Fix MINUS_EXPR relations.
Flesh out and correct relations for both wrapping and non-wrapping values. gcc/ PR tree-optimization/101254 * range-op.cc (operator_minus::op1_op2_relation_effect): Check for wrapping/non-wrapping when setting the result range. gcc/testsuite * gcc.dg/pr101254.c: New.
This commit is contained in:
parent
604dce2d74
commit
a96d8d67d0
@ -1314,24 +1314,54 @@ operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type,
|
||||
unsigned prec = TYPE_PRECISION (type);
|
||||
signop sgn = TYPE_SIGN (type);
|
||||
|
||||
switch (rel)
|
||||
// == and != produce [0,0] and ~[0,0] regardless of wrapping.
|
||||
if (rel == EQ_EXPR)
|
||||
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec));
|
||||
else if (rel == NE_EXPR)
|
||||
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec),
|
||||
VR_ANTI_RANGE);
|
||||
else if (TYPE_OVERFLOW_WRAPS (type))
|
||||
{
|
||||
// op1 > op2, op1 - op2 can be restricted to [1, max]
|
||||
case GT_EXPR:
|
||||
rel_range = int_range<2> (type, wi::one (prec),
|
||||
wi::max_value (prec, sgn));
|
||||
break;
|
||||
// op1 >= op2, op1 - op2 can be restricted to [0, max]
|
||||
case GE_EXPR:
|
||||
rel_range = int_range<2> (type, wi::zero (prec),
|
||||
wi::max_value (prec, sgn));
|
||||
break;
|
||||
// op1 == op2, op1 - op2 can be restricted to [0, 0]
|
||||
case EQ_EXPR:
|
||||
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec));
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
switch (rel)
|
||||
{
|
||||
// For wrapping signed values and unsigned, if op1 > op2 or
|
||||
// op1 < op2, then op1 - op2 can be restricted to ~[0, 0].
|
||||
case GT_EXPR:
|
||||
case LT_EXPR:
|
||||
rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec),
|
||||
VR_ANTI_RANGE);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (rel)
|
||||
{
|
||||
// op1 > op2, op1 - op2 can be restricted to [1, +INF]
|
||||
case GT_EXPR:
|
||||
rel_range = int_range<2> (type, wi::one (prec),
|
||||
wi::max_value (prec, sgn));
|
||||
break;
|
||||
// op1 >= op2, op1 - op2 can be restricted to [0, +INF]
|
||||
case GE_EXPR:
|
||||
rel_range = int_range<2> (type, wi::zero (prec),
|
||||
wi::max_value (prec, sgn));
|
||||
break;
|
||||
// op1 < op2, op1 - op2 can be restricted to [-INF, -1]
|
||||
case LT_EXPR:
|
||||
rel_range = int_range<2> (type, wi::min_value (prec, sgn),
|
||||
wi::minus_one (prec));
|
||||
break;
|
||||
// op1 <= op2, op1 - op2 can be restricted to [-INF, 0]
|
||||
case LE_EXPR:
|
||||
rel_range = int_range<2> (type, wi::min_value (prec, sgn),
|
||||
wi::zero (prec));
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lhs_range.intersect (rel_range);
|
||||
return true;
|
||||
|
27
gcc/testsuite/gcc.dg/pr101254.c
Normal file
27
gcc/testsuite/gcc.dg/pr101254.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* PR tree-optimization/101254 */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fwrapv" } */
|
||||
|
||||
int
|
||||
foo (long long imin, long long imax)
|
||||
{
|
||||
if (imin > imax)
|
||||
return 0;
|
||||
else if (imax - imin < 0 || (imax - imin) + 1 < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
long long imax = __LONG_LONG_MAX__;
|
||||
long long imin = -imax - 1;
|
||||
if (!foo (-10, 10))
|
||||
__builtin_abort ();
|
||||
if (foo (-10, imax))
|
||||
__builtin_abort ();
|
||||
if (foo (imin, imax))
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user