diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-26 12:05:24 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-26 12:05:24 +0000 |
commit | 8ddad41d2bdf91d09d2effc7673ce41a577fb8bb (patch) | |
tree | 2e0ce944007433764dbb17fe53d32320bebbcfb3 | |
parent | bc7ef935ebf12140d3090ef1ff207f3c8df944cf (diff) | |
download | gcc-8ddad41d2bdf91d09d2effc7673ce41a577fb8bb.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187913 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 2 | ||||
-rw-r--r-- | gcc/cfgrtl.c | 96 |
3 files changed, 77 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9e442a359a..3f89efc96fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index e94e7e3fb41..6c56a041d75 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -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)) diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 4e1ec8644d1..3ee92d9a2aa 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -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)) |