aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Pinski <pinskia@gmail.com>2023-10-26 15:07:53 -0700
committerAndrew Pinski <pinskia@gmail.com>2023-10-30 19:15:25 -0700
commit598fdb5290dcf76ef23e993409e22f1512ff835a (patch)
treee5770c37bbcfcfa4dccc0b7c20d0f79ae336f903 /gcc
parenta5c157b95a4c202ec5b8600f80e7e0c88722e8ad (diff)
downloadgcc-598fdb5290dcf76ef23e993409e22f1512ff835a.zip
gcc-598fdb5290dcf76ef23e993409e22f1512ff835a.tar.gz
gcc-598fdb5290dcf76ef23e993409e22f1512ff835a.tar.bz2
MATCH: first of the value replacement moving from phiopt
This moves a few simple patterns that are done in value replacement in phiopt over to match.pd. Just the simple ones which might show up in other code. This allows some optimizations to happen even without depending on sinking from happening and in some cases where phiopt is not invoked (cond-1.c is an example there). Changes since v1: * v2: Add an extra testcase to showcase improvements at -O1. Bootstrapped and tested on x86_64-linux-gnu with no regressions. gcc/ChangeLog: * match.pd: (`a == 0 ? b : b + a`, `a == 0 ? b : b - a`): New patterns. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/cond-1.c: New test. * gcc.dg/tree-ssa/phi-opt-value-1.c: New test. * gcc.dg/tree-ssa/phi-opt-value-1a.c: New test. * gcc.dg/tree-ssa/phi-opt-value-2.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/match.pd14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cond-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1a.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-2.c19
5 files changed, 86 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 7d651a6..22899c5 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4145,6 +4145,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& (INTEGRAL_TYPE_P (TREE_TYPE (@0))))
(op (mult (convert:type @0) @2) @1))))
+/* ?: Value replacement. */
+/* a == 0 ? b : b + a -> b + a */
+(for op (plus bit_ior bit_xor)
+ (simplify
+ (cond (eq @0 integer_zerop) @1 (op:c@2 @1 @0))
+ @2))
+/* a == 0 ? b : b - a -> b - a */
+/* a == 0 ? b : b ptr+ a -> b ptr+ a */
+/* a == 0 ? b : b shift/rotate a -> b shift/rotate a */
+(for op (lrotate rrotate lshift rshift minus pointer_plus)
+ (simplify
+ (cond (eq @0 integer_zerop) @1 (op@2 @1 @0))
+ @2))
+
/* Simplifications of shift and rotates. */
(for rotate (lrotate rrotate)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cond-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cond-1.c
new file mode 100644
index 0000000..478a818
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cond-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int sub(int a, int b, int c, int d) {
+ int e = (a == 0);
+ int f = !e;
+ c = b;
+ d = b - a ;
+ return ((-e & c) | (-f & d));
+}
+
+/* In the end we end up with `(a == 0) ? (b - a) : b`
+ which then can be optimized to just `(b - a)`. */
+
+/* { dg-final { scan-tree-dump-not "cond_expr," "optimized" } } */
+/* { dg-final { scan-tree-dump-not "eq_expr," "optimized" } } */
+/* { dg-final { scan-tree-dump-times "minus_expr," 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1.c
new file mode 100644
index 0000000..a90de89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Phi-OPT should be able to optimize this without sinking being invoked. */
+/* { dg-options "-O -fdump-tree-phiopt2 -fdump-tree-optimized -fno-tree-sink" } */
+
+char *f(char *a, __SIZE_TYPE__ b) {
+ char *d = a + b;
+ if (b == 0) return a;
+ return d;
+}
+int sub(int a, int b, int c) {
+ int d = a - b;
+ if (b == 0) return a;
+ return d;
+}
+
+/* { dg-final { scan-tree-dump-not "goto" "phiopt2" } } */
+/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1a.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1a.c
new file mode 100644
index 0000000..b884f94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1a.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+[[gnu::const]]
+int constcall(int);
+
+int f(int a, int b)
+{
+ int c = b+a;
+ int t = constcall(c);
+ int d;
+ if (a == 0) d= b; else d= c;
+ return constcall(d) + t;
+}
+
+/* There should be no if statement and 2 calls to call1. */
+/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "constcall " 1 "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-2.c
new file mode 100644
index 0000000..809ccfe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* Phi-OPT should be able to optimize this without sinking being invoked. */
+/* { dg-options "-O -fdump-tree-phiopt2 -fdump-tree-optimized -fno-tree-sink" } */
+
+int f(int a, int b, int c) {
+ int d = a + b;
+ if (c > 5) return c;
+ if (a == 0) return b;
+ return d;
+}
+
+unsigned rot(unsigned x, int n) {
+ const int bits = __CHAR_BIT__ * __SIZEOF_INT__;
+ int t = ((x << n) | (x >> (bits - n)));
+ return (n == 0) ? x : t;
+}
+
+/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt2" } } */
+/* { dg-final { scan-tree-dump-times "goto" 2 "optimized" } } */