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. --- gcc/match.pd | 14 ++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/cond-1.c | 17 +++++++++++++++++ .../gcc.dg/tree-ssa/phi-opt-value-1.c | 17 +++++++++++++++++ .../gcc.dg/tree-ssa/phi-opt-value-1a.c | 19 +++++++++++++++++++ .../gcc.dg/tree-ssa/phi-opt-value-2.c | 19 +++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cond-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-1a.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-2.c diff --git a/gcc/match.pd b/gcc/match.pd index 7d651a6582d..22899c51a2f 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 00000000000..478a818b206 --- /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 00000000000..a90de8926c6 --- /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 00000000000..b884f94ddd2 --- /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 00000000000..809ccfe1479 --- /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" } } */ -- 2.39.3