https://gcc.gnu.org/g:348f29b29493a37e2bc9c38b032a37f7e5f0b8a8

commit 348f29b29493a37e2bc9c38b032a37f7e5f0b8a8
Author: Surya Kumari Jangala <[email protected]>
Date:   Sat Jul 4 00:12:27 2026 -0500

    [rs6000] Add support for Dense Math Facility (DMF) registers
    
    This patch makes the necessary changes in the rs6000 backend to
    support Dense Math Facility (DMF) registers which may be present
    in a future Power processor. The DMF registers have a size of 1024 bits.
    
    2026-07-04  Surya Kumari Jangala  <[email protected]>

Diff:
---
 gcc/config/rs6000/rs6000.cc | 76 ++++++++++++++++++++++++++++++++++++++++++---
 gcc/config/rs6000/rs6000.h  | 36 +++++++++++++++++----
 gcc/config/rs6000/rs6000.md |  2 ++
 3 files changed, 103 insertions(+), 11 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 513adf02913f..e656470abfff 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -292,7 +292,8 @@ enum rs6000_reg_type {
   ALTIVEC_REG_TYPE,
   FPR_REG_TYPE,
   SPR_REG_TYPE,
-  CR_REG_TYPE
+  CR_REG_TYPE,
+  DMR_REG_TYPE
 };
 
 /* Map register class to register type.  */
@@ -313,6 +314,7 @@ enum rs6000_reload_reg_type {
   RELOAD_REG_GPR,                      /* General purpose registers.  */
   RELOAD_REG_FPR,                      /* Traditional floating point regs.  */
   RELOAD_REG_VMX,                      /* Altivec (VMX) registers.  */
+  RELOAD_REG_DMR,
   RELOAD_REG_ANY,                      /* OR of GPR, FPR, Altivec masks.  */
   N_RELOAD_REG
 };
@@ -321,7 +323,7 @@ enum rs6000_reload_reg_type {
    into real registers, and skip the ANY class, which is just an OR of the
    bits.  */
 #define FIRST_RELOAD_REG_CLASS RELOAD_REG_GPR
-#define LAST_RELOAD_REG_CLASS  RELOAD_REG_VMX
+#define LAST_RELOAD_REG_CLASS  RELOAD_REG_DMR
 
 /* Map reload register type to a register in the register class.  */
 struct reload_reg_map_type {
@@ -333,6 +335,7 @@ static const struct reload_reg_map_type 
reload_reg_map[N_RELOAD_REG] = {
   { "Gpr",     FIRST_GPR_REGNO },      /* RELOAD_REG_GPR.  */
   { "Fpr",     FIRST_FPR_REGNO },      /* RELOAD_REG_FPR.  */
   { "VMX",     FIRST_ALTIVEC_REGNO },  /* RELOAD_REG_VMX.  */
+  { "DMR",      FIRST_DMR_REGNO },      /* RELOAD_REG_DMR.  */
   { "Any",     -1 },                   /* RELOAD_REG_ANY.  */
 };
 
@@ -1226,6 +1229,8 @@ char rs6000_reg_names[][8] =
       "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",
   /* vrsave vscr sfp */
       "vrsave", "vscr", "sfp",
+  /* DMRs */
+      "0", "1", "2", "3", "4", "5", "6", "7",
 };
 
 #ifdef TARGET_REGNAMES
@@ -1252,6 +1257,8 @@ static const char alt_reg_names[][8] =
   "%cr0",  "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
   /* vrsave vscr sfp */
   "vrsave", "vscr", "sfp",
+  /* DMRs */
+  "%dm0", "%dm1", "%dm2", "%dm3", "%dm4", "%dm5", "%dm6", "%dm7",
 };
 #endif
 
@@ -1842,6 +1849,9 @@ rs6000_hard_regno_nregs_internal (int regno, machine_mode 
mode)
   else if (ALTIVEC_REGNO_P (regno))
     reg_size = UNITS_PER_ALTIVEC_WORD;
 
+  else if (DMR_REGNO_P (regno))
+    reg_size = UNITS_PER_DMR_WORD;
+
   else
     reg_size = UNITS_PER_WORD;
 
@@ -1858,6 +1868,17 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
   if (COMPLEX_MODE_P (mode))
     mode = GET_MODE_INNER (mode);
 
+  if (mode == TDOmode)
+    {
+      if (TARGET_DMF)
+       return (DMR_REGNO_P (regno)
+               || (VSX_REGNO_P (regno)
+                   && VSX_REGNO_P (last_regno)
+                   && (regno & 1) == 0));
+      else
+       return 0;
+    }
+
   /* Vector pair modes need even/odd VSX register pairs.  Only allow vector
      registers.  */
   if (mode == OOmode)
