re PR tree-optimization/64006 (__builtin_mul_overflow fails to signal overflow)
authorJakub Jelinek <jakub@redhat.com>
Fri, 21 Nov 2014 20:41:37 +0000 (21:41 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 21 Nov 2014 20:41:37 +0000 (21:41 +0100)
PR tree-optimization/64006
* tree-vrp.c (stmt_interesting_for_vrp): Return true
for {ADD,SUB,MUL}_OVERFLOW internal calls.
(vrp_visit_assignment_or_call): For {ADD,SUB,MUL}_OVERFLOW
internal calls, check if any REALPART_EXPR/IMAGPART_EXPR
immediate uses would change their value ranges and return
SSA_PROP_INTERESTING if so, or SSA_PROP_NOT_INTERESTING
if there are some REALPART_EXPR/IMAGPART_EXPR immediate uses
interesting for vrp.

* gcc.c-torture/execute/pr64006.c: New test.

From-SVN: r217945

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr64006.c [new file with mode: 0644]
gcc/tree-vrp.c

index 9fb7f7a..1254751 100644 (file)
@@ -1,3 +1,15 @@
+2014-11-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/64006
+       * tree-vrp.c (stmt_interesting_for_vrp): Return true
+       for {ADD,SUB,MUL}_OVERFLOW internal calls.
+       (vrp_visit_assignment_or_call): For {ADD,SUB,MUL}_OVERFLOW
+       internal calls, check if any REALPART_EXPR/IMAGPART_EXPR
+       immediate uses would change their value ranges and return
+       SSA_PROP_INTERESTING if so, or SSA_PROP_NOT_INTERESTING
+       if there are some REALPART_EXPR/IMAGPART_EXPR immediate uses
+       interesting for vrp.
+
 2014-11-21  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR target/63965
index fd91a5c..cfb8c5f 100644 (file)
@@ -1,3 +1,8 @@
+2014-11-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/64006
+       * gcc.c-torture/execute/pr64006.c: New test.
+
 2014-11-21  Lynn Boger  <laboger@linux.vnet.ibm.com>
 
        * go.test/go-test.exp (go-set-goarch): Add case for ppc64le goarch
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr64006.c b/gcc/testsuite/gcc.c-torture/execute/pr64006.c
new file mode 100644 (file)
index 0000000..ddf9207
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR tree-optimization/64006 */
+
+int v;
+
+long __attribute__ ((noinline, noclone))
+test (long *x, int y)
+{
+  int i;
+  long s = 1;
+  for (i = 0; i < y; i++)
+    if (__builtin_mul_overflow (s, x[i], &s))
+      v++;
+  return s;
+}
+
+int
+main ()
+{
+  long d[7] = { 975, 975, 975, 975, 975, 975, 975 };
+  long r = test (d, 7);
+  if (sizeof (long) * __CHAR_BIT__ == 64 && v != 1)
+    __builtin_abort ();
+  else if (sizeof (long) * __CHAR_BIT__ == 32 && v != 4)
+    __builtin_abort ();
+  return 0;
+}
index a75138f..27ec29b 100644 (file)
@@ -6949,6 +6949,20 @@ stmt_interesting_for_vrp (gimple stmt)
          && (is_gimple_call (stmt)
              || !gimple_vuse (stmt)))
        return true;
+      else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+       switch (gimple_call_internal_fn (stmt))
+         {
+         case IFN_ADD_OVERFLOW:
+         case IFN_SUB_OVERFLOW:
+         case IFN_MUL_OVERFLOW:
+           /* These internal calls return _Complex integer type,
+              but are interesting to VRP nevertheless.  */
+           if (lhs && TREE_CODE (lhs) == SSA_NAME)
+             return true;
+           break;
+         default:
+           break;
+         }
     }
   else if (gimple_code (stmt) == GIMPLE_COND
           || gimple_code (stmt) == GIMPLE_SWITCH)
@@ -7101,6 +7115,74 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
 
       return SSA_PROP_NOT_INTERESTING;
     }
+  else if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+    switch (gimple_call_internal_fn (stmt))
+      {
+      case IFN_ADD_OVERFLOW:
+      case IFN_SUB_OVERFLOW:
+      case IFN_MUL_OVERFLOW:
+       /* These internal calls return _Complex integer type,
+          which VRP does not track, but the immediate uses
+          thereof might be interesting.  */
+       if (lhs && TREE_CODE (lhs) == SSA_NAME)
+         {
+           imm_use_iterator iter;
+           use_operand_p use_p;
+           enum ssa_prop_result res = SSA_PROP_VARYING;
+
+           set_value_range_to_varying (get_value_range (lhs));
+
+           FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+             {
+               gimple use_stmt = USE_STMT (use_p);
+               if (!is_gimple_assign (use_stmt))
+                 continue;
+               enum tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
+               if (rhs_code != REALPART_EXPR && rhs_code != IMAGPART_EXPR)
+                 continue;
+               tree rhs1 = gimple_assign_rhs1 (use_stmt);
+               tree use_lhs = gimple_assign_lhs (use_stmt);
+               if (TREE_CODE (rhs1) != rhs_code
+                   || TREE_OPERAND (rhs1, 0) != lhs
+                   || TREE_CODE (use_lhs) != SSA_NAME
+                   || !stmt_interesting_for_vrp (use_stmt)
+                   || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
+                       || !TYPE_MIN_VALUE (TREE_TYPE (use_lhs))
+                       || !TYPE_MAX_VALUE (TREE_TYPE (use_lhs))))
+                 continue;
+
+               /* If there is a change in the value range for any of the
+                  REALPART_EXPR/IMAGPART_EXPR immediate uses, return
+                  SSA_PROP_INTERESTING.  If there are any REALPART_EXPR
+                  or IMAGPART_EXPR immediate uses, but none of them have
+                  a change in their value ranges, return
+                  SSA_PROP_NOT_INTERESTING.  If there are no
+                  {REAL,IMAG}PART_EXPR uses at all,
+                  return SSA_PROP_VARYING.  */
+               value_range_t new_vr = VR_INITIALIZER;
+               extract_range_basic (&new_vr, use_stmt);
+               value_range_t *old_vr = get_value_range (use_lhs);
+               if (old_vr->type != new_vr.type
+                   || !vrp_operand_equal_p (old_vr->min, new_vr.min)
+                   || !vrp_operand_equal_p (old_vr->max, new_vr.max)
+                   || !vrp_bitmap_equal_p (old_vr->equiv, new_vr.equiv))
+                 res = SSA_PROP_INTERESTING;
+               else
+                 res = SSA_PROP_NOT_INTERESTING;
+               BITMAP_FREE (new_vr.equiv);
+               if (res == SSA_PROP_INTERESTING)
+                 {
+                   *output_p = lhs;
+                   return res;
+                 }
+             }
+
+           return res;
+         }
+       break;
+      default:
+       break;
+      }
 
   /* Every other statement produces no useful ranges.  */
   FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF)