From: Richard Biener Date: Fri, 28 Apr 2017 06:42:20 +0000 (+0000) Subject: tree-vrp.c (assert_info): New struct. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=119092c17a0c6e947f774692849dedb84acb53f2;p=gcc.git tree-vrp.c (assert_info): New struct. 2017-04-28 Richard Biener * tree-vrp.c (assert_info): New struct. (add_assert_info): New helper. (register_edge_assert_for_2): Refactor to add asserts to a vector of assert_info. (register_edge_assert_for_1): Likewise. (register_edge_assert_for): Likewise. (finish_register_edge_assert_for): New helper actually registering asserts where live on edge. (find_conditional_asserts): Adjust. (find_switch_asserts): Likewise. (evrp_dom_walker::try_find_new_range): Generalize. (evrp_dom_walker::before_dom_children): Use register_edge_assert_for. * gcc.dg/tree-ssa/evrp7.c: New testcase. * gcc.dg/tree-ssa/evrp8.c: Likewise. * gcc.dg/tree-ssa/evrp9.c: Likewise. * gcc.dg/tree-ssa/vrp35.c: Disable EVRP. * gcc.dg/tree-ssa/vrp36.c: Likewise. * gcc.dg/tree-ssa/pr49039.c: Likewise. From-SVN: r247362 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8ee4265844..aa39842e400 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2017-04-28 Richard Biener + + * tree-vrp.c (assert_info): New struct. + (add_assert_info): New helper. + (register_edge_assert_for_2): Refactor to add asserts to a vector + of assert_info. + (register_edge_assert_for_1): Likewise. + (register_edge_assert_for): Likewise. + (finish_register_edge_assert_for): New helper actually registering + asserts where live on edge. + (find_conditional_asserts): Adjust. + (find_switch_asserts): Likewise. + (evrp_dom_walker::try_find_new_range): Generalize. + (evrp_dom_walker::before_dom_children): Use register_edge_assert_for. + 2017-04-27 Marek Polacek PR sanitizer/80349 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5f25ed1652e..910f42d87ae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2017-04-28 Richard Biener + + * gcc.dg/tree-ssa/evrp7.c: New testcase. + * gcc.dg/tree-ssa/evrp8.c: Likewise. + * gcc.dg/tree-ssa/evrp9.c: Likewise. + * gcc.dg/tree-ssa/vrp35.c: Disable EVRP. + * gcc.dg/tree-ssa/vrp36.c: Likewise. + * gcc.dg/tree-ssa/pr49039.c: Likewise. + 2017-04-27 Marek Polacek PR sanitizer/80349 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c new file mode 100644 index 00000000000..16fbe65e4d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp7.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ + +int test1(int i, int k) +{ + if (i > 0 && i <= 5 && k >= 10 && k < 42) + { + int j = i + 1 + k; + return j == 10; + } + return 1; +} + +/* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = j_.* == 10" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp8.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp8.c new file mode 100644 index 00000000000..b7e5c7aa2de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp8.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ + +int foo(int i) +{ + if (i < 0 || i >= 5) + return i == 1; + return 1; +} + +/* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = i_.* == 1" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp9.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp9.c new file mode 100644 index 00000000000..6e7828e4340 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp9.c @@ -0,0 +1,28 @@ +/* PR tree-optimization/49039 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +extern void bar (void); + +void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x >= 3 && x <= 6) + return; + if (y >= 5 && y <= 8) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 5) + bar (); + if (minv == 6) + bar (); + if (maxv == 5) + bar (); + if (maxv == 6) + bar (); +} + +/* { dg-final { scan-tree-dump-not "== 5" "evrp" } } */ +/* { dg-final { scan-tree-dump-not "== 6" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c index e1fee0839ff..4bc0a8175a0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c @@ -1,6 +1,6 @@ /* PR tree-optimization/49039 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1" } */ +/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1" } */ extern void bar (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c index 20112eafd53..a372a18cc43 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ +/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */ int test1(int i, int k) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c index 3933254474a..1f77b539d70 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ +/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */ int foo(int i) { diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 697cd88502e..df5e4267491 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -89,6 +89,21 @@ static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code, tree, tree, bool, bool *, bool *); +struct assert_info +{ + /* Predicate code for the ASSERT_EXPR. Must be COMPARISON_CLASS_P. */ + enum tree_code comp_code; + + /* Name to register the assert for. */ + tree name; + + /* Value being compared against. */ + tree val; + + /* Expression to compare. */ + tree expr; +}; + /* Location information for ASSERT_EXPRs. Each instance of this structure describes an ASSERT_EXPR for an SSA name. Since a single SSA name may have more than one assertion associated with it, these @@ -5029,6 +5044,19 @@ debug_all_asserts (void) dump_all_asserts (stderr); } +/* Push the assert info for NAME, EXPR, COMP_CODE and VAL to ASSERTS. */ + +static void +add_assert_info (vec &asserts, + tree name, tree expr, enum tree_code comp_code, tree val) +{ + assert_info info; + info.comp_code = comp_code; + info.name = name; + info.val = val; + info.expr = expr; + asserts.safe_push (info); +} /* If NAME doesn't have an ASSERT_EXPR registered for asserting 'EXPR COMP_CODE VAL' at a location that dominates block BB or @@ -5357,9 +5385,10 @@ overflow_comparison_p (tree_code code, tree name, tree val, Invert the condition COND if INVERT is true. */ static void -register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, +register_edge_assert_for_2 (tree name, edge e, enum tree_code cond_code, - tree cond_op0, tree cond_op1, bool invert) + tree cond_op0, tree cond_op1, bool invert, + vec &asserts) { tree val; enum tree_code comp_code; @@ -5370,20 +5399,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, invert, &comp_code, &val)) return; - /* Only register an ASSERT_EXPR if NAME was found in the sub-graph - reachable from E. */ - if (live_on_edge (e, name)) + /* Queue the assert. */ + tree x; + if (overflow_comparison_p (comp_code, name, val, false, &x)) { - tree x; - if (overflow_comparison_p (comp_code, name, val, false, &x)) - { - enum tree_code new_code - = ((comp_code == GT_EXPR || comp_code == GE_EXPR) - ? GT_EXPR : LE_EXPR); - register_new_assert_for (name, name, new_code, x, NULL, e, bsi); - } - register_new_assert_for (name, name, comp_code, val, NULL, e, bsi); + enum tree_code new_code = ((comp_code == GT_EXPR || comp_code == GE_EXPR) + ? GT_EXPR : LE_EXPR); + add_assert_info (asserts, name, name, new_code, x); } + add_assert_info (asserts, name, name, comp_code, val); /* In the case of NAME <= CST and NAME being defined as NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2 @@ -5423,8 +5447,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, && TREE_CODE (name3) == SSA_NAME && (cst2 == NULL_TREE || TREE_CODE (cst2) == INTEGER_CST) - && INTEGRAL_TYPE_P (TREE_TYPE (name3)) - && live_on_edge (e, name3)) + && INTEGRAL_TYPE_P (TREE_TYPE (name3))) { tree tmp; @@ -5442,15 +5465,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, fprintf (dump_file, "\n"); } - register_new_assert_for (name3, tmp, comp_code, val, NULL, e, bsi); + add_assert_info (asserts, name3, tmp, comp_code, val); } /* If name2 is used later, create an ASSERT_EXPR for it. */ if (name2 != NULL_TREE && TREE_CODE (name2) == SSA_NAME && TREE_CODE (cst2) == INTEGER_CST - && INTEGRAL_TYPE_P (TREE_TYPE (name2)) - && live_on_edge (e, name2)) + && INTEGRAL_TYPE_P (TREE_TYPE (name2))) { tree tmp; @@ -5470,7 +5492,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, fprintf (dump_file, "\n"); } - register_new_assert_for (name2, tmp, comp_code, val, NULL, e, bsi); + add_assert_info (asserts, name2, tmp, comp_code, val); } } @@ -5496,8 +5518,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, continue; tree name2 = gimple_assign_lhs (use_stmt); - if (TREE_CODE (name2) != SSA_NAME - || !live_on_edge (e, name2)) + if (TREE_CODE (name2) != SSA_NAME) continue; enum tree_code code = gimple_assign_rhs_code (use_stmt); @@ -5525,8 +5546,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, if (TREE_OVERFLOW_P (cst)) cst = drop_tree_overflow (cst); - register_new_assert_for (name2, name2, comp_code, cst, - NULL, e, bsi); + add_assert_info (asserts, name2, name2, comp_code, cst); } } @@ -5552,15 +5572,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, 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 - && live_on_edge (e, op0)) + && TREE_CODE (op1) == INTEGER_CST) { enum tree_code reverse_op = (rhs_code == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR); op1 = int_const_binop (reverse_op, val, op1); if (TREE_OVERFLOW (op1)) op1 = drop_tree_overflow (op1); - register_new_assert_for (op0, op0, comp_code, op1, NULL, e, bsi); + add_assert_info (asserts, op0, op0, comp_code, op1); } } @@ -5578,8 +5597,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, && 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)) + TYPE_MIN_VALUE (TREE_TYPE (val))))) { tree tmp, cst; enum tree_code new_comp_code = comp_code; @@ -5606,8 +5624,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, fprintf (dump_file, "\n"); } - register_new_assert_for (name2, tmp, new_comp_code, cst, NULL, - e, bsi); + add_assert_info (asserts, name2, tmp, new_comp_code, cst); } } @@ -5623,8 +5640,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, && tree_fits_uhwi_p (cst2) && INTEGRAL_TYPE_P (TREE_TYPE (name2)) && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1) - && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val))) - && live_on_edge (e, name2)) + && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val)))) { mask = wi::mask (tree_to_uhwi (cst2), false, prec); val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2); @@ -5682,8 +5698,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, fprintf (dump_file, "\n"); } - register_new_assert_for (name2, tmp, new_comp_code, new_val, - NULL, e, bsi); + add_assert_info (asserts, name2, tmp, new_comp_code, new_val); } } @@ -5728,12 +5743,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2)) || !INTEGRAL_TYPE_P (TREE_TYPE (names[1])) || (TYPE_PRECISION (TREE_TYPE (name2)) - != TYPE_PRECISION (TREE_TYPE (names[1]))) - || !live_on_edge (e, names[1])) + != TYPE_PRECISION (TREE_TYPE (names[1])))) names[1] = NULL_TREE; } - if (live_on_edge (e, name2)) - names[0] = name2; + names[0] = name2; } } if (names[0] || names[1]) @@ -5924,8 +5937,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, fprintf (dump_file, "\n"); } - register_new_assert_for (names[i], tmp, LE_EXPR, - new_val, NULL, e, bsi); + add_assert_info (asserts, names[i], tmp, LE_EXPR, new_val); } } } @@ -5941,7 +5953,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, static void register_edge_assert_for_1 (tree op, enum tree_code code, - edge e, gimple_stmt_iterator bsi) + edge e, vec &asserts) { gimple *op_def; tree val; @@ -5951,13 +5963,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, if (TREE_CODE (op) != SSA_NAME) return; - /* We know that OP will have a zero or nonzero value. If OP is used - more than once go ahead and register an assert for OP. */ - if (live_on_edge (e, op)) - { - val = build_int_cst (TREE_TYPE (op), 0); - register_new_assert_for (op, op, code, val, NULL, e, bsi); - } + /* We know that OP will have a zero or nonzero value. */ + val = build_int_cst (TREE_TYPE (op), 0); + add_assert_info (asserts, op, op, code, val); /* Now look at how OP is set. If it's set from a comparison, a truth operation or some bit operations, then we may be able @@ -5975,9 +5983,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, tree op1 = gimple_assign_rhs2 (op_def); if (TREE_CODE (op0) == SSA_NAME) - register_edge_assert_for_2 (op0, e, bsi, rhs_code, op0, op1, invert); + register_edge_assert_for_2 (op0, e, rhs_code, op0, op1, invert, asserts); if (TREE_CODE (op1) == SSA_NAME) - register_edge_assert_for_2 (op1, e, bsi, rhs_code, op0, op1, invert); + register_edge_assert_for_2 (op1, e, rhs_code, op0, op1, invert, asserts); } else if ((code == NE_EXPR && gimple_assign_rhs_code (op_def) == BIT_AND_EXPR) @@ -5989,22 +5997,22 @@ register_edge_assert_for_1 (tree op, enum tree_code code, tree op1 = gimple_assign_rhs2 (op_def); if (TREE_CODE (op0) == SSA_NAME && has_single_use (op0)) - register_edge_assert_for_1 (op0, code, e, bsi); + register_edge_assert_for_1 (op0, code, e, asserts); if (TREE_CODE (op1) == SSA_NAME && has_single_use (op1)) - register_edge_assert_for_1 (op1, code, e, bsi); + register_edge_assert_for_1 (op1, code, e, asserts); } else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1) { /* Recurse, flipping CODE. */ code = invert_tree_comparison (code, false); - register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi); + register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts); } else if (gimple_assign_rhs_code (op_def) == SSA_NAME) { /* Recurse through the copy. */ - register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi); + register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts); } else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def))) { @@ -6014,7 +6022,7 @@ register_edge_assert_for_1 (tree op, enum tree_code code, if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)) && (TYPE_PRECISION (TREE_TYPE (rhs)) <= TYPE_PRECISION (TREE_TYPE (op)))) - register_edge_assert_for_1 (rhs, code, e, bsi); + register_edge_assert_for_1 (rhs, code, e, asserts); } } @@ -6023,9 +6031,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, SI. */ static void -register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, +register_edge_assert_for (tree name, edge e, enum tree_code cond_code, tree cond_op0, - tree cond_op1) + tree cond_op1, vec &asserts) { tree val; enum tree_code comp_code; @@ -6043,8 +6051,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, return; /* Register ASSERT_EXPRs for name. */ - register_edge_assert_for_2 (name, e, si, cond_code, cond_op0, - cond_op1, is_else_edge); + register_edge_assert_for_2 (name, e, cond_code, cond_op0, + cond_op1, is_else_edge, asserts); /* If COND is effectively an equality test of an SSA_NAME against @@ -6064,8 +6072,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, { tree op0 = gimple_assign_rhs1 (def_stmt); tree op1 = gimple_assign_rhs2 (def_stmt); - register_edge_assert_for_1 (op0, NE_EXPR, e, si); - register_edge_assert_for_1 (op1, NE_EXPR, e, si); + register_edge_assert_for_1 (op0, NE_EXPR, e, asserts); + register_edge_assert_for_1 (op1, NE_EXPR, e, asserts); } } @@ -6086,12 +6094,28 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, { tree op0 = gimple_assign_rhs1 (def_stmt); tree op1 = gimple_assign_rhs2 (def_stmt); - register_edge_assert_for_1 (op0, EQ_EXPR, e, si); - register_edge_assert_for_1 (op1, EQ_EXPR, e, si); + register_edge_assert_for_1 (op0, EQ_EXPR, e, asserts); + register_edge_assert_for_1 (op1, EQ_EXPR, e, asserts); } } } +/* Finish found ASSERTS for E and register them at GSI. */ + +static void +finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi, + vec &asserts) +{ + for (unsigned i = 0; i < asserts.length (); ++i) + /* Only register an ASSERT_EXPR if NAME was found in the sub-graph + reachable from E. */ + if (live_on_edge (e, asserts[i].name)) + register_new_assert_for (asserts[i].name, asserts[i].expr, + asserts[i].comp_code, asserts[i].val, + NULL, e, gsi); +} + + /* Determine whether the outgoing edges of BB should receive an ASSERT_EXPR for each of the operands of BB's LAST statement. @@ -6123,11 +6147,13 @@ find_conditional_asserts (basic_block bb, gcond *last) /* Register the necessary assertions for each operand in the conditional predicate. */ + auto_vec asserts; FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE) - register_edge_assert_for (op, e, bsi, + register_edge_assert_for (op, e, gimple_cond_code (last), gimple_cond_lhs (last), - gimple_cond_rhs (last)); + gimple_cond_rhs (last), asserts); + finish_register_edge_assert_for (e, bsi, asserts); } } @@ -6239,12 +6265,16 @@ find_switch_asserts (basic_block bb, gswitch *last) /* Register the necessary assertions for the operand in the SWITCH_EXPR. */ - register_edge_assert_for (op, e, bsi, + auto_vec asserts; + register_edge_assert_for (op, e, max ? GE_EXPR : EQ_EXPR, - op, fold_convert (TREE_TYPE (op), min)); + op, fold_convert (TREE_TYPE (op), min), + asserts); if (max) - register_edge_assert_for (op, e, bsi, LE_EXPR, op, - fold_convert (TREE_TYPE (op), max)); + register_edge_assert_for (op, e, LE_EXPR, op, + fold_convert (TREE_TYPE (op), max), + asserts); + finish_register_edge_assert_for (e, bsi, asserts); } XDELETEVEC (ci); @@ -6293,8 +6323,11 @@ find_switch_asserts (basic_block bb, gswitch *last) if (max == NULL_TREE) { /* Register the assertion OP != MIN. */ + auto_vec asserts; min = fold_convert (TREE_TYPE (op), min); - register_edge_assert_for (op, default_edge, bsi, NE_EXPR, op, min); + register_edge_assert_for (op, default_edge, NE_EXPR, op, min, + asserts); + finish_register_edge_assert_for (default_edge, bsi, asserts); } else { @@ -11160,7 +11193,7 @@ public: virtual void after_dom_children (basic_block); void push_value_range (tree var, value_range *vr); value_range *pop_value_range (tree var); - value_range *try_find_new_range (tree op, tree_code code, tree limit); + value_range *try_find_new_range (tree, tree op, tree_code code, tree limit); /* Cond_stack holds the old VR. */ auto_vec > stack; @@ -11169,19 +11202,18 @@ public: auto_vec stmts_to_remove; }; -/* Find new range for OP such that (OP CODE LIMIT) is true. */ +/* Find new range for NAME such that (OP CODE LIMIT) is true. */ value_range * -evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit) +evrp_dom_walker::try_find_new_range (tree name, + tree op, tree_code code, tree limit) { value_range vr = VR_INITIALIZER; - value_range *old_vr = get_value_range (op); + value_range *old_vr = get_value_range (name); /* Discover VR when condition is true. */ - extract_range_for_var_from_comparison_expr (op, code, op, + extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr); - if (old_vr->type == VR_RANGE || old_vr->type == VR_ANTI_RANGE) - vrp_intersect_ranges (&vr, old_vr); /* If we found any usable VR, set the VR to ssa_name and create a PUSH old value in the stack with the old VR. */ if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE) @@ -11245,36 +11277,29 @@ evrp_dom_walker::before_dom_children (basic_block bb) /* Entering a new scope. Try to see if we can find a VR here. */ tree op1 = gimple_cond_rhs (stmt); - tree_code code = gimple_cond_code (stmt); - if (TREE_OVERFLOW_P (op1)) op1 = drop_tree_overflow (op1); + tree_code code = gimple_cond_code (stmt); - /* If condition is false, invert the cond. */ - if (pred_e->flags & EDGE_FALSE_VALUE) - code = invert_tree_comparison (gimple_cond_code (stmt), - HONOR_NANS (op0)); - /* Add VR when (OP0 CODE OP1) condition is true. */ - value_range *op0_range = try_find_new_range (op0, code, op1); - - /* Register ranges for y in x < y where - y might have ranges that are useful. */ - tree limit; - tree_code new_code; - if (TREE_CODE (op1) == SSA_NAME - && extract_code_and_val_from_cond_with_ops (op1, code, - op0, op1, - false, - &new_code, &limit)) + auto_vec asserts; + register_edge_assert_for (op0, pred_e, code, op0, op1, asserts); + if (TREE_CODE (op1) == SSA_NAME) + register_edge_assert_for (op1, pred_e, code, op0, op1, asserts); + + auto_vec, 8> vrs; + for (unsigned i = 0; i < asserts.length (); ++i) { - /* Add VR when (OP1 NEW_CODE LIMIT) condition is true. */ - value_range *op1_range = try_find_new_range (op1, new_code, limit); - if (op1_range) - push_value_range (op1, op1_range); + value_range *vr = try_find_new_range (asserts[i].name, + asserts[i].expr, + asserts[i].comp_code, + asserts[i].val); + if (vr) + vrs.safe_push (std::make_pair (asserts[i].name, vr)); } - - if (op0_range) - push_value_range (op0, op0_range); + /* Push updated ranges only after finding all of them to avoid + ordering issues that can lead to worse ranges. */ + for (unsigned i = 0; i < vrs.length (); ++i) + push_value_range (vrs[i].first, vrs[i].second); } } @@ -11462,13 +11487,13 @@ evrp_dom_walker::before_dom_children (basic_block bb) /* Add VR when (T COMP_CODE value) condition is true. */ value_range *op_range - = try_find_new_range (t, comp_code, value); + = try_find_new_range (t, t, comp_code, value); if (op_range) push_value_range (t, op_range); } } /* Add VR when (OP COMP_CODE value) condition is true. */ - value_range *op_range = try_find_new_range (op, + value_range *op_range = try_find_new_range (op, op, comp_code, value); if (op_range) push_value_range (op, op_range);