On Thu, Mar 08, 2012 at 04:54:31PM +0100, Jakub Jelinek wrote: > This patch adds ASSERT_EXPRs for > if ((int) var cmp CST) > (for cmp >, >=, <, <=). As the testcase shows, various different tests > are folded into that form. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
This patch no longer applies after the PR tree-optimization/52533 fix, so here is an updated patch that does apply and contains a tiny cleanup too: 2012-03-09 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/51721 * tree-vrp.c (register_edge_assert_for_2): Add asserts for unsvar if (int) unsvar cmp CST. * gcc.dg/tree-ssa/vrp64.c: New test. --- gcc/tree-vrp.c.jj 2012-03-09 12:30:19.348501480 +0100 +++ gcc/tree-vrp.c 2012-03-09 12:53:41.844227149 +0100 @@ -4462,8 +4462,6 @@ register_edge_assert_for_2 (tree name, e } } - /* Similarly add asserts for NAME == CST and NAME being defined as - NAME = NAME2 >> CST2. */ if (TREE_CODE_CLASS (comp_code) == tcc_comparison && TREE_CODE (val) == INTEGER_CST) { @@ -4473,7 +4471,60 @@ register_edge_assert_for_2 (tree name, e double_int mask = double_int_zero; unsigned int prec = TYPE_PRECISION (TREE_TYPE (val)); - /* Extract CST2 from the right shift. */ + /* Add asserts for NAME cmp CST and NAME being defined + as NAME = (int) NAME2. */ + if (!TYPE_UNSIGNED (TREE_TYPE (val)) + && (comp_code == LE_EXPR || comp_code == LT_EXPR + || comp_code == GT_EXPR || comp_code == GE_EXPR) + && gimple_assign_cast_p (def_stmt)) + { + name2 = gimple_assign_rhs1 (def_stmt); + if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)) + && INTEGRAL_TYPE_P (TREE_TYPE (name2)) + && TYPE_UNSIGNED (TREE_TYPE (name2)) + && prec == TYPE_PRECISION (TREE_TYPE (name2)) + && (comp_code == LE_EXPR || comp_code == GT_EXPR + || !tree_int_cst_equal (val, + TYPE_MIN_VALUE (TREE_TYPE (val)))) + && live_on_edge (e, name2) + && !has_single_use (name2)) + { + tree tmp, cst; + enum tree_code new_comp_code = comp_code; + + cst = fold_convert (TREE_TYPE (name2), + TYPE_MIN_VALUE (TREE_TYPE (val))); + /* Build an expression for the range test. */ + tmp = build2 (PLUS_EXPR, TREE_TYPE (name2), name2, cst); + cst = fold_build2 (PLUS_EXPR, TREE_TYPE (name2), cst, + fold_convert (TREE_TYPE (name2), val)); + if (comp_code == LT_EXPR || comp_code == GE_EXPR) + { + new_comp_code = comp_code == LT_EXPR ? LE_EXPR : GT_EXPR; + cst = fold_build2 (MINUS_EXPR, TREE_TYPE (name2), cst, + build_int_cst (TREE_TYPE (name2), 1)); + } + + if (dump_file) + { + fprintf (dump_file, "Adding assert for "); + print_generic_expr (dump_file, name2, 0); + fprintf (dump_file, " from "); + print_generic_expr (dump_file, tmp, 0); + fprintf (dump_file, "\n"); + } + + register_new_assert_for (name2, tmp, new_comp_code, cst, NULL, + e, bsi); + + retval = true; + } + } + + /* Add asserts for NAME cmp CST and NAME being defined as + NAME = NAME2 >> CST2. + + Extract CST2 from the right shift. */ if (is_gimple_assign (def_stmt) && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR) { @@ -4491,7 +4542,6 @@ register_edge_assert_for_2 (tree name, e val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2); } } - if (val2 != NULL_TREE && TREE_CODE (val2) == INTEGER_CST && simple_cst_equal (fold_build2 (RSHIFT_EXPR, --- gcc/testsuite/gcc.dg/tree-ssa/vrp64.c.jj 2012-03-09 12:45:23.287171268 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/vrp64.c 2012-03-09 12:45:23.287171268 +0100 @@ -0,0 +1,152 @@ +/* PR tree-optimization/51721 */ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void); + +#define BITSM1 (sizeof (int) * __CHAR_BIT__ - 1) + +void +f1 (unsigned int s) +{ + if (s >> BITSM1 != 0) + { + if (s == 0 || s == 5 || s == __INT_MAX__) + link_error (); + } + else + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U) + link_error (); + } +} + +void +f2 (int s) +{ + if (s >> BITSM1 == 0) + { + if (s == -1 || s == -5 || s == -__INT_MAX__ - 1) + link_error (); + } + else + { + if (s == 0 || s == 5 || s == __INT_MAX__) + link_error (); + } +} + +void +f3 (unsigned int s) +{ + if ((s & (1U << BITSM1)) != 0) + { + if (s == 0 || s == 5 || s == __INT_MAX__) + link_error (); + } + else + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U) + link_error (); + } +} + +void +f4 (int s) +{ + if ((s & (1U << BITSM1)) == 0) + { + if (s == -1 || s == -5 || s == -__INT_MAX__ - 1) + link_error (); + } + else + { + if (s == 0 || s == 5 || s == __INT_MAX__) + link_error (); + } +} + +void +f5 (unsigned int s) +{ + if ((int) s < 0) + { + if (s == 0 || s == 5 || s == __INT_MAX__) + link_error (); + } + else + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U) + link_error (); + } +} + +void +f6 (unsigned int s) +{ + if ((int) s < 4) + { + if (s == 4 || s == 6 || s == __INT_MAX__) + link_error (); + } + else + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U + || s == 3 || s == 0) + link_error (); + } +} + +void +f7 (unsigned int s) +{ + if ((int) s <= -7) + { + if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__) + link_error (); + } + else + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U + || s == -7U) + link_error (); + } +} + +void +f8 (unsigned int s) +{ + if ((int) s >= 4) + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -1U + || s == 3 || s == 0) + link_error (); + } + else + { + if (s == 4 || s == 6 || s == __INT_MAX__) + link_error (); + } +} + +void +f9 (unsigned int s) +{ + if ((int) s > -7) + { + if (s == 1U + __INT_MAX__ || s == 6U + __INT_MAX__ || s == -9U + || s == -7U) + link_error (); + } + else + { + if (s == -6U || s == -1U || s == 0 || s == 4 || s == 6 || s == __INT_MAX__) + link_error (); + } +} + +int +main () +{ + return 0; +} Jakub