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