https://gcc.gnu.org/g:b796f38e114537a5f2d973ba9b1920c1711c38e8

commit b796f38e114537a5f2d973ba9b1920c1711c38e8
Author: Michael Meissner <[email protected]>
Date:   Sat Jul 18 02:39:04 2026 -0400

    DMF patch 6
    
    Hi All,
    
    The following patch has been bootstrapped and regtested on 
powerpc64le-linux.
    
    Changes from v1:
            - Removed duplicated code from the previous patch so this patch
            applies cleanly.
    
    Thank You,
    Kishan
    
    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.
    
    Add DMR register predicate support, 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/
    
            * 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/predicates.md (dmr_register_operand): New predicate.
            (gpc_reg_operand): Accept DMR registers.
            * 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/
    
            * 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                        | 35 ++++----
 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, 164 insertions(+), 37 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 1103f1fc0375..1fadc5cd8869 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 "dm_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 "dm_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_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;
 })
 
@@ -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 cea668fb163c..4ecbbe43ba00 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 a4b7762b0239..929cf8f5a1bc 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -27667,8 +27667,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));
 
@@ -27701,8 +27702,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));
 
@@ -27770,8 +27772,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;
@@ -27783,8 +27786,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));
 
@@ -27811,8 +27815,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));
     }
@@ -27948,8 +27953,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));
 
@@ -27980,8 +27986,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