2012-12-11 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Dec 2012 10:06:15 +0000 (10:06 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Dec 2012 10:06:15 +0000 (10:06 +0000)
PR tree-optimization/55079
* tree-vrp.c (extract_range_from_binary_expr_1): Handle MAX/MIN_EXPR
for more cases.
(register_edge_assert_for_2): Register asserts for post-in/decrement
tests.
(check_array_ref): Dump what expression we emit array bound
warnings for.
(search_for_addr_array): Likewise.

* gcc.dg/Warray-bounds-9.c: New testcase.
* gcc.dg/Warray-bounds-10.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-1.c: Adjust.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194388 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Warray-bounds-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-bounds-9.c [new file with mode: 0644]
gcc/tree-vrp.c

index eef5504..fc1a827 100644 (file)
@@ -1,3 +1,14 @@
+2012-12-11  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/55079
+       * tree-vrp.c (extract_range_from_binary_expr_1): Handle MAX/MIN_EXPR
+       for more cases.
+       (register_edge_assert_for_2): Register asserts for post-in/decrement
+       tests.
+       (check_array_ref): Dump what expression we emit array bound
+       warnings for.
+       (search_for_addr_array): Likewise.
+
 2012-12-11  Eric Botcazou  <ebotcazou@adacore.com>
 
        * tree-ssa-loop-ivopts.c (prepare_decl_rtl) <ADDR_EXPR>: Generate RTL
index 481bbaa..3e81e76 100644 (file)
@@ -1,3 +1,10 @@
+2012-12-11  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/55079
+       * gcc.dg/Warray-bounds-9.c: New testcase.
+       * gcc.dg/Warray-bounds-10.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-pre-1.c: Adjust.
+
 2012-12-10  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/52909
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-10.c b/gcc/testsuite/gcc.dg/Warray-bounds-10.c
new file mode 100644 (file)
index 0000000..5fd6e6f
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Warray-bounds" } */
+
+int f(unsigned len, int buflen)
+{
+  unsigned taillen;
+  unsigned slen;
+  unsigned i;
+  int b[17];            /* needed <= 17 to trigger Warning */
+  int j = 0;            /* needed to trigger Warning */
+
+  b[0] = 0;
+  taillen= buflen & 7;    /* taillen [0..7] */
+
+  if(taillen) {        /* taillen [1..7] */
+      slen= 8 - taillen;    /* slen    [7..1] */
+      if (len<slen)        /* needed to trigger Warning  */
+       slen=len;        /* slen' < slen  */
+      for(i=0; i<slen; i++) {
+         j = b[taillen];    /* taillen + slen = [1..7] + [7..1] = 8 */
+         taillen++;
+      }
+  }
+  return j;
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-9.c b/gcc/testsuite/gcc.dg/Warray-bounds-9.c
new file mode 100644 (file)
index 0000000..92bcd4e
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Warray-bounds" } */
+
+int a[8];
+
+void
+test(unsigned int n)
+{
+  unsigned int i;
+  unsigned int j;
+  if (n<8)
+    for (j=0;j<n;j++)
+      {
+       i = j;
+       do
+         a[i+1]=a[i];
+       while (i--);
+      }
+}
index dc03db5..4319c60 100644 (file)
@@ -2349,6 +2349,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       && code != EXACT_DIV_EXPR
       && code != ROUND_DIV_EXPR
       && code != TRUNC_MOD_EXPR
+      && code != MIN_EXPR
+      && code != MAX_EXPR
       && (vr0.type == VR_VARYING
          || vr1.type == VR_VARYING
          || vr0.type != vr1.type
@@ -2602,21 +2604,49 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == MIN_EXPR
           || code == MAX_EXPR)
     {
-      if (vr0.type == VR_ANTI_RANGE)
+      if (vr0.type == VR_RANGE
+         && !symbolic_range_p (&vr0))
+       {
+         type = VR_RANGE;
+         if (vr1.type == VR_RANGE
+             && !symbolic_range_p (&vr1))
+           {
+             /* For operations that make the resulting range directly
+                proportional to the original ranges, apply the operation to
+                the same end of each range.  */
+             min = vrp_int_const_binop (code, vr0.min, vr1.min);
+             max = vrp_int_const_binop (code, vr0.max, vr1.max);
+           }
+         else if (code == MIN_EXPR)
+           {
+             min = vrp_val_min (expr_type);
+             max = vr0.max;
+           }
+         else if (code == MAX_EXPR)
+           {
+             min = vr0.min;
+             max = vrp_val_max (expr_type);
+           }
+       }
+      else if (vr1.type == VR_RANGE
+              && !symbolic_range_p (&vr1))
        {
-         /* For MIN_EXPR and MAX_EXPR with two VR_ANTI_RANGEs,
-            the resulting VR_ANTI_RANGE is the same - intersection
-            of the two ranges.  */
-         min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min);
-         max = vrp_int_const_binop (MIN_EXPR, vr0.max, vr1.max);
+         type = VR_RANGE;
+         if (code == MIN_EXPR)
+           {
+             min = vrp_val_min (expr_type);
+             max = vr1.max;
+           }
+         else if (code == MAX_EXPR)
+           {
+             min = vr1.min;
+             max = vrp_val_max (expr_type);
+           }
        }
       else
        {
-         /* For operations that make the resulting range directly
-            proportional to the original ranges, apply the operation to
-            the same end of each range.  */
-         min = vrp_int_const_binop (code, vr0.min, vr1.min);
-         max = vrp_int_const_binop (code, vr0.max, vr1.max);
+         set_value_range_to_varying (vr);
+         return;
        }
     }
   else if (code == MULT_EXPR)
@@ -4707,6 +4737,45 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
        }
     }
 
