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