https://gcc.gnu.org/g:09ce82bc3f1b3538e6872a8990764ffb0d2c1b1a

commit 09ce82bc3f1b3538e6872a8990764ffb0d2c1b1a
Author: Kishan Parmar <[email protected]>
Date:   Wed Jul 15 14:03:29 2026 +0530

    rs6000: Build DMF accumulators using DMR insert operations
    
    A future PowerPC processor may provide the Dense Math Facility (DMF),
    where accumulators are backed by dedicated Dense Math Registers (DMRs).
    Update accumulator assembly to build accumulators in DMRs using the new
    DMR insert operations rather than xxmtacc/xxmfacc.
    
    Enable the required OOmode VSX pair patterns under TARGET_DMF,
    use accumulator operands for MMA accumulator assembly and disassembly,
    and avoid emitting xxmtacc/xxmfacc during internal accumulator moves
    and GIMPLE folding when DMF is enabled. Add DMF instruction type and
    ISA attributes for instruction scheduling and enablement.
    
    2026-07-15  Kishan Parmar  <[email protected]>
    
    gcc/ChangeLog:
            * config/rs6000/mma.md (UNSPEC_DMF_INSERT512): New unspec.
            (UNSPEC_DMF_INSERT1024): Likewise.
            (movoo): Enable for TARGET_DMF.
            (*movoo): Likewise.
            (vsx_assemble_pair): Likewise.
            (*vsx_assemble_pair): Likewise.
            (vsx_disassemble_pair): Likewise.
            (*vsx_disassemble_pair): Likewise.
            (dm_insert512): New insn.
            (dm_insert1024): 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.
            * config/rs6000/rs6000.md (type): Add dmf type.
            (isa): Add mma and dmf ISA attributes.
            (enabled): Add mma and dmf enable conditions.
    
    gcc/testsuite/ChangeLog:
            * gcc.target/powerpc/future-dmf-xxacc.c: New test.
            * gcc.target/powerpc/future-nodmf-xxacc.c: New test.

Diff:
---
 gcc/config/rs6000/mma.md                           | 97 +++++++++++++++++-----
 gcc/config/rs6000/predicates.md                    | 19 +++++
 gcc/config/rs6000/rs6000-builtin.cc                |  2 +-
 gcc/config/rs6000/rs6000.cc                        | 37 +++++----
 gcc/config/rs6000/rs6000.md                        | 12 ++-
 .../gcc.target/powerpc/future-dmf-xxacc.c          | 18 ++++
 .../gcc.target/powerpc/future-nodmf-xxacc.c        | 18 ++++
 7 files changed, 165 insertions(+), 38 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 1103f1fc0375..a5baa4c94e00 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -91,6 +91,8 @@
    UNSPEC_MMA_XVI8GER4SPP
    UNSPEC_MMA_XXMFACC
    UNSPEC_MMA_XXMTACC
+   UNSPEC_DMF_INSERT512
+   UNSPEC_DMF_INSERT1024
   ])
 
 (define_c_enum "unspecv"
@@ -270,7 +272,7 @@
        (match_operand:OO 1 "input_operand"))]
   ""
 {
-  if (TARGET_MMA)
+  if (TARGET_MMA || TARGET_DMF)
     {
       rs6000_emit_move (operands[0], operands[1], OOmode);
       DONE;
@@ -295,7 +297,7 @@
 (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))"
   "@
@@ -363,7 +365,7 @@
   [(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]),
@@ -380,7 +382,7 @@
        (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)]
@@ -396,7 +398,7 @@
   [(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]);
@@ -412,7 +414,7 @@
        (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"
@@ -425,19 +427,53 @@
   DONE;
 })
 