+  /* In the case of post-in/decrement tests like if (i++) ... and uses
+     of the in/decremented value on the edge the extra name we want to
+     assert for is not on the def chain of the name compared.  Instead
+     it is in the set of use stmts.  */
+  if ((comp_code == NE_EXPR
+       || comp_code == EQ_EXPR)
+      && TREE_CODE (val) == INTEGER_CST)
+    {
+      imm_use_iterator ui;
+      gimple use_stmt;
+      FOR_EACH_IMM_USE_STMT (use_stmt, ui, name)
+       {
+         /* Cut off to use-stmts that are in the predecessor.  */
+         if (gimple_bb (use_stmt) != e->src)
+           continue;
+
+         if (!is_gimple_assign (use_stmt))
+           continue;
+
+         enum tree_code code = gimple_assign_rhs_code (use_stmt);
+         if (code != PLUS_EXPR
+             && code != MINUS_EXPR)
+           continue;
+
+         tree cst = gimple_assign_rhs2 (use_stmt);
+         if (TREE_CODE (cst) != INTEGER_CST)
+           continue;
+
+         tree name2 = gimple_assign_lhs (use_stmt);
+         if (live_on_edge (e, name2))
+           {
+             cst = int_const_binop (code, val, cst);
+             register_new_assert_for (name2, name2, comp_code, cst,
+                                      NULL, e, bsi);
+             retval = true;
+           }
+       }
+    }
   if (TREE_CODE_CLASS (comp_code) == tcc_comparison
       && TREE_CODE (val) == INTEGER_CST)
     {
@@ -5943,6 +6012,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
               : (tree_int_cst_lt (up_bound, up_sub)
                  || tree_int_cst_equal (up_bound_p1, up_sub))))
     {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Array bound warning for ");
+         dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
+       }
       warning_at (location, OPT_Warray_bounds,
                  "array subscript is above array bounds");
       TREE_NO_WARNING (ref) = 1;
@@ -5950,6 +6024,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
   else if (TREE_CODE (low_sub) == INTEGER_CST
            && tree_int_cst_lt (low_sub, low_bound))
     {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       {
+         fprintf (dump_file, "Array bound warning for ");
+         dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
+       }
       warning_at (location, OPT_Warray_bounds,
                  "array subscript is below array bounds");
       TREE_NO_WARNING (ref) = 1;
@@ -6018,6 +6097,11 @@ search_for_addr_array (tree t, location_t location)
       idx = idx.sdiv (tree_to_double_int (el_sz), TRUNC_DIV_EXPR);
       if (idx.slt (double_int_zero))
        {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Array bound warning for ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
+           }
          warning_at (location, OPT_Warray_bounds,
                      "array subscript is below array bounds");
          TREE_NO_WARNING (t) = 1;
@@ -6026,6 +6110,11 @@ search_for_addr_array (tree t, location_t location)
                        - tree_to_double_int (low_bound)
                        + double_int_one))
        {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           {
+             fprintf (dump_file, "Array bound warning for ");
+             dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
+           }
          warning_at (location, OPT_Warray_bounds,
                      "array subscript is above array bounds");
          TREE_NO_WARNING (t) = 1;