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
This commit is contained in:
J"orn Rennecke 2004-06-14 12:09:08 +00:00 committed by Joern Rennecke
parent ce2a46a203
commit 623a66fa85
8 changed files with 139 additions and 18 deletions

View File

@ -1,3 +1,27 @@
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>
* config/rs6000/rs6000.h (ASM_CPU_SPEC): Handle -mpowerpc64 and -mcpu

View File

@ -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) \
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
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 \
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

View File

@ -629,6 +629,7 @@ extern void find_sub_basic_blocks (basic_block);
extern void find_many_sub_basic_blocks (sbitmap);
extern void rtl_make_eh_edge (sbitmap *, basic_block, rtx);
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_edge_list_print (const char *, const edge *, int, FILE *);
extern void alloc_aux_for_block (basic_block, int);

View File

@ -103,17 +103,42 @@ bool
can_fallthru (basic_block src, basic_block target)
{
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)
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))
insn2 = next_active_insn (insn2);
/* ??? Later we may add code to move jump tables offline. */
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.
Return nonzero if a loop (natural or otherwise) is present.

View File

@ -267,6 +267,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
rtx insn, x;
enum rtx_code code;
int force_fallthru = 0;
edge e;
if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL
&& 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
/* Find out if we can drop through to the next block. */
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
&& GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)

View File

@ -714,6 +714,10 @@ fixup_reorder_chain (void)
&& invert_jump (bb_end_insn,
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_taken->flags |= EDGE_FALLTHRU;
update_br_prob_note (bb);
@ -731,6 +735,10 @@ fixup_reorder_chain (void)
else if (invert_jump (bb_end_insn,
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_taken->flags |= EDGE_FALLTHRU;
update_br_prob_note (bb);
@ -770,7 +778,7 @@ fixup_reorder_chain (void)
continue;
/* A fallthru to exit block. */
if (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR)
if (e_fall->dest == EXIT_BLOCK_PTR)
continue;
}
@ -910,14 +918,20 @@ verify_insn_chain (void)
abort ();
}
/* The block falling through to exit must be the last one in the
reordered chain. Ensure that this condition is met. */
/* If we have assembler epilogues, the block falling through to exit must
be the last one in the reordered chain when we reach final. Ensure
that this condition is met. */
static void
fixup_fallthru_exit_predecessor (void)
{
edge e;
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)
if (e->flags & EDGE_FALLTHRU)
bb = e->src;
@ -926,6 +940,18 @@ fixup_fallthru_exit_predecessor (void)
{
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)
c = c->rbi->next;
@ -1176,7 +1202,12 @@ cfg_layout_finalize (void)
verify_flow_info ();
#endif
rtl_register_cfg_hooks ();
fixup_fallthru_exit_predecessor ();
if (reload_completed
#ifdef HAVE_epilogue
&& !HAVE_epilogue
#endif
)
fixup_fallthru_exit_predecessor ();
fixup_reorder_chain ();
#ifdef ENABLE_CHECKING

View File

@ -1336,7 +1336,19 @@ rtl_split_edge (edge edge_in)
else
before = NULL_RTX;
bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
/* 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);
/* ??? This info is likely going to be out of date very soon. */
if (edge_in->dest->global_live_at_start)

View File

@ -63,6 +63,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "integrate.h"
#include "langhooks.h"
#include "target.h"
#include "cfglayout.h"
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
@ -7558,20 +7559,20 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
}
}
#endif
/* Find the edge that falls through to EXIT. Other edges may exist
due to RETURN instructions, but those don't need epilogues.
There really shouldn't be a mixture -- either all should have
been converted or none, however... */
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU)
break;
if (e == NULL)
goto epilogue_done;
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
/* Find the edge that falls through to EXIT. Other edges may exist
due to RETURN instructions, but those don't need epilogues.
There really shouldn't be a mixture -- either all should have
been converted or none, however... */
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
if (e->flags & EDGE_FALLTHRU)
break;
if (e == NULL)
goto epilogue_done;
start_sequence ();
epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
@ -7597,7 +7598,26 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
insert_insn_on_edge (seq, e);
inserted = 1;
}
else
#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:
if (inserted)