Add a pattern to handle cases where we have an OP that is
unconditionally being applied in the result of a gcond. In this case we
can apply OP to both legs of the conditional. E.g:

t = b ? 10 : 20;
t = t + 20;

becomes just:

t = b ? 30 : 40

        PR 122608

gcc/ChangeLog:

        * match.pd (`(c ? a : b) op d -> c ? (a op d) : (b op d)`): New
          pattern.

gcc/testsuite/ChangeLog:

        * gcc.target/i386/pr110701.c: the pattern added is now folding
          an XOR into the ifcond, and the assembler isn't emitting an
          'andl' anymore.
        * gcc.dg/torture/pr122608.c: New test.

Signed-off-by: Daniel Barboza <[email protected]>
---
 gcc/match.pd                             | 10 +++
 gcc/testsuite/gcc.dg/torture/pr122608.c  | 83 ++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr110701.c |  2 +-
 3 files changed, 94 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr122608.c

diff --git a/gcc/match.pd b/gcc/match.pd
index f164ec59100..9650bbeada7 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6274,6 +6274,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
               && !expand_vec_cond_expr_p (TREE_TYPE (@1), TREE_TYPE (@0)))))
    (vec_cond @0 (op! @3 @1) (op! @3 @2)))))
 
+
+/* Non-vector comutative sink of binary ops to branches:
+   (c ? a : b) op d  -->  c ? (a op d) : (b op d)  */
+(for op (plus minus mult bit_and bit_ior bit_xor
+        lshift rshift rdiv trunc_div ceil_div floor_div round_div exact_div
+        trunc_mod ceil_mod floor_mod round_mod min max)
+ (simplify
+  (op (cond:s @0 @1 @2) @3)
+  (cond @0 (op! @1 @3) (op! @2 @3))))
+
 #if GIMPLE
 (match (nop_atomic_bit_test_and_p @0 @1 @4)
  (bit_and (convert?@4 (ATOMIC_FETCH_OR_XOR_N @2 INTEGER_CST@0 @3))
diff --git a/gcc/testsuite/gcc.dg/torture/pr122608.c 
b/gcc/testsuite/gcc.dg/torture/pr122608.c
new file mode 100644
index 00000000000..f8058149e5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122608.c
@@ -0,0 +1,83 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -fdump-tree-optimized" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-fno-fat-lto-objects" } { "" } } */
+
+#define F(OP,NAME) \
+ __GIMPLE int NAME##_test(int a) \
+ { _Bool b; \
+   int t; \
+   b = a > 0; \
+   t = b ? 20 : 40; \
+   t = t OP 11; \
+   return t; }
+
+F (+, plus)
+F (-, minus)
+F (*, mult)
+F (|, bit_ior)
+F (^, bit_xor)
+F (/, div)
+F (%, mod)
+F (<<, lshift)
+
+__GIMPLE int test_and(int a)
+{
+  _Bool b;
+  int t;
+  b = a > 0;
+  t = b ? 1 : 3;
+  t = t & 3;
+  return t;
+}
+
+__GIMPLE int test_rshift(int a)
+{
+  _Bool b;
+  int t;
+  b = a > 0;
+  t = b ? 2 : 8;
+  t = t >> 1;
+  return t;
+}
+
+static int min (int a, int b)
+{
+  return a < b ? a : b;
+}
+
+static int max (int a, int b)
+{
+  return a > b ? a : b;
+}
+
+__GIMPLE int min_test(int a)
+{
+  _Bool b;
+  int t;
+  b = a > 0;
+  t = b ? 2 : 4;
+  t = min (t, 3);
+  return t;
+}
+
+__GIMPLE int max_test(int a)
+{
+  _Bool b;
+  int t;
+  b = a > 0;
+  t = b ? 2 : 4;
+  t = max (t, 3);
+  return t;
+}
+
+/* { dg-final { scan-tree-dump-times " \\+ " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " \\* " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " \\| " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " \\^ " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " & " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " % " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " << " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " >> " 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MIN_EXPR" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MAX_EXPR" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr110701.c 
b/gcc/testsuite/gcc.target/i386/pr110701.c
index 3f2cea5c3df..8cd179c3b15 100644
--- a/gcc/testsuite/gcc.target/i386/pr110701.c
+++ b/gcc/testsuite/gcc.target/i386/pr110701.c
@@ -8,5 +8,5 @@ void foo() {
   *c = d(340, b >= 0) ^ 3;
 }
 
-/* { dg-final { scan-assembler "andl\[ \\t]\\\$340," } } */
+/* { dg-final { scan-assembler-not "andl\[ \\t]\\\$340," } } */
 /* { dg-final { scan-assembler-not "andw\[ \\t]\\\$340," } } */
-- 
2.43.0

Reply via email to