diff options
Diffstat (limited to 'gcc/tree-ssa-sink.cc')
-rw-r--r-- | gcc/tree-ssa-sink.cc | 73 |
1 files changed, 49 insertions, 24 deletions
diff --git a/gcc/tree-ssa-sink.cc b/gcc/tree-ssa-sink.cc index 959e0d5..2244e89f 100644 --- a/gcc/tree-ssa-sink.cc +++ b/gcc/tree-ssa-sink.cc @@ -356,37 +356,54 @@ statement_sink_location (gimple *stmt, basic_block frombb, use = NULL; - /* If stmt is a store the one and only use needs to be the VOP - merging PHI node. */ + /* If stmt is a store the one and only use needs to be a VUSE on + the live path. */ if (virtual_operand_p (DEF_FROM_PTR (def_p))) { + tree lhs = gimple_get_lhs (stmt); + ao_ref ref; + ao_ref_init (&ref, lhs); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p)) { gimple *use_stmt = USE_STMT (use_p); /* A killing definition is not a use. */ - if ((gimple_has_lhs (use_stmt) - && operand_equal_p (gimple_get_lhs (stmt), - gimple_get_lhs (use_stmt), 0)) - || stmt_kills_ref_p (use_stmt, gimple_get_lhs (stmt))) + if (gimple_vdef (use_stmt) + && ((gimple_has_lhs (use_stmt) + && operand_equal_p (lhs, + gimple_get_lhs (use_stmt), 0)) + || stmt_kills_ref_p (use_stmt, &ref))) { /* If use_stmt is or might be a nop assignment then USE_STMT acts as a use as well as definition. */ if (stmt != use_stmt - && ref_maybe_used_by_stmt_p (use_stmt, - gimple_get_lhs (stmt))) - return false; + && ref_maybe_used_by_stmt_p (use_stmt, &ref)) + { + if (use && use != use_stmt) + return false; + use = use_stmt; + } continue; } - if (gimple_code (use_stmt) != GIMPLE_PHI) - return false; - - if (use - && use != use_stmt) - return false; + if (is_a <gphi *> (use_stmt) + || ref_maybe_used_by_stmt_p (use_stmt, &ref)) + { + if (use && use != use_stmt) + return false; + use = use_stmt; + continue; + } - use = use_stmt; + if (gimple_vdef (use_stmt)) + { + if (stmt_may_clobber_ref_p_1 (use_stmt, &ref, false)) + return false; + /* We do not look past VDEFs, so treat them as sink location. */ + if (use && use != use_stmt) + return false; + use = use_stmt; + } } if (!use) return false; @@ -448,18 +465,26 @@ statement_sink_location (gimple *stmt, basic_block frombb, break; } use = USE_STMT (one_use); + } - if (gimple_code (use) != GIMPLE_PHI) - { - sinkbb = select_best_block (frombb, gimple_bb (use), stmt); + if (gimple_code (use) != GIMPLE_PHI) + { + sinkbb = select_best_block (frombb, gimple_bb (use), stmt); - if (sinkbb == frombb) - return false; + if (sinkbb == frombb) + return false; - *togsi = gsi_after_labels (sinkbb); + /* The SSA update for sinking of stores cannot insert PHIs, the + sink location has to lead to exit without crossing any CFG + merge points to paths not dominated by the sink location. */ + if (gimple_vdef (stmt) + && (!single_succ_p (sinkbb) + || single_succ (sinkbb)->index != EXIT_BLOCK)) + return false; - return true; - } + *togsi = gsi_after_labels (sinkbb); + + return true; } sinkbb = find_bb_for_arg (as_a <gphi *> (use), DEF_FROM_PTR (def_p)); |