[gcc(refs/vendors/ibm/heads/gcc-17-future)] PR target/120528 -- Simplify zero extend from memory to VSX register on power10

Michael Meissner via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:8744edd0c432d1f40ac241698261624d16f81aab

commit 8744edd0c432d1f40ac241698261624d16f81aab
Author: Michael Meissner <[email protected]>
Date:   Wed Jul 1 11:04:03 2026 -0400

    PR target/120528 -- Simplify zero extend from memory to VSX register on power10
    
    Previously GCC would zero extend a DImode value in memory to a TImode
    target in a vector register by firt zero extending the DImode value
    into a GPR TImode register pair, and then do a MTVSRDD to move this
    value to a VSX register.
    
    For example, consider the following code:
    
            #ifndef TYPE
            #define TYPE unsigned long long
            #endif
    
            void
            mem_to_vsx (TYPE *p, __uint128_t *q)
            {
              /* lxvrdx 0,0,3
                 stxv 0,0(4)  */
    
              __uint128_t x = *p;
              __asm__ (" # %x0" : "+wa" (x));
              *q = x;
            }
    
    It currently generates the following code on power10:
    
            mem_to_vsx:
                    ld 10,0(3)
                    li 11,0
                    mtvsrdd 0,11,10
            #APP
                     # 0
            #NO_APP
                    stxv 0,0(4)
                    blr
    
    Instead it could generate:
    
            mem_to_vsx:
                    lxvrdx 0,0,3
            #APP
                     # 0
            #NO_APP
                    stxv 0,0(4)
                    blr
    
    The lxvr{b,h,w,d}x instructions were added in power10, and they load up
    a vector register with a byte, half-word, word, or double-word value in
    the right most bits, and fill the remaining bits to 0.  I noticed this
    code when working on PR target/108958 (which I just posted the patch).
    
    This patch creates a peephole2 to catch this case, and it eliminates
    creating the TImode variable.  Instead it just does the LXVR{B,H,W,D}x
    instruction directly.
    
    I have built GCC with the patches in this patch set applied on both
    little and big endian PowerPC systems and there were no regressions.
    Can I apply this patch to GCC 16?
    
    2026-07-01  Michael Meissner  <[email protected]>
    
    gcc/
    
            PR target/120528
            * config/rs6000/rs6000.md (zero_extend??ti2 peephole2): Add a
            peephole2 to simplify zero extending a QI/HI/SI/DImode value in
            memory to a TImode target in a vector register to use the
            LXVR{B,H,W,D}X instructins.
    
    gcc/testsuite/
    
            PR target/120528
            * gcc.target/powerpc/pr120528.c: New test.

Diff:
---
 gcc/config/rs6000/rs6000.md | 69 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index d75dbc923685..b125f40185eb 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1370,6 +1370,75 @@
     }
 })
 
+;; On power10, optimize zero extending a QI/HI/SI/DImode value from memory that
+;; is going to a vector register target by generating a LXVR{B,H,W,D}X
+;; instruction without creating the TImode value in a GPR and using MTVSRDD to
+;; move it to the vector register.
+(define_peephole2
+  [(set (match_operand:DI 0 "int_reg_operand")
+	(match_operand:DI 1 "memory_operand"))
+   (set (match_operand:DI 2 "base_reg_operand")
+	(const_int 0))
+   (set (match_operand:TI 3 "vsx_register_operand")
+	(match_operand:TI 4 "int_reg_operand"))]
+  "TARGET_POWER10 && TARGET_POWERPC64
+   && (reg_or_subregno (operands[0])
+       == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN)
+   && (reg_or_subregno (operands[2])
+       == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN)
+   && peep2_reg_dead_p (3, operands[4])
+   && (REG_P (XEXP (operands[1], 0))
+       || SUBREG_P (XEXP (operands[1], 0))
+       || GET_CODE (XEXP (operands[1], 0)) == PLUS)"
+  [(set (match_dup 3)
+	(zero_extend:TI (match_dup 5)))]
+{
+  rtx mem = operands[1];
+  rtx addr = XEXP (mem, 0);
+
+  if (indexed_or_indirect_address (addr, DImode))
+    operands[5] = mem;
+  else
+    {
+      rtx op2 = operands[2];
+      emit_insn (gen_rtx_SET (op2, addr));
+      operands[5] = change_address (mem, DImode, op2);
+    }
+})
+
+(define_peephole2
+  [(set (match_operand:DI 0 "int_reg_operand")
+	(zero_extend:DI
+	 (match_operand:QHSI 1 "memory_operand")))
+   (set (match_operand:DI 2 "base_reg_operand")
+	(const_int 0))
+   (set (match_operand:TI 3 "vsx_register_operand")
+	(match_operand:TI 4 "int_reg_operand"))]
+  "TARGET_POWER10 && TARGET_POWERPC64
+   && (reg_or_subregno (operands[0])
+       == reg_or_subregno (operands[4]) + !!WORDS_BIG_ENDIAN)
+   && (reg_or_subregno (operands[2])
+       == reg_or_subregno (operands[4]) + !WORDS_BIG_ENDIAN)
+   && peep2_reg_dead_p (3, operands[4])
+   && (REG_P (XEXP (operands[1], 0))
+       || SUBREG_P (XEXP (operands[1], 0))
+       || GET_CODE (XEXP (operands[1], 0)) == PLUS)"
+  [(set (match_dup 3)
+	(zero_extend:TI (match_dup 5)))]
+{
+  rtx mem = operands[1];
+  rtx addr = XEXP (mem, 0);
+
+  if (indexed_or_indirect_address (addr, DImode))
+    operands[5] = mem;
+  else
+    {
+      rtx op2 = operands[2];
+      emit_insn (gen_rtx_SET (op2, addr));
+      operands[5] = change_address (mem, DImode, op2);
+    }
+})
+
 (define_insn "zero_extendsi<mode>2"
   [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,d,wa,wa,r,wa")
 	(zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,?Z,?Z,r,wa,wa")))]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.