This is the first patch in a series of enabling "DCE" mode in substitute_and_fold for VRP. It exchanges lattice substitution and folding (by substitute_and_fold) with the pass specific folding routine. This is because if we do not substitute before that the pass specific folding might see SSA names that will end up being released (because they are fully propagated out). VRP in particular happily inserts new stmts before the current stmt referencing such SSA names which later causes problems.
[In the end I would like all those pass specific foldings to go away in favor of match.pd rules] Re-bootstrap & regtest running on x86_64-unknown-linux-gnu. Richard. 2016-10-07 Richard Biener <rguent...@suse.de> * tree-ssa-propagate.c (replace_phi_args_in): Remove no longer required hack. (substitute_and_fold_dom_walker::before_dom_children): Substitute and fold before pass specific folding to avoid feeding that with SSA names that will be later released. * tree-ssa-ccp.c (get_value_for_expr): Guard for new SSA names introduced by folding and visited by evaluate_stmt called during ccp_fold_stmt. (likely_value): Likewise. (evaluate_stmt): Likewise. * tree-vrp.c (simplify_truth_ops_using_ranges): Fold modified stmt. (simplify_div_or_mod_using_ranges): Likewise. (simplify_min_or_max_using_ranges): Likewise. (simplify_abs_using_ranges): Likewise. (simplify_conversion_using_ranges): Likewise. (simplify_float_conversion_using_ranges): Likewise. (simplify_stmt_using_ranges): Likewise. * gcc.dg/tree-ssa/vrp01.c: Adjust. * gcc.dg/tree-ssa/vrp34.c: Likewise. Index: gcc/testsuite/gcc.dg/tree-ssa/vrp01.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/vrp01.c (revision 240855) +++ gcc/testsuite/gcc.dg/tree-ssa/vrp01.c (working copy) @@ -25,4 +25,4 @@ foo (int *p, int i) return i; } -/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "if \\\(" 2 "vrp1" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/vrp34.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/vrp34.c (revision 240855) +++ gcc/testsuite/gcc.dg/tree-ssa/vrp34.c (working copy) @@ -15,5 +15,5 @@ foo (int a) } } -/* { dg-final { scan-tree-dump "Folding predicate a_. > 2 to 1" "vrp1" } } */ -/* { dg-final { scan-tree-dump "Folding predicate a_. <= 5 to 1" "vrp1" } } */ +/* Both ifs should be optimized. */ +/* { dg-final { scan-tree-dump-times "if \\\(" 0 "vrp1" } } */ Index: gcc/tree-ssa-ccp.c =================================================================== --- gcc/tree-ssa-ccp.c (revision 240855) +++ gcc/tree-ssa-ccp.c (working copy) @@ -591,7 +591,15 @@ get_value_for_expr (tree expr, bool for_ if (TREE_CODE (expr) == SSA_NAME) { - val = *get_value (expr); + ccp_prop_value_t *val_ = get_value (expr); + if (val_) + val = *val_; + else + { + val.lattice_val = VARYING; + val.value = NULL_TREE; + val.mask = -1; + } if (for_bits_p && val.lattice_val == CONSTANT && TREE_CODE (val.value) == ADDR_EXPR) @@ -673,12 +681,12 @@ likely_value (gimple *stmt) { ccp_prop_value_t *val = get_value (use); - if (val->lattice_val == UNDEFINED) + if (val && val->lattice_val == UNDEFINED) has_undefined_operand = true; else all_undefined_operands = false; - if (val->lattice_val == CONSTANT) + if (val && val->lattice_val == CONSTANT) has_constant_operand = true; if (SSA_NAME_IS_DEFAULT_DEF (use) @@ -1739,11 +1747,11 @@ evaluate_stmt (gimple *stmt) simplified = ccp_fold (stmt); if (simplified && TREE_CODE (simplified) == SSA_NAME) { - val = *get_value (simplified); - if (val.lattice_val != VARYING) + ccp_prop_value_t *val = get_value (simplified); + if (val && val->lattice_val != VARYING) { fold_undefer_overflow_warnings (true, stmt, 0); - return val; + return *val; } } is_constant = simplified && is_gimple_min_invariant (simplified); Index: gcc/tree-ssa-propagate.c =================================================================== --- gcc/tree-ssa-propagate.c (revision 240855) +++ gcc/tree-ssa-propagate.c (working copy) @@ -914,7 +914,6 @@ replace_phi_args_in (gphi *phi, ssa_prop print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); } - basic_block bb = gimple_bb (phi); for (i = 0; i < gimple_phi_num_args (phi); i++) { tree arg = gimple_phi_arg_def (phi, i); @@ -927,19 +926,6 @@ replace_phi_args_in (gphi *phi, ssa_prop { edge e = gimple_phi_arg_edge (phi, i); - /* Avoid propagating constants into loop latch edge - PHI arguments as this makes coalescing the copy - across this edge impossible. If the argument is - defined by an assert - otherwise the stmt will - get removed without replacing its uses. */ - if (TREE_CODE (val) != SSA_NAME - && bb->loop_father->header == bb - && dominated_by_p (CDI_DOMINATORS, e->src, bb) - && is_gimple_assign (SSA_NAME_DEF_STMT (arg)) - && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (arg)) - == ASSERT_EXPR)) - continue; - if (TREE_CODE (val) != SSA_NAME) prop_stats.num_const_prop++; else @@ -1090,18 +1076,6 @@ substitute_and_fold_dom_walker::before_d bool was_noreturn = (is_gimple_call (stmt) && gimple_call_noreturn_p (stmt)); - /* Some statements may be simplified using propagator - specific information. Do this before propagating - into the stmt to not disturb pass specific information. */ - if (fold_fn - && (*fold_fn)(&i)) - { - did_replace = true; - prop_stats.num_stmts_folded++; - stmt = gsi_stmt (i); - update_stmt (stmt); - } - /* Replace real uses in the statement. */ did_replace |= replace_uses_in (stmt, get_value_fn); @@ -1110,6 +1084,22 @@ substitute_and_fold_dom_walker::before_d { fold_stmt (&i, follow_single_use_edges); stmt = gsi_stmt (i); + gimple_set_modified (stmt, true); + } + + /* Some statements may be simplified using propagator + specific information. Do this before propagating + into the stmt to not disturb pass specific information. */ + if (fold_fn) + { + update_stmt_if_modified (stmt); + if ((*fold_fn)(&i)) + { + did_replace = true; + prop_stats.num_stmts_folded++; + stmt = gsi_stmt (i); + gimple_set_modified (stmt, true); + } } /* If this is a control statement the propagator left edges @@ -1127,6 +1117,7 @@ substitute_and_fold_dom_walker::before_d gimple_cond_make_true (as_a <gcond *> (stmt)); else gimple_cond_make_false (as_a <gcond *> (stmt)); + gimple_set_modified (stmt, true); did_replace = true; } } @@ -1155,7 +1146,7 @@ substitute_and_fold_dom_walker::before_d } /* Determine what needs to be done to update the SSA form. */ - update_stmt (stmt); + update_stmt_if_modified (stmt); if (!is_gimple_debug (stmt)) something_changed = true; } Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 240855) +++ gcc/tree-vrp.c (working copy) @@ -9055,6 +9055,7 @@ simplify_truth_ops_using_ranges (gimple_ else gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op0, op1); update_stmt (gsi_stmt (*gsi)); + fold_stmt (gsi, follow_single_use_edges); return true; } @@ -9156,6 +9157,7 @@ simplify_div_or_mod_using_ranges (gimple } update_stmt (stmt); + fold_stmt (gsi, follow_single_use_edges); return true; } @@ -9204,6 +9206,7 @@ simplify_min_or_max_using_ranges (gimple gimple_stmt_iterator gsi = gsi_for_stmt (stmt); gimple_assign_set_rhs_from_tree (&gsi, res); update_stmt (stmt); + fold_stmt (&gsi, follow_single_use_edges); return true; } @@ -9256,6 +9259,8 @@ simplify_abs_using_ranges (gimple *stmt) else gimple_assign_set_rhs_code (stmt, NEGATE_EXPR); update_stmt (stmt); + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + fold_stmt (&gsi, follow_single_use_edges); return true; } } @@ -9906,7 +9911,8 @@ simplify_conversion_using_ranges (gimple return false; gimple_assign_set_rhs1 (stmt, innerop); - update_stmt (stmt); + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + fold_stmt (&gsi, follow_single_use_edges); return true; } @@ -9971,7 +9977,7 @@ simplify_float_conversion_using_ranges ( conv = gimple_build_assign (tem, NOP_EXPR, rhs1); gsi_insert_before (gsi, conv, GSI_SAME_STMT); gimple_assign_set_rhs1 (stmt, tem); - update_stmt (stmt); + fold_stmt (gsi, follow_single_use_edges); return true; } @@ -10176,6 +10182,7 @@ simplify_stmt_using_ranges (gimple_stmt_ new_rhs1, new_rhs2); update_stmt (gsi_stmt (*gsi)); + fold_stmt (gsi, follow_single_use_edges); return true; } }