Knowing that X << X is non-zero means X is also non-zero. This patch teaches this this to range-ops.
As usual, the big twiddling experts could come up with all sorts of fancy enhancements in this area, and we welcome all patches :). I will push this pending tests. gcc/ChangeLog: PR tree-optimization/102546 * range-op.cc (operator_lshift::op1_range): Handle EQ_EXPR relation. --- gcc/range-op.cc | 19 ++++++++++++++++--- gcc/testsuite/gcc.dg/tree-ssa/pr102546.c | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr102546.c diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 5e37133026d..53f3be4266e 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2075,9 +2075,14 @@ operator_lshift::op1_range (irange &r, tree type, const irange &lhs, const irange &op2, - relation_kind rel ATTRIBUTE_UNUSED) const + relation_kind rel) const { tree shift_amount; + int_range<2> adjust (type); + + if (rel == EQ_EXPR && !lhs.contains_p (build_zero_cst (type))) + adjust.set_nonzero (type); + if (op2.singleton_p (&shift_amount)) { wide_int shift = wi::to_wide (shift_amount); @@ -2086,10 +2091,11 @@ operator_lshift::op1_range (irange &r, if (wi::ge_p (shift, wi::uhwi (TYPE_PRECISION (type), TYPE_PRECISION (op2.type ())), UNSIGNED)) - return false; + goto done; if (shift == 0) { r = lhs; + r.intersect (adjust); return true; } @@ -2126,9 +2132,16 @@ operator_lshift::op1_range (irange &r, if (utype != type) range_cast (r, type); + r.intersect (adjust); return true; } - return false; + + done: + if (adjust.varying_p ()) + return false; + + r = adjust; + return true; } bool diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c new file mode 100644 index 00000000000..4bd98747732 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr102546.c @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-options "-O3 -fdump-tree-optimized" } + +static int a; +static char b, c, d; +void bar(void); +void foo(void); + +int main() { + int f = 0; + for (; f <= 5; f++) { + bar(); + b = b && f; + d = f << f; + if (!(a >= d || f)) + foo(); + c = 1; + for (; c; c = 0) + ; + } +} + +// { dg-final { scan-tree-dump-not "foo" "optimized" } } -- 2.31.1