This in this PR we have missed optimization where we miss that, `1 >> x` and `(1 >> x) ^ 1` can't be equal. There are a few ways of optimizing this, the easiest and simpliest is to simplify `1 >> x` into just `x == 0` as those are equivalant (if we ignore out of range values for x). we already have an optimization for `(1 >> X) !=/== 0` so the only difference here is we don't need the `!=/== 0` part to do the transformation.
So this removes the `(1 >> X) !=/== 0` transformation and just adds a simplfied `1 >> x` -> `x == 0` one. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/102705 gcc/ChangeLog: * match.pd (`(1 >> X) != 0`): Remove pattern. (`1 >> x`): New pattern. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr105832-2.c: Update testcase. * gcc.dg/tree-ssa/pr96669-1.c: Likewise. * gcc.dg/tree-ssa/pr102705-1.c: New test. * gcc.dg/tree-ssa/pr102705-2.c: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/match.pd | 16 ++++++++-------- gcc/testsuite/gcc.dg/tree-ssa/pr102705-1.c | 17 +++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr102705-2.c | 17 +++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr105832-2.c | 8 ++++---- gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c | 2 +- 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102705-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102705-2.c diff --git a/gcc/match.pd b/gcc/match.pd index 17193087498..b6cbb851897 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4998,6 +4998,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op @0 { build_int_cst (TREE_TYPE (@1), prec - 1); }))) (op @0 { build_int_cst (TREE_TYPE (@1), low); }))))))) +/* Fold `1 >> a` into `a == 0` for scalar integral types. */ +(simplify + (rshift integer_onep @2) + (if (INTEGRAL_TYPE_P (type)) + (convert (eq:boolean_type_node @2 { build_zero_cst (TREE_TYPE (@2)); })))) /* Simplify (CST << x) & 1 to 0 if CST is even or to x == 0 if it is odd. */ (simplify @@ -5009,7 +5014,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Simplify ((C << x) & D) != 0 where C and D are power of two constants, either to false if D is smaller (unsigned comparison) than C, or to x == log2 (D) - log2 (C). Similarly for right shifts. - Note for `(1 >> x)`, the & 1 has been removed so matching that seperately. */ + Note `(1 >> x)`, the & 1 has been removed so but will have been + already folded above. */ (for cmp (ne eq) icmp (eq ne) (simplify @@ -5026,13 +5032,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) int c2 = wi::clz (wi::to_wide (@2)); } (if (c1 > c2) { constant_boolean_node (cmp == NE_EXPR ? false : true, type); } - (icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); }))))) - /* `(1 >> X) != 0` -> `X == 0` */ - /* `(1 >> X) == 0` -> `X != 0` */ - (simplify - (cmp (rshift integer_onep@1 @0) integer_zerop) - (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))) - (icmp @0 { build_zero_cst (TREE_TYPE (@0)); })))) + (icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); })))))) /* (CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1) (CST1 << A) != CST2 -> A != ctz (CST2) - ctz (CST1) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102705-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102705-1.c new file mode 100644 index 00000000000..60b53c03472 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102705-1.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/102705 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ +/* { dg-final { scan-tree-dump "a == 0" "original" } } */ +/* { dg-final { scan-tree-dump "b == 0" "original" } } */ + +int +f1 (int a) +{ + return (1 >> a); +} + +int +f2 (int b) +{ + return ((1 >> b) & 1); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102705-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102705-2.c new file mode 100644 index 00000000000..a12606c7856 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102705-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* PR tree-optimization/102705 */ +/* { dg-final { scan-tree-dump-not "foo " "optimized" } } */ + + +void foo(void); +static int b; +static char c; +static short a(short d, short e) { return e == 0 || d && e == 1 ? 0 : d % e; } +int main() { + b = c = b >= 2 ? 0 : 1 >> b; + short f = a(0 >= 0 ^ c, 5); + if (f == c) + foo(); + a(0, 9); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr105832-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr105832-2.c index 2d2a33e2755..ebcc76bda68 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr105832-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr105832-2.c @@ -1,10 +1,10 @@ /* PR tree-optimization/105832 */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-original" } */ -/* { dg-final { scan-tree-dump "return a == 0;" "original" } } */ -/* { dg-final { scan-tree-dump "return b == 0;" "original" } } */ -/* { dg-final { scan-tree-dump "return c != 0;" "original" } } */ -/* { dg-final { scan-tree-dump "return d != 0;" "original" } } */ +/* { dg-final { scan-tree-dump "a == 0" "original" } } */ +/* { dg-final { scan-tree-dump "b == 0" "original" } } */ +/* { dg-final { scan-tree-dump "c != 0" "original" } } */ +/* { dg-final { scan-tree-dump "d != 0" "original" } } */ int f1 (int a) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c index 6a95a6ba8c1..56932330218 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr96669-1.c @@ -5,7 +5,7 @@ /* { dg-final { scan-tree-dump "return 1;" "original" } } */ /* { dg-final { scan-tree-dump "return c == 3;" "original" } } */ /* { dg-final { scan-tree-dump "return d != 1;" "original" } } */ -/* { dg-final { scan-tree-dump "return e != 0;" "original" } } */ +/* { dg-final { scan-tree-dump "e != 0" "original" } } */ /* { dg-final { scan-tree-dump "return f == 1;" "original" } } */ /* { dg-final { scan-tree-dump "return 0;" "original" } } */ /* { dg-final { scan-tree-dump "return h != 1;" "original" } } */ -- 2.43.0