This patch is a replacement for the 2nd VRP refactoring patch.  It
simply teaches VRP to look through widening type conversions when
finding suitable edge assertions, e.g.

bool p = x != y;
int q = (int) p;
if (q == 0) // new edge assert: p == 0 and therefore x == y

The new testcase requires that such an edge assertion be inserted.

Full bootstrap + regtest on x86_64-unknown-linux-gnu in progress.  Does
the patch look OK for trunk if no new regressions?

2014-11-11  Patrick Palka  <ppa...@gcc.gnu.org>

gcc/
        * tree-vrp.c (register_edge_assert_for): Look through
        widening type conversions for posible edge assertions.

gcc/testsuite/
        * gcc.dg/vrp-1.c: New testcase.
---
 gcc/testsuite/gcc.dg/vrp-1.c | 31 +++++++++++++++++++++++++++++++
 gcc/tree-vrp.c               | 22 ++++++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/vrp-1.c

diff --git a/gcc/testsuite/gcc.dg/vrp-1.c b/gcc/testsuite/gcc.dg/vrp-1.c
new file mode 100644
index 0000000..df5334e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vrp-1.c
@@ -0,0 +1,31 @@
+/* { dg-options "-O2" } */
+
+void runtime_error (void) __attribute__ ((noreturn));
+void compiletime_error (void) __attribute__ ((noreturn, error ("")));
+
+static void
+compiletime_check_equals_1 (int *x, int y)
+{
+  int __p = *x != y;
+  if (__builtin_constant_p (__p) && __p)
+    compiletime_error ();
+  if (__p)
+    runtime_error ();
+}
+
+static void
+compiletime_check_equals_2 (int *x, int y)
+{
+  int __p = *x != y;
+  if (__builtin_constant_p (__p) && __p)
+    compiletime_error (); /* { dg-error "call to" } */
+  if (__p)
+    runtime_error ();
+}
+
+void
+foo (int *x)
+{
+  compiletime_check_equals_1 (x, 5);
+  compiletime_check_equals_2 (x, 10);
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index f0a4382..979ab44 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5634,6 +5634,7 @@ register_edge_assert_for (tree name, edge e, 
gimple_stmt_iterator si,
      the value zero or one, then we may be able to assert values
      for SSA_NAMEs which flow into COND.  */
 
+
   /* In the case of NAME == 1 or NAME != 0, for BIT_AND_EXPR defining
      statement of NAME we can assert both operands of the BIT_AND_EXPR
      have nonzero value.  */
@@ -5673,6 +5674,27 @@ register_edge_assert_for (tree name, edge e, 
gimple_stmt_iterator si,
          register_edge_assert_for_1 (op1, EQ_EXPR, e, si);
        }
     }
+
+  /* In the case of NAME != 0 or NAME == 0, if NAME's defining statement
+     is a widening type conversion then we can assert that NAME's
+     RHS is accordingly nonzero or zero.  */
+  if ((comp_code == EQ_EXPR || comp_code == NE_EXPR)
+      && integer_zerop (val))
+    {
+      gimple def_stmt = SSA_NAME_DEF_STMT (name);
+      if (is_gimple_assign (def_stmt))
+       {
+         enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
+         if (CONVERT_EXPR_CODE_P (def_code))
+           {
+             tree lhs = gimple_assign_lhs (def_stmt);
+             tree rhs = gimple_assign_rhs1 (def_stmt);
+             if (TYPE_PRECISION (TREE_TYPE (lhs))
+                 >= TYPE_PRECISION (TREE_TYPE (rhs)))
+               register_edge_assert_for_1 (rhs, comp_code, e, si);
+           }
+       }
+    }
 }
 
 
-- 
2.2.0.rc1.16.g6066a7e

Reply via email to