In unrolling of the inner loop in the test case below we introduce
unreachable code that otherwise contains out-of-bounds array accesses.
This is because the estimation of the maximum number of iterations of
the inner loop is too conservative: we assume 6 iterations instead of
the actual 4.

Nonetheless, VRP should be able to tell that the code is unreachable so
that it doesn't warn about it.  The only thing holding VRP back is that
it doesn't look through conditionals of the form

   if (j_10 != CST1)    where j_10 = j_9 + CST2

so that it could add the assertion

   j_9 != (CST1 - CST2)

This patch teaches VRP to detect such conditionals and to add such
assertions, so that it could remove instead of warn about the
unreachable code created during loop unrolling.

What this addition does with the test case below is something like this:

ASSERT_EXPR (i <= 5);
for (i = 1; i < 6; i++)
  {
    j = i - 1;
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 1)
    bar[j] = baz[j];

    j = i - 2
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 2)
    bar[j] = baz[j];

    j = i - 3
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 3)
    bar[j] = baz[j];

    j = i - 4
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 4)
    bar[j] = baz[j];

    j = i - 5
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 5)
    bar[j] = baz[j];

    j = i - 6
    if (j == 0)
      break;
    // ASSERT_EXPR (i != 6)
    bar[j] = baz[j]; // unreachable because (i != 6 && i <= 5) is always false
  }

(I think the patch I sent a year ago that improved the
 register_edge_assert stuff would have fixed this too.  I'll try to
 post it again during next stage 1.
 https://gcc.gnu.org/ml/gcc-patches/2014-11/msg00908.html)

Bootstrap + regtest in progress on x86_64-pc-linux-gnu, does this look
OK to commit after testing?

gcc/ChangeLog:

        PR tree-optimization/59124
        * tree-vrp.c (register_edge_assert_for): For NAME != CST1
        where NAME = A + CST2 add the assertion A != (CST1 - CST2).

gcc/testsuite/ChangeLog:

        PR tree-optimization/59124
        * gcc.dg/Warray-bounds-19.c: New test.
---
 gcc/testsuite/gcc.dg/Warray-bounds-19.c | 17 +++++++++++++++++
 gcc/tree-vrp.c                          | 22 ++++++++++++++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-19.c

diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-19.c 
b/gcc/testsuite/gcc.dg/Warray-bounds-19.c
new file mode 100644
index 0000000..e2f9661
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-19.c
@@ -0,0 +1,17 @@
+/* PR tree-optimization/59124 */
+/* { dg-options "-O3 -Warray-bounds" } */
+
+unsigned baz[6];
+
+void foo(unsigned *bar, unsigned n)
+{
+  unsigned i, j;
+
+  if (n > 6)
+    n = 6;
+
+  for (i = 1; i < n; i++)
+    for (j = i - 1; j > 0; j--)
+      bar[j - 1] = baz[j - 1];
+}
+
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b5654c5..31bd575 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5820,6 +5820,28 @@ register_edge_assert_for (tree name, edge e, 
gimple_stmt_iterator si,
        }
     }
 
+  /* In the case of NAME != CST1 where NAME = A + CST2 we can
+     assert that NAME != (CST1 - CST2).  */
+  if ((comp_code == EQ_EXPR || comp_code == NE_EXPR)
+      && TREE_CODE (val) == INTEGER_CST)
+    {
+      gimple *def_stmt = SSA_NAME_DEF_STMT (name);
+
+      if (is_gimple_assign (def_stmt)
+         && gimple_assign_rhs_code (def_stmt) == PLUS_EXPR)
+       {
+         tree op0 = gimple_assign_rhs1 (def_stmt);
+         tree op1 = gimple_assign_rhs2 (def_stmt);
+         if (TREE_CODE (op0) == SSA_NAME
+             && TREE_CODE (op1) == INTEGER_CST)
+           {
+             op1 = int_const_binop (MINUS_EXPR, val, op1);
+             register_edge_assert_for_2 (op0, e, si, comp_code,
+                                         op0, op1, is_else_edge);
+           }
+       }
+    }
+
   /* In the case of NAME == 0 or NAME != 1, for BIT_IOR_EXPR defining
      statement of NAME we can assert both operands of the BIT_IOR_EXPR
      have zero value.  */
-- 
2.8.0.rc3.27.gade0865

Reply via email to