diff mbox

Fix PR79666

Message ID alpine.LSU.2.20.1702221049060.8538@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Feb. 22, 2017, 9:53 a.m. UTC
I am testing the following patch to fix PR79666 - we may not create
a symbolic range with expressions that may introduce (not already present)
undefined overflow.

With a new predicate like operand_not_min_p we can possibly improve
this for symbolic ops with a useful range, but I'm not sure we'd
ever arrive with non-VARYING ops here.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Eric - you added these improvements so you might want to double-check
effects on Ada code (and see if the above suggestion is worth
the effort).

Thanks,
Richard.

2017-02-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/79666
	* tree-vrp.c (extract_range_from_binary_expr_1): Make sure
	to not symbolically negate if that may introduce undefined
	overflow.

	* gcc.dg/torture/pr79666.c: New testcase.

Comments

Eric Botcazou Feb. 22, 2017, 11:15 a.m. UTC | #1
> Eric - you added these improvements so you might want to double-check
> effects on Ada code (and see if the above suggestion is worth
> the effort).

I think that all the relevant testcases are in the gnat.dg testsuite.
diff mbox

Patch

Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 245646)
+++ gcc/tree-vrp.c	(working copy)
@@ -2631,8 +2631,17 @@  extract_range_from_binary_expr_1 (value_
 	    min = build_symbolic_expr (expr_type, sym_min_op0,
 				       neg_min_op0, min);
 	  else if (sym_min_op1)
-	    min = build_symbolic_expr (expr_type, sym_min_op1,
-				       neg_min_op1 ^ minus_p, min);
+	    {
+	      /* We may not negate if that might introduce
+		 undefined overflow.  */
+	      if (! minus_p
+		  || neg_min_op1
+		  || TYPE_OVERFLOW_WRAPS (expr_type))
+		min = build_symbolic_expr (expr_type, sym_min_op1,
+					   neg_min_op1 ^ minus_p, min);
+	      else
+		min = NULL_TREE;
+	    }
 
 	  /* Likewise for the upper bound.  */
 	  if (sym_max_op0 == sym_max_op1)
@@ -2641,8 +2650,17 @@  extract_range_from_binary_expr_1 (value_
 	    max = build_symbolic_expr (expr_type, sym_max_op0,
 				       neg_max_op0, max);
 	  else if (sym_max_op1)
-	    max = build_symbolic_expr (expr_type, sym_max_op1,
-				       neg_max_op1 ^ minus_p, max);
+	    {
+	      /* We may not negate if that might introduce
+		 undefined overflow.  */
+	      if (! minus_p
+		  || neg_max_op1
+		  || TYPE_OVERFLOW_WRAPS (expr_type))
+		max = build_symbolic_expr (expr_type, sym_max_op1,
+					   neg_max_op1 ^ minus_p, max);
+	      else
+		max = NULL_TREE;
+	    }
 	}
       else
 	{
Index: gcc/testsuite/gcc.dg/torture/pr79666.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr79666.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr79666.c	(working copy)
@@ -0,0 +1,30 @@ 
+/* { dg-do run } */
+
+struct
+{
+  unsigned a:6;
+} b;
+
+int c, e, g = 7;
+signed char d, f = 6, h = -10;
+
+void fn1 ()
+{
+  for (; c < 9; c++)
+    {
+      if (f)
+	g = ~(~0 / (g ^ e));
+      b.a = ~0;
+      d = ~((h ^ b.a) & 132 & (~(f && g) | (d && 1)));
+      e = ~0;
+      if (d < 127 || f < 1)
+	continue;
+      g = 0;
+    }
+}
+
+int main ()
+{
+  fn1 ();
+  return 0; 
+}