This is a follow up of
https://gcc.gnu.org/pipermail/gcc-patches/2025-June/687919.html
I had it in my queue but due to other priorities it got postponed

-- >8 --

This patch allows us to use the "splat the sign bit" idiom to
efficiently select between 0 and 2^n-1.
With that we can avoid branches and we got a shorter sequence than
using conditional-zero instructions.

The PLUS 2^n-1 sequence appears particularly for signed division
by a power of two.

gcc/ChangeLog:
        * match.pd
        (A < 0 ? ARG1 OP 2^n-1 : ARG1): New pattern.
        (A < 0 ? ARG0 : ARG0 OP 2^n-1): New pattern.

gcc/testsuite/ChangeLog:
        * gcc.dg/tree-ssa/phi-opt-49.c: New test.
        * gcc.target/sh/pr59533-1.c: Fix expected output.
---
 gcc/match.pd                               | 15 +++++++++
 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-49.c | 36 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/sh/pr59533-1.c    | 12 ++++----
 3 files changed, 57 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-49.c

diff --git a/gcc/match.pd b/gcc/match.pd
index b037b1a2876..f32f53d910e 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -12099,3 +12099,18 @@ and,
  (if (INTEGRAL_TYPE_P (type))
    (with { tree itype = TREE_TYPE (@2); }
     (convert (minus @2 (convert:itype @1))))))
+
+/* Simplify (a < 0) ? ARG1 OP CONST : ARG1 to ((a < 0) ? 0 : CONST) OP ARG1
+   when CONST is a 2^n-1 constant.  */
+(for op (plus bit_ior bit_xor)
+ (simplify
+  (cond (lt @0 integer_zerop@1) (op:c @2 INTEGER_CST@3) @2)
+   (if (wi::exact_log2 (wi::to_wide (@3) + 1) != -1)
+    (op:c (cond (lt @0 @1) @3 { build_zero_cst (type); }) @2))))
+
+/* Same for (a < 0) ? ARG0 : ARG0 OP CONST.  */
+(for op (plus bit_ior bit_xor)
+ (simplify
+  (cond (lt @0 integer_zerop@1) @2 (op:c @2 INTEGER_CST@3))
+   (if (wi::exact_log2 (wi::to_wide (@3) + 1) != -1)
+    (op:c (cond (lt @0 @1) { build_zero_cst (type); }  @3) @2))))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-49.c 
b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-49.c
new file mode 100644
index 00000000000..61d2c8ca615
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-49.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-phiopt4" } */
+
+long f1(long c, long a)
+{
+  return c < 0 ? a : a + 7;
+}
+
+long f2(long c, long a)
+{
+  return c < 0 ? a + 7 : a;
+}
+
+long f3(long c, long a)
+{
+  return c < 0 ? a : a | 15;
+}
+
+long f4(long c, long a)
+{
+  return c < 0 ? a | 15 : a;
+}
+
+long f5(long c, long a)
+{
+  return c < 0 ? a : a ^ 31;
+}
+
+long f6(long c, long a)
+{
+  return c < 0 ? a ^ 31 : a;
+}
+
+/* { dg-final { scan-tree-dump-not "if" "phiopt4" } } */
+/* { dg-final { scan-assembler-not "blt" } } */
+/* { dg-final { scan-assembler-not "bge" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr59533-1.c 
b/gcc/testsuite/gcc.target/sh/pr59533-1.c
index b0469859df5..660cf1024c6 100644
--- a/gcc/testsuite/gcc.target/sh/pr59533-1.c
+++ b/gcc/testsuite/gcc.target/sh/pr59533-1.c
@@ -2,19 +2,19 @@
 /* { dg-do compile }  */
 /* { dg-options "-O1" } */
 
-/* { dg-final { scan-assembler-times "shll" 1 } }  */
-/* { dg-final { scan-assembler-times "movt" 5 } }  */
+/* { dg-final { scan-assembler-times "shll" 5 } }  */
+/* { dg-final { scan-assembler-times "movt" 9 } }  */
 /* { dg-final { scan-assembler-times "rotcl" 1 } }  */
 /* { dg-final { scan-assembler-times "and" 3 } }  */
 /* { dg-final { scan-assembler-times "extu.b" 5 } }  */
 
-/* { dg-final { scan-assembler-times "cmp/pz" 27 { target { ! sh2a } } } }  */
+/* { dg-final { scan-assembler-times "cmp/pz" 23 { target { ! sh2a } } } }  */
 /* { dg-final { scan-assembler-times "addc" 4 { target { ! sh2a } } } }  */
-/* { dg-final { scan-assembler-times "subc" 16 { target { ! sh2a } } } }  */
+/* { dg-final { scan-assembler-times "subc" 12 { target { ! sh2a } } } }  */
 
-/* { dg-final { scan-assembler-times "cmp/pz" 25 { target { sh2a } } } }  */
+/* { dg-final { scan-assembler-times "cmp/pz" 21 { target { sh2a } } } }  */
 /* { dg-final { scan-assembler-times "addc" 6 { target { sh2a } } } }  */
-/* { dg-final { scan-assembler-times "subc" 14 { target { sh2a } } } }  */
+/* { dg-final { scan-assembler-times "subc" 10 { target { sh2a } } } }  */
 /* { dg-final { scan-assembler-times "bld" 2 { target { sh2a } } } }  */
 
 int
-- 
2.53.0

Reply via email to