@@ -1865,7 +1886,12 @@ rs6000_hard_regno_mode_ok_uncached (int regno, 
machine_mode mode)
 
   /* MMA accumulator modes need FPR registers divisible by 4.  */
   if (mode == XOmode)
-    return (TARGET_MMA && FP_REGNO_P (regno) && (regno & 3) == 0);
+    return ((TARGET_DMF && DMR_REGNO_P (regno))
+            || (TARGET_MMA && FP_REGNO_P (regno) && (regno & 3) == 0));
+
+  /* No other types other than XOmode or TDOmode can go in DMRs.  */
+  if (DMR_REGNO_P (regno))
+    return 0;
 
   /* PTImode can only go in GPRs.  Quad word memory operations require even/odd
      register combinations, and use PTImode where we need to deal with quad
@@ -2273,6 +2299,7 @@ rs6000_debug_reg_global (void)
     V4DFmode,
     OOmode,
     XOmode,
+    TDOmode,
     CCmode,
     CCUNSmode,
     CCEQmode,
@@ -2308,6 +2335,7 @@ rs6000_debug_reg_global (void)
   rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO,
                          LAST_ALTIVEC_REGNO,
                          "vs");
+  rs6000_debug_reg_print (FIRST_DMR_REGNO, LAST_DMR_REGNO, "dmr");
   rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr");
   rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr");
   rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr");
@@ -2634,6 +2662,20 @@ rs6000_setup_reg_addr_masks (void)
          addr_mask = 0;
          reg = reload_reg_map[rc].reg;
 
+         if (rc == RELOAD_REG_DMR)
+           {
+             if (TARGET_DMF && (m2 == XOmode || m2 == TDOmode))
+               {
+                 addr_mask = RELOAD_REG_VALID;
+                         reg_addr[m].addr_mask[rc] = addr_mask;
+                 any_addr_mask |= addr_mask;
+               }
+             else
+               reg_addr[m].addr_mask[rc] = 0;
+
+             continue;
+           }
+
          /* Can mode values go in the GPR/FPR/Altivec registers?  */
          if (reg >= 0 && rs6000_hard_regno_mode_ok_p[m][reg])
            {
@@ -2731,8 +2773,9 @@ rs6000_setup_reg_addr_masks (void)
             instructions are enabled, otherwise they can only do offset loads
             since it will be broken into two vector moves.  Vector quads can
             only do offset loads.  */
-         else if ((addr_mask != 0) && TARGET_MMA
-                  && (m2 == OOmode || m2 == XOmode))
+         else if ((addr_mask != 0)
+                  && ((TARGET_MMA && (m2 == OOmode || m2 == XOmode))
+                       || (TARGET_DMF && (m2 == TDOmode))))
            {
              addr_mask |= RELOAD_REG_OFFSET;
              if (rc == RELOAD_REG_FPR || rc == RELOAD_REG_VMX)
@@ -2780,6 +2823,9 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   for (r = FIRST_ALTIVEC_REGNO; r <= LAST_ALTIVEC_REGNO; ++r)
     rs6000_regno_regclass[r] = ALTIVEC_REGS;
 
+  for (r = FIRST_DMR_REGNO; r <= LAST_DMR_REGNO; ++r)
+    rs6000_regno_regclass[r] = DMR_REGS;
+
   rs6000_regno_regclass[CR0_REGNO] = CR0_REGS;
   for (r = CR1_REGNO; r <= CR7_REGNO; ++r)
     rs6000_regno_regclass[r] = CR_REGS;
@@ -2808,6 +2854,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   reg_class_to_reg_type[(int)LINK_OR_CTR_REGS] = SPR_REG_TYPE;
   reg_class_to_reg_type[(int)CR_REGS] = CR_REG_TYPE;
   reg_class_to_reg_type[(int)CR0_REGS] = CR_REG_TYPE;
+  reg_class_to_reg_type[(int)DMR_REGS] = DMR_REG_TYPE;
 
   if (TARGET_VSX)
     {
@@ -3191,6 +3238,9 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
       else if (c == FLOAT_REGS)
        reg_size = UNITS_PER_FP_WORD;
 
+      else if (c == DMR_REGS)
+       reg_size = UNITS_PER_DMR_WORD;
+
       else
        reg_size = UNITS_PER_WORD;
 
@@ -12356,6 +12406,9 @@ rs6000_secondary_reload_memory (rtx addr,
   const char *type = NULL;
   const char *fail_msg = NULL;
 
+  if (rclass == DMR_REGS)
+    return 2;
+
   if (GPR_REG_CLASS_P (rclass))
     addr_mask = reg_addr[mode].addr_mask[RELOAD_REG_GPR];
 
@@ -12698,6 +12751,11 @@ rs6000_secondary_reload_simple_move (enum 
rs6000_reg_type to_type,
               || (to_type == SPR_REG_TYPE && from_type == GPR_REG_TYPE)))
     return true;
 
+  if (TARGET_DMF && (mode == XOmode || mode == TDOmode)
+      && ((to_type == DMR_REG_TYPE && from_type == VSX_REG_TYPE)
+          || (to_type == VSX_REG_TYPE && from_type == DMR_REG_TYPE)))
+    return true;
+
   return false;
 }
 
@@ -13392,6 +13450,9 @@ rs6000_preferred_reload_class (rtx x, enum reg_class 
rclass)
   machine_mode mode = GET_MODE (x);
   bool is_constant = CONSTANT_P (x);
 
+  if (rclass == DMR_REGS)
+    return NO_REGS;
+
   /* If a mode can't go in FPR/ALTIVEC/VSX registers, don't return a preferred
      reload class for it.  */
   if ((rclass == ALTIVEC_REGS || rclass == VSX_REGS)
@@ -24115,6 +24176,8 @@ rs6000_compute_pressure_classes (enum reg_class 
*pressure_classes)
       if (TARGET_HARD_FLOAT)
        pressure_classes[n++] = FLOAT_REGS;
     }
+  if (TARGET_DMF)
+    pressure_classes[n++] = DMR_REGS;
   pressure_classes[n++] = CR_REGS;
   pressure_classes[n++] = SPECIAL_REGS;
 
@@ -24280,6 +24343,9 @@ rs6000_debugger_regno (unsigned int regno, unsigned int 
format)
   if (regno == 64)
     return 64;
 
+  if (DMR_REGNO_P (regno))
+    return regno - FIRST_DMR_REGNO + 112;
+
   gcc_unreachable ();
 }
 
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index f3ea2e9659a4..0ecb15d021f5 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -657,6 +657,7 @@ extern unsigned char rs6000_recip_bits[];
 #define UNITS_PER_FP_WORD 8
 #define UNITS_PER_ALTIVEC_WORD 16
 #define UNITS_PER_VSX_WORD 16
+#define UNITS_PER_DMR_WORD 128
 
 /* Type used for ptrdiff_t, as a string used in a declaration.  */
 #define PTRDIFF_TYPE "int"
@@ -770,7 +771,7 @@ enum data_align { align_abi, align_opt, align_both };
    Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame
    pointer, which is eventually eliminated in favor of SP or FP.  */
 
-#define FIRST_PSEUDO_REGISTER 111
+#define FIRST_PSEUDO_REGISTER 119
 
 /* Use standard DWARF numbering for DWARF debugging information.  */
 #define DEBUGGER_REGNO(REGNO) rs6000_debugger_regno ((REGNO), 0)
@@ -807,7 +808,9 @@ enum data_align { align_abi, align_opt, align_both };
    /* cr0..cr7 */                                 \
    0, 0, 0, 0, 0, 0, 0, 0,                        \
    /* vrsave vscr sfp */                          \
-   1, 1, 1                                        \
+   1, 1, 1,                                       \
+   /* DMRs */                                     \
+   0, 0, 0, 0, 0, 0, 0, 0                         \
 }
 
 /* Like `CALL_USED_REGISTERS' except this macro doesn't require that
@@ -831,7 +834,9 @@ enum data_align { align_abi, align_opt, align_both };
    /* cr0..cr7 */                                 \
    1, 1, 0, 0, 0, 1, 1, 1,                        \
    /* vrsave vscr sfp */                          \