+(define_insn "dmf_insert512"
+  [(set (match_operand:XO 0 "dmr_register_operand" "=wD")
+       (unspec:XO [(match_operand:OO 1 "vsx_register_operand" "wa")
+                   (match_operand:OO 2 "vsx_register_operand" "wa")
+                   (match_operand 3 "const_0_to_1_operand")]
+                  UNSPEC_DMF_INSERT512))]
+  "TARGET_DMF"
+  "dmxxinstdmr512 %0,%x1,%x2,%3"
+  [(set_attr "type" "dmf")])
+
+;; Move from VSX registers to DMR registers via two insert 512 bit
+;; instructions.
+(define_insn "dmf_insert1024"
+  [(set (match_operand:TDO 0 "dmr_register_operand" "=wD")
+       (unspec:TDO [(match_operand:OO 1 "vsx_register_operand" "wa")
+                    (match_operand:OO 2 "vsx_register_operand" "wa")
+                    (match_operand:OO 3 "vsx_register_operand" "wa")
+                    (match_operand:OO 4 "vsx_register_operand" "wa")]
+                   UNSPEC_DMF_INSERT1024))]
+  "TARGET_DMF"
+  "dmxxinstdmr512 %0,%x1,%x2,0\n\tdmxxinstdmr512 %0,%x3,%x4,1"
+  [(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_dmf_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;
 })
 
@@ -445,7 +481,7 @@
 ;; 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")
@@ -453,7 +489,7 @@
           (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)]
@@ -468,7 +504,7 @@
 
 (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"
 {
@@ -499,15 +535,36 @@
   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/predicates.md b/gcc/config/rs6000/predicates.md
index 9d4928b04642..a6ec04f5922d 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -163,6 +163,22 @@
   return VINT_REGNO_P (REGNO (op));
 })
 
+;; Return 1 if op is a dense math register
+(define_predicate "dmr_register_operand"
+  (match_operand 0 "register_operand")
+{
+  if (!TARGET_DMF)
+    return 0;
+
+  if (!REG_P (op))
+    return 0;
+
+  if (!HARD_REGISTER_P (op))
+    return 1;
+
+  return DMR_REGNO_P (REGNO (op));
+})
+
 ;; Return 1 if op is an accumulator.  On power10/11 systems, the accumulators
 ;; overlap with the FPRs. If TARGET_DMF is true, it will be Dense math 
register.
 (define_predicate "accumulator_operand"
@@ -387,6 +403,9 @@
   if (TARGET_VSX && VSX_REGNO_P (REGNO (op)))
     return 1;
 
+  if (TARGET_DMF && DMR_REGNO_P (REGNO (op)))
+    return 1;
+
   return INT_REGNO_P (REGNO (op)) || FP_REGNO_P (REGNO (op));
 })
 
diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 2d35d5861246..806505220f29 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -1163,7 +1163,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 8f8672192159..f92ab14ac4a3 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.  */
@@ -27603,8 +27603,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));
 
@@ -27637,8 +27638,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));
 
@@ -27706,8 +27708,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;
@@ -27719,8 +27722,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));
 
@@ -27747,8 +27751,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));
     }
@@ -27884,8 +27889,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));
 
@@ -27916,8 +27922,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/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 86d79d922586..e06dcec65889 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -223,7 +223,7 @@
    vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,
    vecfloat,vecfdiv,vecdouble,mtvsr,mfvsr,crypto,
    veclogical,veccmpfx,vecexts,vecmove,
-   htm,htmsimple,dfp,mma,
+   htm,htmsimple,dfp,mma,dmf,
    fused_arith_logical,
    fused_cmp_isel,
    fused_carry,
@@ -371,7 +371,7 @@
   (const (symbol_ref "(enum attr_cpu) rs6000_tune")))
 
 ;; The ISA we implement.
-(define_attr "isa" "any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10,future"
+(define_attr "isa" 
"any,p5,p6,p7,p7v,p8,p8v,p9,p9v,p9kf,p9tf,p10,future,mma,dmf"
   (const_string "any"))
 
 ;; Is this alternative enabled for the current CPU/ISA/etc.?
@@ -427,6 +427,14 @@
      (and (eq_attr "isa" "future")
           (match_test "TARGET_FUTURE"))
      (const_int 1)
+
+     (and (eq_attr "isa" "mma")
+         (match_test "TARGET_MMA"))
+     (const_int 1)
+
+     (and (eq_attr "isa" "dmf")
+         (match_test "TARGET_DMF"))
+     (const_int 1)
     ] (const_int 0)))
 
 ;; If this instruction is microcoded on the CELL processor
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 000000000000..2242f6693d02
--- /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 000000000000..a643dc5f6380
--- /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} } } */

Reply via email to