aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ"orn Rennecke <joern.rennecke@superh.com>2004-06-11 17:04:28 +0000
committerJ"orn Rennecke <joern.rennecke@superh.com>2004-06-11 17:04:28 +0000
commit338e425e063d30632011ea280c516b7e4453eba6 (patch)
tree6e624df4023bf832921a9a036175ea60b5b75539
parentdbc31bef859f8b4093a1f20a36abaee55e41173a (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/sh-elf-3_5-branch@82977 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.sh-elf23
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/basic-block.h1
-rw-r--r--gcc/cfganal.c27
-rw-r--r--gcc/cfgbuild.c7
-rw-r--r--gcc/cfglayout.c39
-rw-r--r--gcc/cfgrtl.c14
-rw-r--r--gcc/function.c42
8 files changed, 138 insertions, 18 deletions
diff --git a/gcc/ChangeLog.sh-elf b/gcc/ChangeLog.sh-elf
index 1f6aad7f6a5..c94ea069d61 100644
--- a/gcc/ChangeLog.sh-elf
+++ b/gcc/ChangeLog.sh-elf
@@ -16,6 +16,29 @@
* cfgrtl.c (rtl_split_edge): Add special handling of fall through
edges to the exit block.
+ Apply this one instead:
+ * 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-08 J"orn Rennecke <joern.rennecke@superh.com>
* sh.c (dump_table): New argument start. Changed caller.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 2fa566aeea1..61f1c25a923 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1757,7 +1757,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
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index f087f8b5180..f6ac31692ad 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -626,6 +626,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);
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index 1a7d280513f..c8675dca6e2 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -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.
diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 0cef94eafd3..8402dad578f 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -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)
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index 899aa1a5665..66742686e16 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -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
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index cdfde6fba05..6e22d80ac84 100644
--- a/gcc/cfgrtl.c
+++ b/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)
diff --git a/gcc/function.c b/gcc/function.c
index 69866f9812d..38e82d6b8e2 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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
@@ -7564,20 +7565,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);
@@ -7603,7 +7604,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)