Commit 623a66fa by J"orn Rennecke Committed by Joern Rennecke

basic-block.h (could_fall_through): Declare.

	* basic-block.h (could_fall_through): Declare.
	* cfganal.c (can_fallthru): Succeed if the target is EXIT_BLOCK_PTR.
	Fail if the source already has a fallthrough edge to the exit
	block pointer.
	(could_fall_through): New function.
	* cfgbuild.c (make_edges): Check if we already have a fallthrough
	edge to the exit block pointer.
	* cfglayout.c (fixup_fallthru_exit_predecessor): Check that it is
	not called before reload has completed.
	Handle special case of first block having a fall-through exit edge.
	(cfg_layout_finalize): Don't call it before reload or if we have
	rtl epilogues.
	(fixup_reorder_chain): A fall through to the exit block does not
	require the block to come last.  Add sanity checks.
	* cfgrtl.c (rtl_split_edge): Add special handling of fall through
	edges to the exit block.
	* function.c (cfglayout.h): #include.
	(thread_prologue_and_epilogue_insns): If we have neither return nor
	epilogue, but a fall through to the exit block from mid-function,
	force a non-fall-through exit.
	* Makefile.in (function.o): Depend on CFGLAYOUT_H.

From-SVN: r83089
parent ce2a46a2
2004-06-14 J"orn Rennecke <joern.rennecke@superh.com>
* basic-block.h (could_fall_through): Declare.
* cfganal.c (can_fallthru): Succeed if the target is EXIT_BLOCK_PTR.
Fail if the source already has a fallthrough edge to the exit
block pointer.
(could_fall_through): New function.
* cfgbuild.c (make_edges): Check if we already have a fallthrough
edge to the exit block pointer.
* cfglayout.c (fixup_fallthru_exit_predecessor): Check that it is
not called before reload has completed.
Handle special case of first block having a fall-through exit edge.
(cfg_layout_finalize): Don't call it before reload or if we have
rtl epilogues.
(fixup_reorder_chain): A fall through to the exit block does not
require the block to come last. Add sanity checks.
* cfgrtl.c (rtl_split_edge): Add special handling of fall through
edges to the exit block.
* function.c (cfglayout.h): #include.
(thread_prologue_and_epilogue_insns): If we have neither return nor
epilogue, but a fall through to the exit block from mid-function,
force a non-fall-through exit.
* Makefile.in (function.o): Depend on CFGLAYOUT_H.
2004-06-14 Alan Modra <amodra@bigpond.net.au> 2004-06-14 Alan Modra <amodra@bigpond.net.au>
* config/rs6000/rs6000.h (ASM_CPU_SPEC): Handle -mpowerpc64 and -mcpu * config/rs6000/rs6000.h (ASM_CPU_SPEC): Handle -mpowerpc64 and -mcpu
......
...@@ -1759,7 +1759,8 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_ ...@@ -1759,7 +1759,8 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_
flags.h function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \ flags.h function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \ output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
$(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(CFGLAYOUT_H) \
flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \ flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \ insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
$(TM_P_H) langhooks.h gt-function.h $(TARGET_H) basic-block.h $(TM_P_H) langhooks.h gt-function.h $(TARGET_H) basic-block.h
......
...@@ -629,6 +629,7 @@ extern void find_sub_basic_blocks (basic_block); ...@@ -629,6 +629,7 @@ extern void find_sub_basic_blocks (basic_block);
extern void find_many_sub_basic_blocks (sbitmap); extern void find_many_sub_basic_blocks (sbitmap);
extern void rtl_make_eh_edge (sbitmap *, basic_block, rtx); extern void rtl_make_eh_edge (sbitmap *, basic_block, rtx);
extern bool can_fallthru (basic_block, basic_block); extern bool can_fallthru (basic_block, basic_block);
extern bool could_fall_through (basic_block, basic_block);
extern void flow_nodes_print (const char *, const sbitmap, FILE *); extern void flow_nodes_print (const char *, const sbitmap, FILE *);
extern void flow_edge_list_print (const char *, const edge *, int, FILE *); extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
extern void alloc_aux_for_block (basic_block, int); extern void alloc_aux_for_block (basic_block, int);
......
...@@ -103,11 +103,19 @@ bool ...@@ -103,11 +103,19 @@ bool
can_fallthru (basic_block src, basic_block target) can_fallthru (basic_block src, basic_block target)
{ {
rtx insn = BB_END (src); rtx insn = BB_END (src);
rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : BB_HEAD (target); rtx insn2;
edge e;
if (target == EXIT_BLOCK_PTR)
return true;
if (src->next_bb != target) if (src->next_bb != target)
return 0; return 0;
for (e = src->succ; e; e = e->succ_next)
if (e->dest == EXIT_BLOCK_PTR
&& e->flags & EDGE_FALLTHRU)
return 0;
insn2 = BB_HEAD (target);
if (insn2 && !active_insn_p (insn2)) if (insn2 && !active_insn_p (insn2))
insn2 = next_active_insn (insn2); insn2 = next_active_insn (insn2);
...@@ -115,6 +123,23 @@ can_fallthru (basic_block src, basic_block target) ...@@ -115,6 +123,23 @@ can_fallthru (basic_block src, basic_block target)
return next_active_insn (insn) == insn2; return next_active_insn (insn) == insn2;
} }
/* Return nonzero if we could reach target from src by falling through,
if the target was made adjacent. If we already have a fall-through
edge to the exit block, we can't do that. */
bool
could_fall_through (basic_block src, basic_block target)
{
edge e;
if (target == EXIT_BLOCK_PTR)
return true;
for (e = src->succ; e; e = e->succ_next)
if (e->dest == EXIT_BLOCK_PTR
&& e->flags & EDGE_FALLTHRU)
return 0;
return true;
}
/* Mark the back edges in DFS traversal. /* Mark the back edges in DFS traversal.
Return nonzero if a loop (natural or otherwise) is present. Return nonzero if a loop (natural or otherwise) is present.
Inspired by Depth_First_Search_PP described in: Inspired by Depth_First_Search_PP described in:
......
...@@ -267,6 +267,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p ...@@ -267,6 +267,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
rtx insn, x; rtx insn, x;
enum rtx_code code; enum rtx_code code;
int force_fallthru = 0; int force_fallthru = 0;
edge e;
if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL
&& LABEL_ALT_ENTRY_P (BB_HEAD (bb))) && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
...@@ -389,6 +390,12 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p ...@@ -389,6 +390,12 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
/* Find out if we can drop through to the next block. */ /* Find out if we can drop through to the next block. */
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
for (e = bb->succ; e; e = e->succ_next)
if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_FALLTHRU)
{
insn = 0;
break;
}
while (insn while (insn
&& GET_CODE (insn) == NOTE && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK) && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
......
...@@ -714,6 +714,10 @@ fixup_reorder_chain (void) ...@@ -714,6 +714,10 @@ fixup_reorder_chain (void)
&& invert_jump (bb_end_insn, && invert_jump (bb_end_insn,
label_for_bb (e_fall->dest), 0)) label_for_bb (e_fall->dest), 0))
{ {
#ifdef ENABLE_CHECKING
if (!could_fall_through (e_taken->src, e_taken->dest))
abort ();
#endif
e_fall->flags &= ~EDGE_FALLTHRU; e_fall->flags &= ~EDGE_FALLTHRU;
e_taken->flags |= EDGE_FALLTHRU; e_taken->flags |= EDGE_FALLTHRU;
update_br_prob_note (bb); update_br_prob_note (bb);
...@@ -731,6 +735,10 @@ fixup_reorder_chain (void) ...@@ -731,6 +735,10 @@ fixup_reorder_chain (void)
else if (invert_jump (bb_end_insn, else if (invert_jump (bb_end_insn,
label_for_bb (e_fall->dest), 0)) label_for_bb (e_fall->dest), 0))
{ {
#ifdef ENABLE_CHECKING
if (!could_fall_through (e_taken->src, e_taken->dest))
abort ();
#endif
e_fall->flags &= ~EDGE_FALLTHRU; e_fall->flags &= ~EDGE_FALLTHRU;
e_taken->flags |= EDGE_FALLTHRU; e_taken->flags |= EDGE_FALLTHRU;
update_br_prob_note (bb); update_br_prob_note (bb);
...@@ -770,7 +778,7 @@ fixup_reorder_chain (void) ...@@ -770,7 +778,7 @@ fixup_reorder_chain (void)
continue; continue;
/* A fallthru to exit block. */ /* A fallthru to exit block. */
if (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR) if (e_fall->dest == EXIT_BLOCK_PTR)
continue; continue;
} }
...@@ -910,14 +918,20 @@ verify_insn_chain (void) ...@@ -910,14 +918,20 @@ verify_insn_chain (void)
abort (); abort ();
} }
/* The block falling through to exit must be the last one in the /* If we have assembler epilogues, the block falling through to exit must
reordered chain. Ensure that this condition is met. */ be the last one in the reordered chain when we reach final. Ensure
that this condition is met. */
static void static void
fixup_fallthru_exit_predecessor (void) fixup_fallthru_exit_predecessor (void)
{ {
edge e; edge e;
basic_block bb = NULL; basic_block bb = NULL;
/* This transformation is not valid before reload, because we might separate
a call from the instruction that copies the return value. */
if (! reload_completed)
abort ();
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
bb = e->src; bb = e->src;
...@@ -926,6 +940,18 @@ fixup_fallthru_exit_predecessor (void) ...@@ -926,6 +940,18 @@ fixup_fallthru_exit_predecessor (void)
{ {
basic_block c = ENTRY_BLOCK_PTR->next_bb; basic_block c = ENTRY_BLOCK_PTR->next_bb;
/* If the very first block is the one with the fall-through exit
edge, we have to split that block. */
if (c == bb)
{
bb = split_block (bb, NULL)->dest;
initialize_bb_rbi (bb);
bb->rbi->next = c->rbi->next;
c->rbi->next = bb;
bb->rbi->footer = c->rbi->footer;
c->rbi->footer = NULL;
}
while (c->rbi->next != bb) while (c->rbi->next != bb)
c = c->rbi->next; c = c->rbi->next;
...@@ -1176,6 +1202,11 @@ cfg_layout_finalize (void) ...@@ -1176,6 +1202,11 @@ cfg_layout_finalize (void)
verify_flow_info (); verify_flow_info ();
#endif #endif
rtl_register_cfg_hooks (); rtl_register_cfg_hooks ();
if (reload_completed
#ifdef HAVE_epilogue
&& !HAVE_epilogue
#endif
)
fixup_fallthru_exit_predecessor (); fixup_fallthru_exit_predecessor ();
fixup_reorder_chain (); fixup_reorder_chain ();
......
...@@ -1336,6 +1336,18 @@ rtl_split_edge (edge edge_in) ...@@ -1336,6 +1336,18 @@ rtl_split_edge (edge edge_in)
else else
before = NULL_RTX; before = NULL_RTX;
/* If this is a fall through edge to the exit block, the blocks might be
not adjacent, and the right place is the after the source. */
if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR)
{
before = NEXT_INSN (BB_END (edge_in->src));
if (before
&& GET_CODE (before) == NOTE
&& NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END)
before = NEXT_INSN (before);
bb = create_basic_block (before, NULL, edge_in->src);
}
else
bb = create_basic_block (before, NULL, edge_in->dest->prev_bb); bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
/* ??? This info is likely going to be out of date very soon. */ /* ??? This info is likely going to be out of date very soon. */
......
...@@ -63,6 +63,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -63,6 +63,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "integrate.h" #include "integrate.h"
#include "langhooks.h" #include "langhooks.h"
#include "target.h" #include "target.h"
#include "cfglayout.h"
#ifndef LOCAL_ALIGNMENT #ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
...@@ -7558,9 +7559,6 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED) ...@@ -7558,9 +7559,6 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
} }
} }
#endif #endif
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
/* Find the edge that falls through to EXIT. Other edges may exist /* Find the edge that falls through to EXIT. Other edges may exist
due to RETURN instructions, but those don't need epilogues. due to RETURN instructions, but those don't need epilogues.
There really shouldn't be a mixture -- either all should have There really shouldn't be a mixture -- either all should have
...@@ -7572,6 +7570,9 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED) ...@@ -7572,6 +7570,9 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
if (e == NULL) if (e == NULL)
goto epilogue_done; goto epilogue_done;
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
start_sequence (); start_sequence ();
epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG); epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
...@@ -7597,7 +7598,26 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED) ...@@ -7597,7 +7598,26 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
insert_insn_on_edge (seq, e); insert_insn_on_edge (seq, e);
inserted = 1; inserted = 1;
} }
else
#endif #endif
{
basic_block cur_bb;
if (! next_active_insn (BB_END (e->src)))
goto epilogue_done;
/* We have a fall-through edge to the exit block, the source is not
at the end of the function, and there will be an assembler epilogue
at the end of the function.
We can't use force_nonfallthru here, because that would try to
use return. Inserting a jump 'by hand' is extremely messy, so
we take advantage of cfg_layout_finalize using
fixup_fallthru_exit_predecessor. */
cfg_layout_initialize ();
FOR_EACH_BB (cur_bb)
if (cur_bb->index >= 0 && cur_bb->next_bb->index >= 0)
cur_bb->rbi->next = cur_bb->next_bb;
cfg_layout_finalize ();
}
epilogue_done: epilogue_done:
if (inserted) if (inserted)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment