Hello,

Below patch is bootstrapped and regtested on Power64le-linux-gnu.

Thank You,
Kishan

A future PowerPC processor may provide the Dense Math Facility (DMF),
where accumulators are backed by dedicated Dense Math Registers (DMRs)
instead of aliased VSX/FPR registers. Since DMRs do not require
priming or depriming, xxmtacc/xxmfacc become no-op operations.

Update accumulator assembly to build accumulators in DMRs using DMR
insert operations instead of relying on aliased VSX/FPR registers.
Enable the required OOmode VSX pair patterns under TARGET_DMF and avoid
emitting xxmtacc/xxmfacc during internal accumulator moves and GIMPLE
folding when DMF is enabled.

This patch depends on the following prerequisite patches and can be
upstream after they have been upstreamed:

  rs6000: Add support for Dense Math Facility (DMF) registers
        https://patchwork.ozlabs.org/project/gcc/patch/
        [email protected]/

  rs6000: Add the __dmr1024 opaque type
        https://patchwork.ozlabs.org/project/gcc/patch/
        [email protected]/

  rs6000: Add %wD constraint and predicate for accumulators
        https://patchwork.ozlabs.org/project/gcc/patch/
        [email protected]/

  [PATCH v3] rs6000: Add Dense Math builtin infrastructure
        https://patchwork.ozlabs.org/project/gcc/patch/
        [email protected]/

  [PATCH v2] rs6000: Add Dense Math (DMF/MMA+) built-in/instruction
        support
        https://patchwork.ozlabs.org/project/gcc/patch/
        [email protected]/

2026-07-14  Kishan Parmar  <[email protected]>

gcc/ChangeLog:
        * config/rs6000/mma.md (movoo): Enable for TARGET_DMF.
        (*movoo): Likewise.
        (vsx_assemble_pair): Likewise.
        (*vsx_assemble_pair): Likewise.
        (vsx_disassemble_pair): Likewise.
        (*vsx_disassemble_pair): Likewise.
        (mma_assemble_acc): Use accumulator_operand.
        Build accumulators via DMR insert operations when TARGET_DMF.
        (*mma_assemble_acc): Use accumulator_operand.
        (mma_<acc>): New define_expand treating xxmtacc/xxmfacc as no-ops
        for TARGET_DMF.
        (*mma_<acc>): Restrict to !TARGET_DMF and use accumulator_operand.
        (mma_disassemble_acc): Use accumulator_operand.
        * config/rs6000/rs6000-builtin.cc (rs6000_gimple_fold_mma_builtin): Do
        not emit xxmfacc for DISASSEMBLE_ACC when TARGET_DMF.
        * config/rs6000/rs6000.cc (rs6000_hard_regno_mode_ok_uncached): Allow
        OOmode in VSX register pairs for TARGET_DMF.
        (rs6000_split_multireg_move): Avoid emitting xxmtacc/xxmfacc when
        TARGET_DMF.

gcc/testsuite/ChangeLog:
        * gcc.target/powerpc/future-dmf-xxacc.c: New test.
        * gcc.target/powerpc/future-nodmf-xxacc.c: New test.

---
 gcc/config/rs6000/mma.md                      | 72 +++++++++++++------
 gcc/config/rs6000/rs6000-builtin.cc           |  2 +-
 gcc/config/rs6000/rs6000.cc                   | 37 ++++++----
 .../gcc.target/powerpc/future-dmf-xxacc.c       | 18 +++++
 .../gcc.target/powerpc/future-nodmf-xxacc.c       | 18 +++++
 5 files changed, 111 insertions(+), 36 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/future-dmf-xxacc.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/future-nodmf-xxacc.c

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 7f0c26c6eb5..85c4fcbfc62 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -298,7 +298,7 @@ (define_expand "movoo"
        (match_operand:OO 1 "input_operand"))]
   ""
 {
-  if (TARGET_MMA)
+  if (TARGET_MMA || TARGET_DMF)
     {
       rs6000_emit_move (operands[0], operands[1], OOmode);
       DONE;
@@ -323,7 +323,7 @@ (define_expand "movoo"
 (define_insn_and_split "*movoo"
   [(set (match_operand:OO 0 "nonimmediate_operand" "=wa,ZwO,wa")
        (match_operand:OO 1 "input_operand" "ZwO,wa,wa"))]
-  "TARGET_MMA
+  "(TARGET_MMA || TARGET_DMF)
    && (gpc_reg_operand (operands[0], OOmode)
        || gpc_reg_operand (operands[1], OOmode))"
   "@
@@ -391,7 +391,7 @@ (define_expand "vsx_assemble_pair"
   [(match_operand:OO 0 "vsx_register_operand")
    (match_operand:V16QI 1 "mma_assemble_input_operand")
    (match_operand:V16QI 2 "mma_assemble_input_operand")]
-  "TARGET_MMA"
+  "TARGET_MMA || TARGET_DMF"
 {
   rtx src = gen_rtx_UNSPEC (OOmode,
                            gen_rtvec (2, operands[1], operands[2]),
@@ -408,7 +408,7 @@ (define_insn_and_split "*vsx_assemble_pair"
        (unspec:OO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
                    (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")]
                   UNSPEC_VSX_ASSEMBLE))]
-  "TARGET_MMA"
+  "TARGET_MMA || TARGET_DMF"
   "#"
   "&& reload_completed"
   [(const_int 0)]
@@ -424,7 +424,7 @@ (define_expand "vsx_disassemble_pair"
   [(match_operand:V16QI 0 "mma_disassemble_output_operand")
    (match_operand:OO 1 "vsx_register_operand")
    (match_operand 2 "const_0_to_1_operand")]
-  "TARGET_MMA"
+  "TARGET_MMA || TARGET_DMF"
 {
   rtx src;
   int regoff = INTVAL (operands[2]);
@@ -440,7 +440,7 @@ (define_insn_and_split "*vsx_disassemble_pair"
        (unspec:V16QI [(match_operand:OO 1 "vsx_register_operand" "wa")
                       (match_operand 2 "const_0_to_1_operand")]
                       UNSPEC_MMA_EXTRACT))]
-  "TARGET_MMA
+  "(TARGET_MMA || TARGET_DMF)
    && vsx_register_operand (operands[1], OOmode)"
   "#"
   "&& reload_completed"
@@ -477,18 +477,29 @@ (define_insn "dm_insert1024"
   [(set_attr "type" "dmf")])
 
 (define_expand "mma_assemble_acc"
-  [(match_operand:XO 0 "fpr_reg_operand")
+  [(match_operand:XO 0 "accumulator_operand")
    (match_operand:V16QI 1 "mma_assemble_input_operand")
    (match_operand:V16QI 2 "mma_assemble_input_operand")
    (match_operand:V16QI 3 "mma_assemble_input_operand")
    (match_operand:V16QI 4 "mma_assemble_input_operand")]
-  "TARGET_MMA"
+  "TARGET_MMA || TARGET_DMF"
 {
-  rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode,
-                                    gen_rtvec (4, operands[1], operands[2],
-                                               operands[3], operands[4]),
-                                    UNSPECV_MMA_ASSEMBLE);
-  emit_move_insn (operands[0], src);
+  if (TARGET_DMF)
+    {
+      rtx vp0 = gen_reg_rtx (OOmode);
+      rtx vp1 = gen_reg_rtx (OOmode);
+      emit_insn (gen_vsx_assemble_pair (vp0, operands[1], operands[2]));
+      emit_insn (gen_vsx_assemble_pair (vp1, operands[3], operands[4]));
+      emit_insn (gen_dm_insert512 (operands[0], vp0, vp1, const0_rtx));
+    }
+  else
+    {
+      rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode,
+                                        gen_rtvec (4, operands[1], operands[2],
+                                                   operands[3], operands[4]),
+                                        UNSPECV_MMA_ASSEMBLE);
+      emit_move_insn (operands[0], src);
+    }
   DONE;
 })
 
@@ -496,7 +507,7 @@ (define_expand "mma_assemble_acc"
 ;; as an early clobber so we don't accidentally clobber the input operands.  */
 
 (define_insn_and_split "*mma_assemble_acc"
-  [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
+  [(set (match_operand:XO 0 "accumulator_operand" "=&wD")
        (unspec_volatile:XO
          [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
           (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
@@ -504,7 +515,7 @@ (define_insn_and_split "*mma_assemble_acc"
           (match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")]
          UNSPECV_MMA_ASSEMBLE))]
   "TARGET_MMA
-   && fpr_reg_operand (operands[0], XOmode)"
+   && accumulator_operand (operands[0], XOmode)"
   "#"
   "&& reload_completed"
   [(const_int 0)]
@@ -543,7 +554,7 @@ (define_expand "dmf_build_dmr"
 
 (define_expand "mma_disassemble_acc"
   [(match_operand:V16QI 0 "mma_disassemble_output_operand")
-   (match_operand:XO 1 "fpr_reg_operand")
+   (match_operand:XO 1 "accumulator_operand")
    (match_operand 2 "const_0_to_3_operand")]
   "TARGET_MMA"
 {
@@ -574,15 +585,36 @@ (define_insn_and_split "*mma_disassemble_acc"
   DONE;
 })
 
+;; xxmtacc/xxmfacc prime/deprime an accumulator that lives in 4 adjacent
+;; FPRs -- they reformat that shared FPR/accumulator storage in place.  On
+;; TARGET_DMF, DMRs are a register file entirely separate from the FPRs,
+;; so there is no such format to convert and these are a nop.  This expand
+;; only exists so __builtin_mma_xxmfacc/xxmtacc (which always resolve to
+;; this pattern) correctly do nothing on TARGET_DMF instead of failing
+;; to match any insn.
+(define_expand "mma_<acc>"
+  [(set (match_operand:XO 0 "accumulator_operand")
+       (unspec:XO [(match_operand:XO 1 "accumulator_operand")]
+                  MMA_ACC))]
+  "TARGET_MMA || TARGET_DMF"
+{
+  if (TARGET_DMF)
+    {
+      emit_move_insn (operands[0], operands[1]);
+      DONE;
+    }
+})
+
+
 ;; MMA instructions that do not use their accumulators as an input, still
 ;; must not allow their vector operands to overlap the registers used by
 ;; the accumulator.  We enforce this by marking the output as early clobber.
 
-(define_insn "mma_<acc>"
-  [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
-       (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")]
+(define_insn "*mma_<acc>"
+  [(set (match_operand:XO 0 "accumulator_operand" "=&wD")
+       (unspec:XO [(match_operand:XO 1 "accumulator_operand" "0")]
                    MMA_ACC))]
-  "TARGET_MMA"
+  "TARGET_MMA && !TARGET_DMF"
   "<acc> %A0"
   [(set_attr "type" "mma")])
 
diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 95372aaac71..16cfa87c343 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -1180,7 +1180,7 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
 
       /* If we're disassembling an accumulator into a different type, we need
         to emit a xxmfacc instruction now, since we cannot do it later.  */
-      if (fncode == RS6000_BIF_DISASSEMBLE_ACC)
+      if (fncode == RS6000_BIF_DISASSEMBLE_ACC && !TARGET_DMF)
        {
          new_decl = rs6000_builtin_decls[RS6000_BIF_XXMFACC_INTERNAL];
          new_call = gimple_build_call (new_decl, 1, src);
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 231d07caf20..4e2345644d8 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -1888,7 +1888,7 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
   /* Vector pair modes need even/odd VSX register pairs.  Only allow vector
      registers.  */
   if (mode == OOmode)
-    return (TARGET_MMA && VSX_REGNO_P (regno) && (regno & 1) == 0);
+    return ((TARGET_MMA || TARGET_DMF) && VSX_REGNO_P (regno) && (regno & 1) 
== 0);
 
   /* MMA accumulator modes need FPR registers divisible by 4.
      If TARGET_DMF is true, XOmode value can be held in a DMR register.  */
@@ -27584,8 +27584,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
          unsigned size = GET_MODE_SIZE (reg_mode);
 
          /* If we are reading an accumulator register, we have to
-            deprime it before we can access it.  */
-         if (TARGET_MMA
+            deprime it before we can access it, unless we have dense math
+            registers, which do not need priming/depriming.  */
+         if (TARGET_MMA && !TARGET_DMF
              && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
            emit_insn (gen_mma_xxmfacc (src, src));
 
@@ -27618,8 +27619,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
            }
 
          /* If we are writing an accumulator register, we have to
-            prime it after we've written it.  */
-         if (TARGET_MMA
+            prime it after we've written it, unless we have dense math
+            registers, which do not need priming/depriming.  */
+         if (TARGET_MMA && !TARGET_DMF
              && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
            emit_insn (gen_mma_xxmtacc (dst, dst));
 
@@ -27687,8 +27689,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
            }
 
          /* We are writing an accumulator register, so we have to
-            prime it after we've written it.  */
-         if (GET_MODE (src) == XOmode)
+            prime it after we've written it, unless we have dense math
+            registers, which do not need priming/depriming.  */
+         if (GET_MODE (src) == XOmode && !TARGET_DMF)
            emit_insn (gen_mma_xxmtacc (dst, dst));
 
          return;
@@ -27700,8 +27703,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
   if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
     {
       /* If we are reading an accumulator register, we have to
-        deprime it before we can access it.  */
-      if (TARGET_MMA
+        deprime it before we can access it, unless we have dense math
+        registers, which do not need priming/depriming.  */
+      if (TARGET_MMA && !TARGET_DMF
          && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
        emit_insn (gen_mma_xxmfacc (src, src));
 
@@ -27728,8 +27732,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
        }
 
       /* If we are writing an accumulator register, we have to
-        prime it after we've written it.  */
-      if (TARGET_MMA
+        prime it after we've written it, unless we have dense math
+        registers, which do not need priming/depriming.  */
+      if (TARGET_MMA && !TARGET_DMF
          && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
        emit_insn (gen_mma_xxmtacc (dst, dst));
     }
@@ -27865,8 +27870,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
        }
 
       /* If we are reading an accumulator register, we have to
-        deprime it before we can access it.  */
-      if (TARGET_MMA && REG_P (src)
+        deprime it before we can access it, unless we have dense math
+        registers, which do not need priming/depriming.  */
+      if (TARGET_MMA && !TARGET_DMF && REG_P (src)
          && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src)))
        emit_insn (gen_mma_xxmfacc (src, src));
 
@@ -27897,8 +27903,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
        }
 
       /* If we are writing an accumulator register, we have to
-        prime it after we've written it.  */
-      if (TARGET_MMA && REG_P (dst)
+        prime it after we've written it, unless we have dense math
+        registers, which do not need priming/depriming.  */
+      if (TARGET_MMA && !TARGET_DMF && REG_P (dst)
          && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst)))
        emit_insn (gen_mma_xxmtacc (dst, dst));
 
diff --git a/gcc/testsuite/gcc.target/powerpc/future-dmf-xxacc.c 
b/gcc/testsuite/gcc.target/powerpc/future-dmf-xxacc.c
new file mode 100644
index 00000000000..2242f6693d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/future-dmf-xxacc.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+
+void
+foo (__vector_quad *acc)
+{
+  __builtin_mma_xxmtacc (acc);
+}
+
+void
+bar (__vector_quad *acc)
+{
+  __builtin_mma_xxmfacc (acc);
+}
+
+/* { dg-final { scan-assembler-not {\mxxmtacc\M} } } */
+/* { dg-final { scan-assembler-not {\mxxmfacc\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/future-nodmf-xxacc.c 
b/gcc/testsuite/gcc.target/powerpc/future-nodmf-xxacc.c
new file mode 100644
index 00000000000..a643dc5f638
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/future-nodmf-xxacc.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2 -mno-dense-math" } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+
+void
+foo (__vector_quad *acc)
+{
+  __builtin_mma_xxmtacc (acc);
+}
+
+void
+bar (__vector_quad *acc)
+{
+  __builtin_mma_xxmfacc (acc);
+}
+
+/* { dg-final { scan-assembler {\mxxmtacc\M} } } */
+/* { dg-final { scan-assembler {\mxxmfacc\M} } } */
-- 
2.52.0

Reply via email to