-   0, 0, 0                                        \
+   0, 0, 0,                                       \
+   /* DMRs */                                     \
+   1, 1, 1, 1, 1, 1, 1, 1                         \
 }
 
 #define TOTAL_ALTIVEC_REGS     (LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1)
@@ -868,6 +873,7 @@ enum data_align { align_abi, align_opt, align_both };
        v2              (not saved; incoming vector arg reg; return value)
        v19 - v14       (not saved or used for anything)
        v31 - v20       (saved; order given to save least number)
+       dmr0 - dmr7     (not saved)
        vrsave, vscr    (fixed)
        sfp             (fixed)
 */
@@ -910,6 +916,8 @@ enum data_align { align_abi, align_opt, align_both };
    66,                                                         \
    83, 82, 81, 80, 79, 78,                                     \
    95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84,             \
+   /* DMRs */                                                  \
+   111, 112, 113, 114, 115, 116, 117, 118,                     \
    108, 109,                                                   \
    110                                                         \
 }
@@ -936,6 +944,9 @@ enum data_align { align_abi, align_opt, align_both };
 /* True if register is a VSX register.  */
 #define VSX_REGNO_P(N) (FP_REGNO_P (N) || ALTIVEC_REGNO_P (N))
 
+/* True if register is a DMR register.  */
+#define DMR_REGNO_P(N) ((N) >= FIRST_DMR_REGNO && (N) <= LAST_DMR_REGNO)
+
 /* Alternate name for any vector register supporting floating point, no matter
    which instruction set(s) are available.  */
 #define VFLOAT_REGNO_P(N) \
