This improves VRP so that two of the three (the remaining one invalid
IMHO) spurious array-bound warnings in PR55079 no longer appear.
With the patch we now properly handle

  MIN_EXPR <[1, 6], VARYING>

and register asserts for i_2 in

  i_2 = i_1 + 1;
  if (i_1 != 0)

which is a common pattern from tests of post-modify expressions.

For gcc.dg/tree-ssa/ssa-pre-1.c this is too fancy and thus I needed
to adjust the testcase to avoid VRP being too clever.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2012-12-10  Richard Biener  <rguent...@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.

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

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c      (revision 194358)
--- gcc/tree-vrp.c      (working copy)
*************** extract_range_from_binary_expr_1 (value_
*** 2349,2354 ****
--- 2349,2356 ----
        && 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
*************** extract_range_from_binary_expr_1 (value_
*** 2602,2622 ****
    else if (code == MIN_EXPR
           || code == MAX_EXPR)
      {
!       if (vr0.type == VR_ANTI_RANGE)
        {
!         /* 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);
        }
        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);
        }
      }
    else if (code == MULT_EXPR)
--- 2604,2652 ----
    else if (code == MIN_EXPR
           || code == MAX_EXPR)
      {
!       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))
!       {
!         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
        {
!         set_value_range_to_varying (vr);
!         return;
        }
      }
    else if (code == MULT_EXPR)
*************** register_edge_assert_for_2 (tree name, e
*** 4707,4712 ****
--- 4737,4781 ----
        }
      }
  
+   /* 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)
      {
*************** check_array_ref (location_t location, tr
*** 5943,5948 ****
--- 6012,6022 ----
               : (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;
*************** check_array_ref (location_t location, tr
*** 5950,5955 ****
--- 6024,6034 ----
    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;
*************** search_for_addr_array (tree t, location_
*** 6018,6023 ****
--- 6097,6107 ----
        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;
*************** search_for_addr_array (tree t, location_
*** 6026,6031 ****
--- 6110,6120 ----
                        - 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;
Index: gcc/testsuite/gcc.dg/Warray-bounds-9.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-9.c      (revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-9.c      (working copy)
***************
*** 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: gcc/testsuite/gcc.dg/Warray-bounds-10.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-10.c     (revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-10.c     (working copy)
***************
*** 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;
+ }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c   (revision 194358)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c   (working copy)
*************** int foo(int argc, char **argv)
*** 9,15 ****
        b  = argc + 1;
        c =  argc + 2;
        a = b + c;
!       if (argc * 2)
        {
                c = argc + 3;
        }
--- 9,15 ----
        b  = argc + 1;
        c =  argc + 2;
        a = b + c;
!       if (argc > 2)
        {
                c = argc + 3;
        }

Reply via email to