[PR102546] X << Y being non-zero implies X is also non-zero.

This patch teaches this to range-ops.

Tested on x86-64 Linux.

gcc/ChangeLog:

	PR tree-optimization/102546
	* range-op.cc (operator_lshift::op1_range): Teach range-ops that
	X << Y is non-zero implies X is also non-zero.
This commit is contained in:
Aldy Hernandez 2021-10-01 13:05:36 +02:00
parent 257d2890a7
commit 5f9ccf17de
2 changed files with 37 additions and 4 deletions

View file

@ -2078,6 +2078,12 @@ operator_lshift::op1_range (irange &r,
relation_kind rel ATTRIBUTE_UNUSED) const
{
tree shift_amount;
if (!lhs.contains_p (build_zero_cst (type)))
r.set_nonzero (type);
else
r.set_varying (type);
if (op2.singleton_p (&shift_amount))
{
wide_int shift = wi::to_wide (shift_amount);
@ -2089,21 +2095,24 @@ operator_lshift::op1_range (irange &r,
return false;
if (shift == 0)
{
r = lhs;
r.intersect (lhs);
return true;
}
// Work completely in unsigned mode to start.
tree utype = type;
int_range_max tmp_range;
if (TYPE_SIGN (type) == SIGNED)
{
int_range_max tmp = lhs;
utype = unsigned_type_for (type);
range_cast (tmp, utype);
op_rshift.fold_range (r, utype, tmp, op2);
op_rshift.fold_range (tmp_range, utype, tmp, op2);
}
else
op_rshift.fold_range (r, utype, lhs, op2);
op_rshift.fold_range (tmp_range, utype, lhs, op2);
r.intersect (tmp_range);
// Start with ranges which can produce the LHS by right shifting the
// result by the shift amount.
@ -2128,7 +2137,8 @@ operator_lshift::op1_range (irange &r,
range_cast (r, type);
return true;
}
return false;
return !r.varying_p ();
}
bool

View file

@ -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" } }