cfgcleanup.c (try_optimize_cfg): Do not delete forwarder blocks if CLEANUP_NO_INSN_DEL.

* cfgcleanup.c (try_optimize_cfg): Do not delete forwarder blocks
	if CLEANUP_NO_INSN_DEL.
	* cfgrtl.c (unique_locus_on_edge_between_p): New function extracted
	from cfg_layout_merge_blocks.
	(emit_nop_for_unique_locus_between): New function.
	(rtl_merge_blocks): Invoke emit_nop_for_unique_locus_between.
	(cfg_layout_merge_blocks): Likewise.

From-SVN: r187913
This commit is contained in:
Eric Botcazou 2012-05-26 12:05:24 +00:00 committed by Eric Botcazou
parent 60ba49d019
commit 9be9422751
3 changed files with 77 additions and 31 deletions

View File

@ -1,3 +1,13 @@
2012-05-26 Eric Botcazou <ebotcazou@adacore.com>
* cfgcleanup.c (try_optimize_cfg): Do not delete forwarder blocks
if CLEANUP_NO_INSN_DEL.
* cfgrtl.c (unique_locus_on_edge_between_p): New function extracted
from cfg_layout_merge_blocks.
(emit_nop_for_unique_locus_between): New function.
(rtl_merge_blocks): Invoke emit_nop_for_unique_locus_between.
(cfg_layout_merge_blocks): Likewise.
2012-05-26 Dimitrios Apostolou <jimis@gmx.net>
Paolo Bonzini <bonzini@gnu.org>

View File

@ -2644,7 +2644,7 @@ try_optimize_cfg (int mode)
}
/* If we fall through an empty block, we can remove it. */
if (!(mode & CLEANUP_CFGLAYOUT)
if (!(mode & (CLEANUP_CFGLAYOUT | CLEANUP_NO_INSN_DEL))
&& single_pred_p (b)
&& (single_pred_edge (b)->flags & EDGE_FALLTHRU)
&& !LABEL_P (BB_HEAD (b))

View File

@ -603,6 +603,56 @@ rtl_split_block (basic_block bb, void *insnp)
return new_bb;
}
/* Return true if the single edge between blocks A and B is the only place
in RTL which holds some unique locus. */
static bool
unique_locus_on_edge_between_p (basic_block a, basic_block b)
{
const int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
rtx insn, end;
if (!goto_locus)
return false;
/* First scan block A backward. */
insn = BB_END (a);
end = PREV_INSN (BB_HEAD (a));
while (insn != end && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
insn = PREV_INSN (insn);
if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
return false;
/* Then scan block B forward. */
insn = BB_HEAD (b);
if (insn)
{
end = NEXT_INSN (BB_END (b));
while (insn != end && !NONDEBUG_INSN_P (insn))
insn = NEXT_INSN (insn);
if (insn != end && INSN_LOCATOR (insn) != 0
&& locator_eq (INSN_LOCATOR (insn), goto_locus))
return false;
}
return true;
}
/* If the single edge between blocks A and B is the only place in RTL which
holds some unique locus, emit a nop with that locus between the blocks. */
static void
emit_nop_for_unique_locus_between (basic_block a, basic_block b)
{
if (!unique_locus_on_edge_between_p (a, b))
return;
BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
INSN_LOCATOR (BB_END (a)) = EDGE_SUCC (a, 0)->goto_locus;
}
/* Blocks A and B are to be merged into a single block A. The insns
are already contiguous. */
@ -681,15 +731,25 @@ rtl_merge_blocks (basic_block a, basic_block b)
/* Delete everything marked above as well as crap that might be
hanging out between the two blocks. */
BB_HEAD (b) = NULL;
BB_END (a) = a_end;
BB_HEAD (b) = b_empty ? NULL_RTX : b_head;
delete_insn_chain (del_first, del_last, true);
/* When not optimizing CFG and the edge is the only place in RTL which holds
some unique locus, emit a nop with that locus in between. */
if (!optimize)
{
emit_nop_for_unique_locus_between (a, b);
a_end = BB_END (a);
}
/* Reassociate the insns of B with A. */
if (!b_empty)
{
update_bb_for_insn_chain (a_end, b_debug_end, a);
a_end = b_debug_end;
BB_END (a) = b_debug_end;
BB_HEAD (b) = NULL_RTX;
}
else if (b_end != b_debug_end)
{
@ -701,11 +761,10 @@ rtl_merge_blocks (basic_block a, basic_block b)
reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
b_debug_end);
update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
a_end = b_debug_end;
BB_END (a) = b_debug_end;
}
df_bb_delete (b->index);
BB_END (a) = a_end;
/* If B was a forwarder block, propagate the locus on the edge. */
if (forwarder_p && !EDGE_SUCC (b, 0)->goto_locus)
@ -2853,33 +2912,10 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
gcc_assert (!JUMP_P (BB_END (a)));
/* When not optimizing and the edge is the only place in RTL which holds
/* When not optimizing CFG and the edge is the only place in RTL which holds
some unique locus, emit a nop with that locus in between. */
if (!optimize && EDGE_SUCC (a, 0)->goto_locus)
{
rtx insn = BB_END (a), end = PREV_INSN (BB_HEAD (a));
int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
while (insn != end && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0))
insn = PREV_INSN (insn);
if (insn != end && locator_eq (INSN_LOCATOR (insn), goto_locus))
goto_locus = 0;
else
{
insn = BB_HEAD (b);
end = NEXT_INSN (BB_END (b));
while (insn != end && !INSN_P (insn))
insn = NEXT_INSN (insn);
if (insn != end && INSN_LOCATOR (insn) != 0
&& locator_eq (INSN_LOCATOR (insn), goto_locus))
goto_locus = 0;
}
if (goto_locus)
{
BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
INSN_LOCATOR (BB_END (a)) = goto_locus;
}
}
if (!optimize)
emit_nop_for_unique_locus_between (a, b);
/* Possible line number notes should appear in between. */
if (BB_HEADER (b))