Hi,
this is a regression on the mainline, but the underlying issue is present on
the branches too, and similar to PR tree-optimization/79666, but this time for
the invariant part instead of the symbolic one.
In extract_range_from_binary_expr_1, when the invariant part of the symbolic
computation overflows, we drop to varying:
/* If we have overflow for the constant part and the resulting
range will be symbolic, drop to VR_VARYING. */
if ((min_ovf && sym_min_op0 != sym_min_op1)
|| (max_ovf && sym_max_op0 != sym_max_op1))
{
set_value_range_to_varying (vr);
return;
}
But we fail to compute the overflow when the operation is MINUS_EXPR and the
first operand is 0, i.e. we can silently negate INT_MIN and fail to bail out.
Fixed by computing overflow in this case too. Tested on x86_64-suse-linux, OK
for mainline and 6 branch?
2017-04-19 Eric Botcazou <ebotca...@adacore.com>
PR tree-optimization/80426
* tree-vrp.c (extract_range_from_binary_expr_1): For an additive
operation on symbolic operands, also compute the overflow for the
invariant part when the operation degenerates into a negation.
2017-04-19 Eric Botcazou <ebotca...@adacore.com>
* gcc.c-torture/execute/20170419-1.c: New test.
--
Eric Botcazou
Index: tree-vrp.c
===================================================================
--- tree-vrp.c (revision 246960)
+++ tree-vrp.c (working copy)
@@ -2461,7 +2461,19 @@ extract_range_from_binary_expr_1 (value_
else if (min_op0)
wmin = min_op0;
else if (min_op1)
- wmin = minus_p ? wi::neg (min_op1) : min_op1;
+ {
+ if (minus_p)
+ {
+ wmin = wi::neg (min_op1);
+
+ /* Check for overflow. */
+ if (wi::cmp (0, min_op1, sgn)
+ != wi::cmp (wmin, 0, sgn))
+ min_ovf = wi::cmp (0, min_op1, sgn);
+ }
+ else
+ wmin = min_op1;
+ }
else
wmin = wi::shwi (0, prec);
@@ -2489,7 +2501,19 @@ extract_range_from_binary_expr_1 (value_
else if (max_op0)
wmax = max_op0;
else if (max_op1)
- wmax = minus_p ? wi::neg (max_op1) : max_op1;
+ {
+ if (minus_p)
+ {
+ wmax = wi::neg (max_op1);
+
+ /* Check for overflow. */
+ if (wi::cmp (0, max_op1, sgn)
+ != wi::cmp (wmax, 0, sgn))
+ max_ovf = wi::cmp (0, max_op1, sgn);
+ }
+ else
+ wmax = max_op1;
+ }
else
wmax = wi::shwi (0, prec);
/* PR tree-optimization/80426 */
/* Testcase by <ishiura-compi...@ml.kwansei.ac.jp> */
#define INT_MAX 0x7fffffff
#define INT_MIN (-INT_MAX-1)
int x;
int main (void)
{
volatile int a = 0;
volatile int b = -INT_MAX;
int j;
for(j = 0; j < 18; j += 1) {
x = ( (a == 0) != (b - (int)(INT_MIN) ) );
}
if (x != 0)
__builtin_abort ();
return 0;
}