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) ]) ;;