@@ -975,7 +986,7 @@ enum data_align { align_abi, align_opt, align_both };
 /* Modes that are not vectors, but require vector alignment.  Treat these like
    vectors in terms of loads and stores.  */
 #define VECTOR_ALIGNMENT_P(MODE)                                       \
-  (FLOAT128_VECTOR_P (MODE) || (MODE) == OOmode || (MODE) == XOmode)
+  (FLOAT128_VECTOR_P (MODE) || (MODE) == OOmode || (MODE) == XOmode || (MODE) 
== TDOmode)
 
 #define ALTIVEC_VECTOR_MODE(MODE)                                      \
   ((MODE) == V16QImode                                                 \
@@ -1138,6 +1149,8 @@ enum reg_class
   { 0x00000000, 0x00000000, 0xffffffff, 0x00000000 },                  \
   /* VSX_REGS.  */                                                     \
   { 0x00000000, 0xffffffff, 0xffffffff, 0x00000000 },                  \
+  /* DMR_REGS.  */                                                     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x007f8000 },                  \
   /* VRSAVE_REGS.  */                                                  \
   { 0x00000000, 0x00000000, 0x00000000, 0x00001000 },                  \
   /* VSCR_REGS.  */                                                    \
@@ -1165,7 +1178,7 @@ enum reg_class
   /* CA_REGS.  */                                                      \
   { 0x00000000, 0x00000000, 0x00000000, 0x00000004 },                  \
   /* ALL_REGS.  */                                                     \
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0x00007fff }                   \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0x007fffff }                   \
 }
 
 /* The same information, inverted:
@@ -2066,7 +2079,16 @@ extern char rs6000_reg_names[][8];       /* register 
names (0 vs. %r0).  */
   &rs6000_reg_names[108][0],   /* vrsave  */                           \
   &rs6000_reg_names[109][0],   /* vscr  */                             \
                                                                        \
-  &rs6000_reg_names[110][0]    /* sfp  */                              \
+  &rs6000_reg_names[110][0],   /* sfp  */                              \
+                                                                       \
+  &rs6000_reg_names[111][0],   /* dmr0  */                             \
+  &rs6000_reg_names[112][0],   /* dmr1  */                             \
+  &rs6000_reg_names[113][0],   /* dmr2  */                             \
+  &rs6000_reg_names[114][0],   /* dmr3  */                             \
+  &rs6000_reg_names[115][0],   /* dmr4  */                             \
+  &rs6000_reg_names[116][0],   /* dmr5  */                             \
+  &rs6000_reg_names[117][0],   /* dmr6  */                             \
+  &rs6000_reg_names[118][0]    /* dmr7  */                             \
 }
 
 /* Table of additional register names to use in user input.  */
@@ -2120,6 +2142,8 @@ extern char rs6000_reg_names[][8];        /* register 
names (0 vs. %r0).  */
   {"vs52", 84}, {"vs53", 85}, {"vs54", 86}, {"vs55", 87},      \
   {"vs56", 88}, {"vs57", 89}, {"vs58", 90}, {"vs59", 91},      \
   {"vs60", 92}, {"vs61", 93}, {"vs62", 94}, {"vs63", 95},      \
+  {"dmr0", 111}, {"dmr1", 112}, {"dmr2", 113}, {"dmr3", 114},   \
+  {"dmr4", 115}, {"dmr5", 116}, {"dmr6", 117}, {"dmr7", 118},   \
 }
 
 /* This is how to output an element of a case-vector that is relative.  */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 4ec3d3da8a99..86d79d922586 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -51,6 +51,8 @@
    (VRSAVE_REGNO               108)
    (VSCR_REGNO                 109)
    (FRAME_POINTER_REGNUM       110)
+   (FIRST_DMR_REGNO            111)
+   (LAST_DMR_REGNO             118)
   ])
 
 ;;

Reply via email to