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

commit cd8f2706b8df99bce312f9be5b8ae577e8f889c5
Author: Jeevitha <[email protected]>
Date:   Wed Jul 8 06:03:17 2026 -0500

    rs6000: Add TDOmode move patterns
    
    Add support for moving TDOmode (1024-bit Dense Math Register) objects
    between memory, VSX registers, and Dense Math Registers.

Diff:
---
 gcc/config/rs6000/mma.md              | 85 +++++++++++++++++++++++++++++++++++
 gcc/config/rs6000/rs6000-builtin.cc   |  3 +-
 gcc/config/rs6000/rs6000-builtins.def |  6 +++
 gcc/config/rs6000/rs6000.cc           | 23 ++++++----
 4 files changed, 107 insertions(+), 10 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 5f15e3b2e8f6..07274bc54d05 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -92,6 +92,7 @@
    UNSPEC_MMA_XXMFACC
    UNSPEC_MMA_XXMTACC
    UNSPEC_DM_INSERT512
+   UNSPEC_DMF_EXTRACT512
    UNSPEC_DMF_INSERT1024
    UNSPEC_DMF_DMXOR
    UNSPEC_DMF_DMXVI8GERX4
@@ -476,6 +477,90 @@
   "dmxxinstdmr512 %0,%x1,%x2,0\n\tdmxxinstdmr512 %0,%x3,%x4,1"
   [(set_attr "type" "dmf")])
 
+(define_insn "dm_extract512"
+  [(set (match_operand:XO 0 "vsx_register_operand" "=wa")
+       (unspec:XO [(match_operand:TDO 1 "dmr_register_operand" "wD")
+                   (match_operand 2 "const_0_to_1_operand" "n")]
+                  UNSPEC_DMF_EXTRACT512))]
+  "TARGET_DMF"
+  "dmxxextfdmr512 %x0,%Y0,%1,%2"
+  [(set_attr "type" "dmf")])
+
+;; TDO (1024-bit dense-math) move expander.
+(define_expand "movtdo"
+  [(set (match_operand:TDO 0 "nonimmediate_operand")
+       (match_operand:TDO 1 "input_operand"))]
+  "TARGET_DMF"
+{
+  rs6000_emit_move (operands[0], operands[1], TDOmode);
+  DONE;
+})
+
+(define_insn_and_split "*movtdo"
+  [(set (match_operand:TDO 0 "nonimmediate_operand" "=wa,m,wa,wD,wa,wD")
+       (match_operand:TDO 1 "input_operand"         "m,wa,wa,wD,wD,wa"))]
+  "TARGET_DMF
+   && (gpc_reg_operand (operands[0], TDOmode)
+       || gpc_reg_operand (operands[1], TDOmode))"
+{
+  if (which_alternative == 4)
+    return "dmmr %0,%1";
+  else
+    return "#";
+}
+"reload_completed
+ && (!dmr_register_operand (operands[0], TDOmode)
+     || !dmr_register_operand (operands[1], TDOmode))"
+  [(const_int 0)]
+{
+  rtx dst = operands[0];
+  rtx src = operands[1];
+
+  /* Memory-involving moves (alt 0/1) and plain wa<-wa VSX moves (alt 2)
+     both go through the generic multiregister splitter.  */
+  if (!REG_P (dst) || !REG_P (src)
+      || (VSX_REGNO_P (REGNO (dst)) && VSX_REGNO_P (REGNO (src))))
+    {
+      rs6000_split_multireg_move (dst, src);
+      DONE;
+    }
+
+  unsigned dst_regno = REGNO (dst);
+  unsigned src_regno = REGNO (src);
+  bool dst_is_dmr = DMR_REGNO_P (dst_regno);
+  bool src_is_dmr = DMR_REGNO_P (src_regno);
+  bool dst_is_vsx = VSX_REGNO_P (dst_regno);
+  bool src_is_vsx = VSX_REGNO_P (src_regno);
+
+  /* wD <- wD: already a dmmr move, nothing to split.  */
+  if (dst_is_dmr && src_is_dmr)
+    DONE;
+
+  /* wD <- wa  */
+  if (dst_is_dmr && src_is_vsx)
+    {
+      rtx chunk0 = gen_rtx_REG (OOmode, src_regno);
+      rtx chunk1 = gen_rtx_REG (OOmode, src_regno + 2);
+      rtx chunk2 = gen_rtx_REG (OOmode, src_regno + 4);
+      rtx chunk3 = gen_rtx_REG (OOmode, src_regno + 6);
+
+      emit_insn (gen_dm_insert1024 (dst, chunk0, chunk1, chunk2, chunk3));
+      DONE;
+    }
+
+  /* wa <- wD  */
+  if (dst_is_vsx && src_is_dmr)
+    {
+      rtx chunk0 = gen_rtx_REG (XOmode, dst_regno);
+      rtx chunk1 = gen_rtx_REG (XOmode, dst_regno + 4);
+      emit_insn (gen_dm_extract512 (chunk0, src, const0_rtx));
+      emit_insn (gen_dm_extract512 (chunk1, src, const1_rtx));
+      DONE;
+    }
+
+  gcc_unreachable ();
+})
+
 (define_expand "mma_assemble_acc"
   [(match_operand:XO 0 "accumulator_operand")
    (match_operand:V16QI 1 "mma_assemble_input_operand")
diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 1cf6976cb7b4..e16ebb54065b 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -1130,7 +1130,8 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
      already expanded it!  Exceptions: lxvp and stxvp.  */
   if (rs6000_builtin_info[fncode].assoc_bif == RS6000_BIF_NONE
       && fncode != RS6000_BIF_LXVP
-      && fncode != RS6000_BIF_STXVP)
+      && fncode != RS6000_BIF_STXVP
+      && fncode != RS6000_BIF_DMMR)
     return false;
 
   bifdata *bd = &rs6000_builtin_info[fncode];
diff --git a/gcc/config/rs6000/rs6000-builtins.def 
b/gcc/config/rs6000/rs6000-builtins.def
index e4183d847508..dc39ef2e5262 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -4050,6 +4050,12 @@
   dmr1024 __builtin_dmsetdmrz_internal ();
     DMSETDMRZ_INTERNAL dmf_dmsetdmrz {dm}
 
+  void __builtin_dmmr (dmr1024 *, dmr1024 *);
+    DMMR nothing {dm,dmint}
+
+  dmr1024 __builtin_dmmr_internal (dmr1024);
+    DMMR_INTERNAL movtdo {dm}
+
   void __builtin_dmxor (dmr1024 *, dmr1024 *);
     DMXOR nothing {dm,dmint,dmr}
 
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 7017c2d3d43a..09a453efcb39 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -11294,6 +11294,11 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode 
mode)
               (mode == OOmode) ? "__vector_pair" : "__vector_quad");
       break;
 
