aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <quic_apinski@quicinc.com>2024-04-30 14:45:26 -0700
committerAndrew Pinski <quic_apinski@quicinc.com>2024-05-07 14:41:15 -0700
commite472527c7b45d23e8dfd0fb767a6e663b4bc136e (patch)
tree5926e0837501251d372a701b24c9aeefac966c33
parent9f14f1978260148d4d6208dfd73df1858e623758 (diff)
downloadgcc-e472527c7b45d23e8dfd0fb767a6e663b4bc136e.zip
gcc-e472527c7b45d23e8dfd0fb767a6e663b4bc136e.tar.gz
gcc-e472527c7b45d23e8dfd0fb767a6e663b4bc136e.tar.bz2
MATCH: Add some more value_replacement simplifications (a != 0 ? expr : 0) to match
This adds a few more of what is currently done in phiopt's value_replacement to match. I noticed this when I was hooking up phiopt's value_replacement code to use match and disabling the old code. But this can be done independently from the hooking up phiopt's value_replacement as phiopt is already hooked up for simplified versions already. /* a != 0 ? a / b : 0 -> a / b iff b is nonzero. */ /* a != 0 ? a * b : 0 -> a * b */ /* a != 0 ? a & b : 0 -> a & b */ We prefer the `cond ? a : 0` forms to allow optimization of `a * cond` which uses that form. Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/114894 gcc/ChangeLog: * match.pd (`a != 0 ? a / b : 0`): New pattern. (`a != 0 ? a * b : 0`): New pattern. (`a != 0 ? a & b : 0`): New pattern. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/phi-opt-value-5.c: New test. Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
-rw-r--r--gcc/match.pd18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c39
2 files changed, 57 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index d401e75..03a03c3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4290,6 +4290,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(cond (eq @0 integer_all_onesp) @1 (op:c@2 @1 @0))
@2))
+/* a != 0 ? a / b : 0 -> a / b iff b is nonzero. */
+(for op (trunc_div ceil_div floor_div round_div exact_div)
+ (simplify
+ (cond (ne @0 integer_zerop) (op@2 @3 @1) integer_zerop )
+ (if (bitwise_equal_p (@0, @3)
+ && tree_expr_nonzero_p (@1))
+ @2)))
+
+/* Note we prefer the != case here
+ as (a != 0) * (a * b) will generate that version. */
+/* a != 0 ? a * b : 0 -> a * b */
+/* a != 0 ? a & b : 0 -> a & b */
+(for op (mult bit_and)
+ (simplify
+ (cond (ne @0 integer_zerop) (op:c@2 @1 @3) integer_zerop)
+ (if (bitwise_equal_p (@0, @3))
+ @2)))
+
/* Simplifications of shift and rotates. */
(for rotate (lrotate rrotate)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c
new file mode 100644
index 0000000..8062eb1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* PR treee-optimization/114894 */
+/* Phi-OPT should be able to optimize these without sinking being invoked. */
+/* { dg-options "-O -fdump-tree-phiopt2 -fdump-tree-phiopt3 -fdump-tree-optimized -fno-tree-sink" } */
+
+int fmul1(int a, int b)
+{
+ int c = a * b;
+ if (a != 0)
+ return c;
+ return 0;
+}
+
+
+int fand1(int a, int b)
+{
+ int c = a & b;
+ if (a != 0)
+ return c;
+ return 0;
+}
+
+
+void g(int);
+
+int fdiv1(int a, int b)
+{
+ int d = b|1;
+ g(d);
+ int c = a / d;
+ return a != 0 ? c : 0;
+}
+
+/* fdiv1 requires until later than phiopt2 to be able to detect that
+ d is non-zero. to be able to remove the conditional. */
+/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt2" } } */
+/* { dg-final { scan-tree-dump-not "goto" "phiopt3" } } */
+/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
+