Disable an unsafe VRP transformation when -fno-strict-overflow is set
authorPatrick Palka <ppalka@gcc.gnu.org>
Thu, 20 Nov 2014 22:25:35 +0000 (22:25 +0000)
committerPatrick Palka <ppalka@gcc.gnu.org>
Thu, 20 Nov 2014 22:25:35 +0000 (22:25 +0000)
gcc/
* tree-vrp.c (test_for_singularity): New parameter
strict_overflow_p.  Set *strict_overflow_p to true if signed
overflow must be undefined for the return value to satisfy the
conditional.
(simplify_cond_using_ranges): Don't perform the simplification
if it violates overflow rules.

gcc/testsuite/
* gcc.dg/no-strict-overflow-8.c: New test.

From-SVN: r217895

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/no-strict-overflow-8.c [new file with mode: 0644]
gcc/tree-vrp.c

index 394ae4fd44265792bedab1391a68e71df59e1898..4501014d340b788cfc18ed5c5b3aeadcd3fde83a 100644 (file)
@@ -1,3 +1,12 @@
+2014-11-20  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       * tree-vrp.c (test_for_singularity): New parameter
+       strict_overflow_p.  Set *strict_overflow_p to true if signed
+       overflow must be undefined for the return value to satisfy the
+       conditional.
+       (simplify_cond_using_ranges): Don't perform the simplification
+       if it violates overflow rules.
+
 2014-11-20  Marek Polacek  <polacek@redhat.com>
 
        * tree-ssa-loop-niter.c (maybe_lower_iteration_bound): Fix typo.
index 4aba5fb9e86a6dce3116ac8a45ab2e9a6d0cc510..882e2ac4e82a967e15ff2c3d772355ba8ed71bdb 100644 (file)
@@ -1,3 +1,7 @@
+2014-11-20  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       * gcc.dg/no-strict-overflow-8.c: New test.
+
 2014-11-20  Andrew Stubbs  <ams@codesourcery.com>
 
        * gcc.dg/undefined-loop-1.c: New file.
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-8.c b/gcc/testsuite/gcc.dg/no-strict-overflow-8.c
new file mode 100644 (file)
index 0000000..11ef935
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-optimized" } */
+
+/* We cannot fold i > 0 because p->a - p->b can be larger than INT_MAX
+   and thus i can wrap.  Dual of Wstrict-overflow-18.c  */
+
+struct c { unsigned int a; unsigned int b; };
+extern void bar (struct c *);
+int
+foo (struct c *p)
+{
+  int i;
+  int sum = 0;
+
+  for (i = 0; i < p->a - p->b; ++i)
+    {
+      if (i > 0)
+       sum += 2;
+      bar (p);
+    }
+  return sum;
+}
+
+/* { dg-final { scan-tree-dump "i_.* > 0" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index bcf4c2ba60c64bfc5f020b5eb44b88dd3cad1474..a75138ffc5b1774d2ca3d9899003492d48bc19f5 100644 (file)
@@ -9117,11 +9117,15 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
    a known value range VR.
 
    If there is one and only one value which will satisfy the
-   conditional, then return that value.  Else return NULL.  */
+   conditional, then return that value.  Else return NULL.
+
+   If signed overflow must be undefined for the value to satisfy
+   the conditional, then set *STRICT_OVERFLOW_P to true.  */
 
 static tree
 test_for_singularity (enum tree_code cond_code, tree op0,
-                     tree op1, value_range_t *vr)
+                     tree op1, value_range_t *vr,
+                     bool *strict_overflow_p)
 {
   tree min = NULL;
   tree max = NULL;
@@ -9172,7 +9176,16 @@ test_for_singularity (enum tree_code cond_code, tree op0,
         then there is only one value which can satisfy the condition,
         return that value.  */
       if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min))
-       return min;
+       {
+         if ((cond_code == LE_EXPR || cond_code == LT_EXPR)
+             && is_overflow_infinity (vr->max))
+           *strict_overflow_p = true;
+         if ((cond_code == GE_EXPR || cond_code == GT_EXPR)
+             && is_overflow_infinity (vr->min))
+           *strict_overflow_p = true;
+
+         return min;
+       }
     }
   return NULL;
 }
@@ -9252,9 +9265,12 @@ simplify_cond_using_ranges (gcond *stmt)
         able to simplify this conditional. */
       if (vr->type == VR_RANGE)
        {
-         tree new_tree = test_for_singularity (cond_code, op0, op1, vr);
+         enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON;
+         bool sop = false;
+         tree new_tree = test_for_singularity (cond_code, op0, op1, vr, &sop);
 
-         if (new_tree)
+         if (new_tree
+             && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
            {
              if (dump_file)
                {
@@ -9275,16 +9291,30 @@ simplify_cond_using_ranges (gcond *stmt)
                  fprintf (dump_file, "\n");
                }
 
+             if (sop && issue_strict_overflow_warning (wc))
+               {
+                 location_t location = input_location;
+                 if (gimple_has_location (stmt))
+                   location = gimple_location (stmt);
+
+                 warning_at (location, OPT_Wstrict_overflow,
+                             "assuming signed overflow does not occur when "
+                             "simplifying conditional");
+               }
+
              return true;
            }
 
          /* Try again after inverting the condition.  We only deal
             with integral types here, so no need to worry about
             issues with inverting FP comparisons.  */
-         cond_code = invert_tree_comparison (cond_code, false);
-         new_tree = test_for_singularity (cond_code, op0, op1, vr);
+         sop = false;
+         new_tree = test_for_singularity
+                      (invert_tree_comparison (cond_code, false),
+                       op0, op1, vr, &sop);
 
-         if (new_tree)
+         if (new_tree
+             && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))))
            {
              if (dump_file)
                {
@@ -9305,6 +9335,17 @@ simplify_cond_using_ranges (gcond *stmt)
                  fprintf (dump_file, "\n");
                }
 
+             if (sop && issue_strict_overflow_warning (wc))
+               {
+                 location_t location = input_location;
+                 if (gimple_has_location (stmt))
+                   location = gimple_location (stmt);
+
+                 warning_at (location, OPT_Wstrict_overflow,
+                             "assuming signed overflow does not occur when "
+                             "simplifying conditional");
+               }
+
              return true;
            }
        }