diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-20.c new file mode 100644 index 00000000000..266ceb000a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-20.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink1-details" } */ + +void bar (); +int foo (int *p, int x) +{ + int res = *p; + if (x) + { + bar (); + res = 1; + } + return res; +} + +/* { dg-final { scan-tree-dump "Sinking # VUSE" "sink1" } } */ diff --git a/gcc/tree-ssa-sink.cc b/gcc/tree-ssa-sink.cc index d83d7be587d..5cf9e737e84 100644 --- a/gcc/tree-ssa-sink.cc +++ b/gcc/tree-ssa-sink.cc @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfg.h" #include "cfgloop.h" #include "tree-eh.h" +#include "tree-ssa-live.h" /* TODO: 1. Sinking store only using scalar promotion (IE without moving the RHS): @@ -263,7 +264,8 @@ select_best_block (basic_block early_bb, static bool statement_sink_location (gimple *stmt, basic_block frombb, - gimple_stmt_iterator *togsi, bool *zero_uses_p) + gimple_stmt_iterator *togsi, bool *zero_uses_p, + virtual_operand_live &vop_live) { gimple *use; use_operand_p one_use = NULL_USE_OPERAND_P; @@ -386,10 +388,7 @@ statement_sink_location (gimple *stmt, basic_block frombb, if (commondom == frombb) return false; - /* If this is a load then do not sink past any stores. - Look for virtual definitions in the path from frombb to the sink - location computed from the real uses and if found, adjust - that it a common dominator. */ + /* If this is a load then do not sink past any stores. */ if (gimple_vuse (stmt)) { /* Do not sink loads from hard registers. */ @@ -398,51 +397,14 @@ statement_sink_location (gimple *stmt, basic_block frombb, && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))) return false; - imm_use_iterator imm_iter; - use_operand_p use_p; - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vuse (stmt)) - { - gimple *use_stmt = USE_STMT (use_p); - basic_block bb = gimple_bb (use_stmt); - /* For PHI nodes the block we know sth about is the incoming block - with the use. */ - if (gimple_code (use_stmt) == GIMPLE_PHI) - { - /* If the PHI defines the virtual operand, ignore it. */ - if (gimple_phi_result (use_stmt) == gimple_vuse (stmt)) - continue; - /* In case the PHI node post-dominates the current insert - location we can disregard it. But make sure it is not - dominating it as well as can happen in a CFG cycle. */ - if (commondom != bb - && !dominated_by_p (CDI_DOMINATORS, commondom, bb) - && dominated_by_p (CDI_POST_DOMINATORS, commondom, bb) - /* If the blocks are possibly within the same irreducible - cycle the above check breaks down. */ - && !((bb->flags & commondom->flags & BB_IRREDUCIBLE_LOOP) - && bb->loop_father == commondom->loop_father) - && !((commondom->flags & BB_IRREDUCIBLE_LOOP) - && flow_loop_nested_p (commondom->loop_father, - bb->loop_father)) - && !((bb->flags & BB_IRREDUCIBLE_LOOP) - && flow_loop_nested_p (bb->loop_father, - commondom->loop_father))) - continue; - bb = EDGE_PRED (bb, PHI_ARG_INDEX_FROM_USE (use_p))->src; - } - else if (!gimple_vdef (use_stmt)) - continue; - /* If the use is not dominated by the path entry it is not on - the path. */ - if (!dominated_by_p (CDI_DOMINATORS, bb, frombb)) - continue; - /* There is no easy way to disregard defs not on the path from - frombb to commondom so just consider them all. */ - commondom = nearest_common_dominator (CDI_DOMINATORS, - bb, commondom); - if (commondom == frombb) - return false; - } + /* When the live virtual operand at the intended sink location is + not the same as the one from the load walk up the dominator tree + for a new candidate location. */ + while (commondom != frombb + && vop_live.get_live_in (commondom) != gimple_vuse (stmt)) + commondom = get_immediate_dominator (CDI_DOMINATORS, commondom); + if (commondom == frombb) + return false; } /* Our common dominator has to be dominated by frombb in order to be a @@ -681,7 +643,7 @@ sink_common_stores_to_bb (basic_block bb) /* Perform code sinking on BB */ static unsigned -sink_code_in_bb (basic_block bb) +sink_code_in_bb (basic_block bb, virtual_operand_live &vop_live) { gimple_stmt_iterator gsi; edge_iterator ei; @@ -708,7 +670,7 @@ sink_code_in_bb (basic_block bb) gimple_stmt_iterator togsi; bool zero_uses_p; - if (!statement_sink_location (stmt, bb, &togsi, &zero_uses_p)) + if (!statement_sink_location (stmt, bb, &togsi, &zero_uses_p, vop_live)) { gimple_stmt_iterator saved = gsi; if (!gsi_end_p (gsi)) @@ -864,12 +826,14 @@ pass_sink_code::execute (function *fun) calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS); + virtual_operand_live vop_live; + auto_vec worklist; worklist.quick_push (EXIT_BLOCK_PTR_FOR_FN (fun)); do { basic_block bb = worklist.pop (); - todo |= sink_code_in_bb (bb); + todo |= sink_code_in_bb (bb, vop_live); for (basic_block son = first_dom_son (CDI_POST_DOMINATORS, bb); son; son = next_dom_son (CDI_POST_DOMINATORS, son))