https://gcc.gnu.org/g:eface71c18caea3009ddc1ac624cb41647e9d5c4

commit r15-3041-geface71c18caea3009ddc1ac624cb41647e9d5c4
Author: Andrew Pinski <quic_apin...@quicinc.com>
Date:   Mon Aug 12 17:37:32 2024 -0700

    Match: Add pattern for `(a ? b : 0) | (a ? 0 : c)` into `a ? b : c` 
[PR103660]
    
    This adds a pattern to convert `(a ? b : 0) | (a ? 0 : c)` into `a ? b : c`
    which is simplier. It adds both for cond and vec_cond; even though vec_cond 
is
    handled via a different pattern currently but requires extra steps for 
matching
    so this should be slightly faster.
    
    Also handle it for xor and plus too since those can be handled the same way.
    
    Bootstrapped and tested on x86_64-linux-gnu with no regressions.
    
            PR tree-optimization/103660
    
    gcc/ChangeLog:
    
            * match.pd (`(a ? b : 0) | (a ? 0 : c)`): New pattern.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/tree-ssa/pr103660-4.C: New test.
            * gcc.dg/tree-ssa/pr103660-4.c: New test.
    
    Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>

Diff:
---
 gcc/match.pd                               | 10 +++++++
 gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C | 35 ++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c | 43 ++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index b43ceb6def0..65a3aae2243 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2339,6 +2339,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (if (INTEGRAL_TYPE_P (type))
   (bit_and @0 @1)))
 
+/* Fold `(a ? b : 0) | (a ? 0 : c)` into (a ? b : c).
+    Handle also ^ and + in replacement of `|`. */
+(for cnd (cond vec_cond)
+ (for op (bit_ior bit_xor plus)
+  (simplify
+   (op:c
+    (cnd:s @0 @00 integer_zerop)
+    (cnd:s @0 integer_zerop @01))
+   (cnd @0 @00 @01))))
+
 (for cmp (tcc_comparison)
      icmp (inverted_tcc_comparison)
  /* Fold (((a < b) & c) | ((a >= b) & d)) into (a < b ? c : d) & 1.  */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C 
b/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C
new file mode 100644
index 00000000000..47727f86e24
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr103660-4.C
@@ -0,0 +1,35 @@
+/* PR tree-optimization/103660 */
+/* Vector type version. */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop2-raw -Wno-psabi" } */
+
+typedef int v4si __attribute((__vector_size__(4 * sizeof(int))));
+#define funcs(OP,n)                    \
+v4si min_##n(v4si a, v4si b) {         \
+  v4si t = {0,0,0,0};                  \
+  v4si X = a < b ? a : t;              \
+  v4si Y = a < b ? t : b;              \
+  return (X OP Y);                     \
+}                                      \
+v4si f_##n(v4si a, v4si b,             \
+          v4si c, v4si d) {            \
+  v4si t = {0,0,0,0};                  \
+  v4si X = a < b ? c : t;              \
+  v4si Y = a < b ? t : d;              \
+  return (X OP Y);                     \
+}
+
+
+funcs(|, ior)
+funcs(^, xor)
+funcs(+, plus)
+
+/* min_ior/min_xor/min_plus should produce min<a,b> or `a < b ? a : b` 
depending on if the target
+   supports min on the vector type or not. */
+/* f_ior/f_xor/f_plus should produce (a < b) ? c : d */
+/* { dg-final { scan-tree-dump-not   "bit_xor_expr, "     "forwprop2" } } */
+/* { dg-final { scan-tree-dump-not   "bit_ior_expr, "     "forwprop2" } } */
+/* { dg-final { scan-tree-dump-not   "plus_expr, "        "forwprop2" } } */
+/* { dg-final { scan-tree-dump-not   "bit_ior_expr, "     "forwprop2" } } */
+/* { dg-final { scan-tree-dump-times "(?:lt_expr|min_expr), "        6 
"forwprop2" } } */
+/* { dg-final { scan-tree-dump-times "(?:vec_cond_expr|min_expr), "  6 
"forwprop2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c
new file mode 100644
index 00000000000..26c956fdcec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103660-4.c
@@ -0,0 +1,43 @@
+/* PR tree-optimization/103660 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fgimple -fdump-tree-forwprop1-raw" } */
+
+#define funcs(OP,n)            \
+__GIMPLE()                     \
+int min_##n(int a, int b) {    \
+  _Bool X;                     \
+  int t;                       \
+  int t1;                      \
+  int t2;                      \
+  X = a < b;                   \
+  t1 = X ? a : 0;              \
+  t2 = X ? 0 : b;              \
+  t = t1 OP t2;                        \
+  return t;                    \
+}                              \
+__GIMPLE()                     \
+int f_##n(int a, int b, int c, \
+        int d) {               \
+  _Bool X;                     \
+  int t;                       \
+  int t1;                      \
+  int t2;                      \
+  X = a < b;                   \
+  t1 = X ? c : 0;              \
+  t2 = X ? 0 : d;              \
+  t = t1 OP t2;                        \
+  return t;                    \
+}
+
+funcs(|, ior)
+funcs(^, xor)
+funcs(+, plus)
+
+/* min_i/min_ioror/min_plus should produce min<a,b> */
+/* f_xor/f_ior/f_plus should produce (a < b) ? c : d */
+/* { dg-final { scan-tree-dump-not   "bit_xor_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not   "bit_ior_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not   "plus_expr, "    "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "min_expr, "   3 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "lt_expr, "    3 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "cond_expr, "  3 "forwprop1" } } */

Reply via email to