Hi,

Following is version 4 of the  patch proposed for master to fix PR119702. 
This patch has been bootstrapped and regtested on powerpc64le-linux.
Kindly review the patch.

Thanks and regards,
Avinash Jayakar

Changes from v3:
        1. Add author information before changelog.
        2. Right placement of PR target/119702.
        3. Added new test to check multiply by 2 generates vadd insn.
Changes from v2:
        1. Indentation fixes in the commit message
        2. define_insn has the name *altivec_vsl<VI_char>_const_1
        3. Iterate starting from 0 for checking vector constant = 1 and 
        fixed source code formatting for the for loop.
        4. Removed unused macro in pr119702-1.c test file
Changes from v1:
        1. Use define_insn instead of define_expand to recognize left
        shift by constant 1 and generate add instruction.
        2. Updated test cases to cover integer types from byte, half-
        word, word and double word.

rs6000: Use vector addition when left shifting by 1[PR119702]

Whenever a vector of integers is left shifted by a constant value 1, 
gcc generates the following code for powerpc64le target:
        vspltisw 0,1
        vsld 2,2,0
Instead the following code can be generated which is more efficient:
        vaddudm 2,2,2
This patch adds a pattern in  altivec.md to recognize a vector left shift by
a constant value, and generates an add instruction if constant is 1.

Added the pattern in altivec.md to recognize a vector left shift by a
constant value, and generate add instructions if constant is 1.
Added a predicate in predicates.md to recognize if the rtl node is a
uniform constant vector with value 1.

Two test files have been added
        1. Check if left shift by 1 is converted to vadd instructions 
        for byte, half-word, word, and double-word.
        2. Check the same but for multiply by 2.

2025-09-12  Avinash Jayakar  <avina...@linux.ibm.com>

gcc/ChangeLog:
        PR target/119702
        * config/rs6000/altivec.md (*altivec_vsl<VI_char>_const_1): recognize
        << 1 and replace with vadd insn.
        * config/rs6000/predicates.md (vector_constant_1): predicate to check
        vector constant of all 1.

gcc/testsuite/ChangeLog:
        PR target/119702
        * gcc.target/powerpc/pr119702-1.c: New test
        * gcc.target/powerpc/pr119702-2.c: New test
---
 gcc/config/rs6000/altivec.md                  |  8 +++
 gcc/config/rs6000/predicates.md               | 11 ++++
 gcc/testsuite/gcc.target/powerpc/pr119702-1.c | 53 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/pr119702-2.c | 53 +++++++++++++++++++
 4 files changed, 125 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr119702-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr119702-2.c

diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 7edc288a656..7621f5c4f0a 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -2107,6 +2107,14 @@
   "vsrv %0,%1,%2"
   [(set_attr "type" "vecsimple")])
 
+(define_insn "*altivec_vsl<VI_char>_const_1"
+  [(set (match_operand:VI2 0 "register_operand" "=v")
+       (ashift:VI2 (match_operand:VI2 1 "register_operand" "v")
+                     (match_operand:VI2 2 "vector_constant_1" "")))]
+  "<VI_unit>"
+  "vaddu<VI_char>m %0,%1,%1"
+)
+
 (define_insn "*altivec_vsl<VI_char>"
   [(set (match_operand:VI2 0 "register_operand" "=v")
         (ashift:VI2 (match_operand:VI2 1 "register_operand" "v")
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 647e89afb6a..7a9c7df84ad 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -924,6 +924,17 @@
     }
 })
 
+(define_predicate "vector_constant_1"
+  (match_code "const_vector")
+{
+  unsigned nunits = GET_MODE_NUNITS (mode), i;
+  for (i = 0; i < nunits; i++) 
+    if (INTVAL (CONST_VECTOR_ELT(op, i)) != 1)
+      return 0;
+  
+  return 1;
+})
+
 ;; Return 1 if operand is 0.0.
 (define_predicate "zero_fp_constant"
   (and (match_code "const_double")
diff --git a/gcc/testsuite/gcc.target/powerpc/pr119702-1.c 
b/gcc/testsuite/gcc.target/powerpc/pr119702-1.c
new file mode 100644
index 00000000000..3f292cde9a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr119702-1.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+
+#include <inttypes.h>
+
+void lshift1_64(uint64_t *a) {
+  a[0] <<= 1;
+  a[1] <<= 1;
+}
+
+void lshift1_32(unsigned int *a) {
+  a[0] <<= 1;
+  a[1] <<= 1;
+  a[2] <<= 1;
+  a[3] <<= 1;
+}
+
+void lshift1_16(uint16_t *a) {
+  a[0] <<= 1;
+  a[1] <<= 1;
+  a[2] <<= 1;
+  a[3] <<= 1;
+  a[4] <<= 1;
+  a[5] <<= 1;
+  a[6] <<= 1;
+  a[7] <<= 1;
+}
+
+void lshift1_8(uint8_t *a) {
+  a[0] <<= 1;
+  a[1] <<= 1;
+  a[2] <<= 1;
+  a[3] <<= 1;
+  a[4] <<= 1;
+  a[5] <<= 1;
+  a[6] <<= 1;
+  a[7] <<= 1;
+  a[8] <<= 1;
+  a[9] <<= 1;
+  a[10] <<= 1;
+  a[11] <<= 1;
+  a[12] <<= 1;
+  a[13] <<= 1;
+  a[14] <<= 1;
+  a[15] <<= 1;
+}
+
+
+/* { dg-final { scan-assembler-times {\mvaddudm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvadduwm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvadduhm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvaddubm\M} 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr119702-2.c 
b/gcc/testsuite/gcc.target/powerpc/pr119702-2.c
new file mode 100644
index 00000000000..f1c1b8b86e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr119702-2.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+
+#include <inttypes.h>
+
+void lshift1_64(uint64_t *a) {
+  a[0] *= 2;
+  a[1] *= 2;
+}
+
+void lshift1_32(unsigned int *a) {
+  a[0] *= 2;
+  a[1] *= 2;
+  a[2] *= 2;
+  a[3] *= 2;
+}
+
+void lshift1_16(uint16_t *a) {
+  a[0] *= 2;
+  a[1] *= 2;
+  a[2] *= 2;
+  a[3] *= 2;
+  a[4] *= 2;
+  a[5] *= 2;
+  a[6] *= 2;
+  a[7] *= 2;
+}
+
+void lshift1_8(uint8_t *a) {
+  a[0] *= 2;
+  a[1] *= 2;
+  a[2] *= 2;
+  a[3] *= 2;
+  a[4] *= 2;
+  a[5] *= 2;
+  a[6] *= 2;
+  a[7] *= 2;
+  a[8] *= 2;
+  a[9] *= 2;
+  a[10] *= 2;
+  a[11] *= 2;
+  a[12] *= 2;
+  a[13] *= 2;
+  a[14] *= 2;
+  a[15] *= 2;
+}
+
+
+/* { dg-final { scan-assembler-times {\mvaddudm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvadduwm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvadduhm\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mvaddubm\M} 1 } } */
+
-- 
2.51.0

Reply via email to