Hi! 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? 2012-03-08 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-06 17:02:12.000000000 +0100 +++ gcc/tree-vrp.c 2012-03-08 11:41:17.749509390 +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) { @@ -4472,7 +4470,61 @@ register_edge_assert_for_2 (tree name, e tree val2 = NULL_TREE; unsigned HOST_WIDE_INT mask[2] = { 0, 0 }; - /* 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)) + && (TYPE_PRECISION (TREE_TYPE (val)) + == 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) { @@ -4500,7 +4552,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-08 12:58:05.773797384 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/vrp64.c 2012-03-08 12:57:26.000000000 +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