+    case E_TDOmode:
+      if (CONST_INT_P (operands[1]))
+       error ("%qs is an opaque type, and you cannot set it to constants",
+              "__dmr1024");
+      break;
     case E_SImode:
     case E_DImode:
       /* Use default pattern for address of ELF small data */
@@ -27584,9 +27589,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
   mode = GET_MODE (dst);
   nregs = hard_regno_nregs (reg, mode);
 
-  /* If we have a vector quad register for MMA, and this is a load or store,
-     see if we can use vector paired load/stores.  */
-  if (mode == XOmode && TARGET_MMA
+  /* If we have a vector quad register for MMA or DMR register for Dense Math, 
and
+     this is a load or store, see if we can use vector paired load/stores.  */
+  if ((mode == XOmode || mode == TDOmode) && (TARGET_MMA || TARGET_DMF)
       && (MEM_P (dst) || MEM_P (src)))
     {
       reg_mode = OOmode;
@@ -27594,7 +27599,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
     }
   /* If we have a vector pair/quad mode, split it into two/four separate
      vectors.  */
-  else if (mode == OOmode || mode == XOmode)
+  else if (mode == OOmode || mode == XOmode || mode == TDOmode)
     reg_mode = V1TImode;
   else if (FP_REGNO_P (reg))
     reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode :
@@ -27646,7 +27651,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
      below.  This means the last register gets the first memory
      location.  We also need to be careful of using the right register
      numbers if we are splitting XO to OO.  */
-  if (mode == OOmode || mode == XOmode)
+  if (mode == OOmode || mode == XOmode || mode == TDOmode)
     {
       nregs = hard_regno_nregs (reg, mode);
       int reg_mode_nregs = hard_regno_nregs (reg, reg_mode);
@@ -27784,8 +27789,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
       /* Move register range backwards, if we might have destructive
         overlap.  */
       int i;
-      /* XO/OO are opaque so cannot use subregs. */
-      if (mode == OOmode || mode == XOmode )
+      /* XO/OO/TDO are opaque so cannot use subregs. */
+      if (mode == OOmode || mode == XOmode || mode == TDOmode)
        {
          for (i = nregs - 1; i >= 0; i--)
            {
@@ -27960,8 +27965,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
          if (j == 0 && used_update)
            continue;
 
-         /* XO/OO are opaque so cannot use subregs. */
-         if (mode == OOmode || mode == XOmode )
+         /* XO/OO/TDO are opaque so cannot use subregs. */
+         if (mode == OOmode || mode == XOmode || mode == TDOmode)
            {
              rtx dst_i = gen_rtx_REG (reg_mode, REGNO (dst) + j);
              rtx src_i = gen_rtx_REG (reg_mode, REGNO (src) + j);

Reply via email to