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:
parent
ce2a46a203
commit
623a66fa85
8 changed files with 139 additions and 18 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
14
gcc/cfgrtl.c
14
gcc/cfgrtl.c
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue