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

commit d60c7baae662f45d9f846b65f4906980472ea31e
Author: Kishan Parmar <[email protected]>
Date:   Mon Jun 1 18:42:57 2026 +0530

    rs6000: Fix VSX register numbering in dmxxextfdmr512 instruction output
    
    The dmxxextfdmr512 instruction extracts 512 bits from a DMR register and
    stores the result into four consecutive VSX registers. The instruction
    requires two VSX register numbers (vs[n] and vs[n+2]) as operands.
    
    The output templates were missing the %x modifier, which caused two issues:
    1. When Altivec registers were allocated during reload.
    2. The %Y modifier was adding 2 to register number by default, without 
checking
       if the VSX register numbering was used.
    
    This caused subsequent instructions to misinterpret which registers
    dmxxextfdmr512 stored into. When Altivec register v28 was allocated:
    - dmxxextfdmr512 instruction: Stored result into vs28, vs29, vs30, vs31.
    - Subsequent stxv instructions: Tried to access v28+32 (vs60,vs61,vs62,vs63)
      thinking they were accessing Altivec registers, but the offset calculation
      was wrong because the pattern didn't use VSX numbering.
    
    The actual assembly showed:
      dmxxextfdmr512 vs28,vs30,dm1,0  # Wrong: should be vs60,vs62
      stxv vs60,96(r1)                # Accessing wrong registers
    
    The fix ensures VSX register numbering is used consistently:
    1. Add %x modifier to patterns to force vsx register allocation (v28 + 32).
    2. Modify %Y to convert to VSX numbering before adding offset, so the
       second register number is also correct (vs60+2 → vs62, not v28+2 → v30).
    
    With the fix, the correct assembly is generated:
      dmxxextfdmr512 vs60,vs62,dm1,0  # Correct VSX register numbers
      stxv vs60,96(r1)                # Accessing correct registers

Diff:
---
 gcc/config/rs6000/mma.md                          |  6 +++---
 gcc/config/rs6000/rs6000.cc                       | 25 ++++++++++++++++++++++-
 gcc/testsuite/gcc.target/powerpc/dm-double-test.c |  2 +-
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index b5fe4cf3188f..98e4b4aa74c3 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -481,9 +481,9 @@
    #
    #
    #
-   dmxxinstdmr512 %0,%1,%Y1,0
+   dmxxinstdmr512 %0,%x1,%Y1,0
    dmmr %0,%1
-   dmxxextfdmr512 %0,%Y0,%1,0"
+   dmxxextfdmr512 %x0,%Y0,%1,0"
   "&& reload_completed
    && !dmr_operand (operands[0], XOmode)
    && !dmr_operand (operands[1], XOmode)"
@@ -1016,7 +1016,7 @@
                    (match_operand 2 "const_0_to_1_operand" "n")]
                   UNSPEC_DM_EXTRACT512))]
   "TARGET_DENSE_MATH"
-  "dmxxextfdmr512 %0,%Y0,%1,%2"
+  "dmxxextfdmr512 %x0,%Y0,%1,%2"
   [(set_attr "type" "mma")])
 
 ;; Reload DMR registers from memory
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 4930966d1476..7f7bb28f28be 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -14704,7 +14704,30 @@ print_operand (FILE *file, rtx x, int code)
     case 'Y':
       /* Like 'L', for third word of TImode/PTImode  */
       if (REG_P (x))
-       fputs (reg_names[REGNO (x) + 2], file);
+        {
+          /* Check if this is a VSX register being used in a VSX context.
+             If so, convert to VSX numbering and add 2.  */
+          if (VSX_REGNO_P (REGNO (x)))
+            {
+              int reg = REGNO (x);
+              int vsx_reg = (FP_REGNO_P (reg)
+                             ? reg - 32
+                             : reg - FIRST_ALTIVEC_REGNO + 32);
+              vsx_reg += 2;  /* Add 2 to VSX register number */
+
+#ifdef TARGET_REGNAMES
+              if (TARGET_REGNAMES)
+                fprintf (file, "%%vs%d", vsx_reg);
+              else
+#endif
+                fprintf (file, "%d", vsx_reg);
+            }
+          else
+            {
+              /* Non-VSX register: use original behavior (add 2 to hardware 
reg) */
+              fputs (reg_names[REGNO (x) + 2], file);
+            }
+        }
       else if (MEM_P (x))
        {
          machine_mode mode = GET_MODE (x);
diff --git a/gcc/testsuite/gcc.target/powerpc/dm-double-test.c 
b/gcc/testsuite/gcc.target/powerpc/dm-double-test.c
index 66c197795856..eaa01426c780 100644
--- a/gcc/testsuite/gcc.target/powerpc/dm-double-test.c
+++ b/gcc/testsuite/gcc.target/powerpc/dm-double-test.c
@@ -188,7 +188,7 @@ main (int argc, char *argv[])
   return ret;
 }
 
-/* { dg-final { scan-assembler {\mdmsetdmrz\M}      } } */
+/* { dg-final { scan-assembler {\mdmsetaccz\M}      } } */
 /* { dg-final { scan-assembler {\mdmxvf64gerpp\M}   } } */
 /* { dg-final { scan-assembler {\mdmxxextfdmr512\M} } } */

Reply via email to