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;
}

Reply via email to