aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-01-28 14:22:50 -0800
committerRichard Henderson <rth@gcc.gnu.org>2000-01-28 14:22:50 -0800
commit19d3c25c9a4da9526a2012b47d14bc731fd0422e (patch)
tree838b5c749cb462341ad1b64dc6cc0bd1daa6820f
parent47e6ea667d23d2fd20ad3664e39654cc8a44502f (diff)
downloadgcc-19d3c25c9a4da9526a2012b47d14bc731fd0422e.zip
gcc-19d3c25c9a4da9526a2012b47d14bc731fd0422e.tar.gz
gcc-19d3c25c9a4da9526a2012b47d14bc731fd0422e.tar.bz2
flow.c (find_basic_blocks): Remove do_cleanup argument.
* flow.c (find_basic_blocks): Remove do_cleanup argument. Break out that code ... (cleanup_cfg): ... here. (commit_one_edge_insertion): Detect a return instruction being emitted to an edge. Emit a barrier following; clear fallthru. (commit_edge_insertions): Verify CFG consistency. * function.c (expand_function_start): Kill unused variable. (expand_function_end): Likewise. (thread_prologue_and_epilogue_insns): Use insert_insn_on_edge to insert the epilogue. * gcse.c (gcse_main): Adjust for find_basic_blocks change. (delete_null_pointer_checks): Likewise. * output.h: Likewise. * reg-stack.c (reg_to_stack): Likewise. * toplev.c (rest_of_compilation): Likewise. Run thread_prologue_and_epilogue_insns after rebuilding the CFG. From-SVN: r31676
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/flow.c77
-rw-r--r--gcc/function.c148
-rw-r--r--gcc/gcse.c6
-rw-r--r--gcc/output.h3
-rw-r--r--gcc/reg-stack.c2
-rw-r--r--gcc/toplev.c23
7 files changed, 125 insertions, 154 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c1e8282..8f43f07 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,25 @@
2000-01-28 Richard Henderson <rth@cygnus.com>
+ * flow.c (find_basic_blocks): Remove do_cleanup argument.
+ Break out that code ...
+ (cleanup_cfg): ... here.
+ (commit_one_edge_insertion): Detect a return instruction being
+ emitted to an edge. Emit a barrier following; clear fallthru.
+ (commit_edge_insertions): Verify CFG consistency.
+ * function.c (expand_function_start): Kill unused variable.
+ (expand_function_end): Likewise.
+ (thread_prologue_and_epilogue_insns): Use insert_insn_on_edge
+ to insert the epilogue.
+
+ * gcse.c (gcse_main): Adjust for find_basic_blocks change.
+ (delete_null_pointer_checks): Likewise.
+ * output.h: Likewise.
+ * reg-stack.c (reg_to_stack): Likewise.
+ * toplev.c (rest_of_compilation): Likewise. Run
+ thread_prologue_and_epilogue_insns after rebuilding the CFG.
+
+2000-01-28 Richard Henderson <rth@cygnus.com>
+
* Makefile.in (flow.o): Revert 24 Jan change.
* flow.c (mark_regs_live_at_end): Likewise. Force BLKmode
FUNCTION_VALUE result to DECL_RESULT's mode.
diff --git a/gcc/flow.c b/gcc/flow.c
index 008f0c2..0578bef 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -372,11 +372,10 @@ int flow_loop_outside_edge_p PARAMS ((const struct loop *, edge));
numbers in use. */
void
-find_basic_blocks (f, nregs, file, do_cleanup)
+find_basic_blocks (f, nregs, file)
rtx f;
int nregs ATTRIBUTE_UNUSED;
FILE *file ATTRIBUTE_UNUSED;
- int do_cleanup;
{
int max_uid;
@@ -425,23 +424,8 @@ find_basic_blocks (f, nregs, file, do_cleanup)
compute_bb_for_insn (max_uid);
/* Discover the edges of our cfg. */
-
record_active_eh_regions (f);
make_edges (label_value_list);
-
- /* Delete unreachable blocks, then merge blocks when possible. */
-
- if (do_cleanup)
- {
- delete_unreachable_blocks ();
- move_stray_eh_region_notes ();
- record_active_eh_regions (f);
- if (optimize)
- try_merge_blocks ();
- }
-
- /* Mark critical edges. */
-
mark_critical_edges ();
/* Kill the data we won't maintain. */
@@ -740,6 +724,19 @@ find_basic_blocks_1 (f)
return label_value_list;
}
+/* Tidy the CFG by deleting unreachable code and whatnot. */
+
+void
+cleanup_cfg (f)
+ rtx f;
+{
+ delete_unreachable_blocks ();
+ move_stray_eh_region_notes ();
+ record_active_eh_regions (f);
+ try_merge_blocks ();
+ mark_critical_edges ();
+}
+
/* Create a new basic block consisting of the instructions between
HEAD and END inclusive. Reuses the note and basic block struct
in BB_NOTE, if any. */
@@ -1552,9 +1549,13 @@ static void
commit_one_edge_insertion (e)
edge e;
{
- rtx before = NULL_RTX, after = NULL_RTX, tmp;
+ rtx before = NULL_RTX, after = NULL_RTX, insns, tmp;
basic_block bb;
+ /* Pull the insns off the edge now since the edge might go away. */
+ insns = e->insns;
+ e->insns = NULL_RTX;
+
/* Figure out where to put these things. If the destination has
one predecessor, insert there. Except for the exit block. */
if (e->dest->pred->pred_next == NULL
@@ -1611,28 +1612,50 @@ commit_one_edge_insertion (e)
}
/* Now that we've found the spot, do the insertion. */
- tmp = e->insns;
- e->insns = NULL_RTX;
/* Set the new block number for these insns, if structure is allocated. */
if (basic_block_for_insn)
{
rtx i;
- for (i = tmp; i != NULL_RTX; i = NEXT_INSN (i))
+ for (i = insns; i != NULL_RTX; i = NEXT_INSN (i))
set_block_for_insn (i, bb);
}
if (before)
{
- emit_insns_before (tmp, before);
+ emit_insns_before (insns, before);
if (before == bb->head)
- bb->head = tmp;
+ bb->head = insns;
}
else
{
- tmp = emit_insns_after (tmp, after);
+ rtx last = emit_insns_after (insns, after);
if (after == bb->end)
- bb->end = tmp;
+ {
+ bb->end = last;
+
+ if (GET_CODE (last) == JUMP_INSN)
+ {
+ if (returnjump_p (last))
+ {
+ /* ??? Remove all outgoing edges from BB and add one
+ for EXIT. This is not currently a problem because
+ this only happens for the (single) epilogue, which
+ already has a fallthru edge to EXIT. */
+
+ e = bb->succ;
+ if (e->dest != EXIT_BLOCK_PTR
+ || e->succ_next != NULL
+ || (e->flags & EDGE_FALLTHRU) == 0)
+ abort ();
+ e->flags &= ~EDGE_FALLTHRU;
+
+ emit_barrier_after (last);
+ }
+ else
+ abort ();
+ }
+ }
}
}
@@ -1644,6 +1667,10 @@ commit_edge_insertions ()
int i;
basic_block bb;
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
+
i = -1;
bb = ENTRY_BLOCK_PTR;
while (1)
diff --git a/gcc/function.c b/gcc/function.c
index 8339208..960fd1c 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5867,7 +5867,6 @@ expand_function_start (subr, parms_have_cleanups)
tree subr;
int parms_have_cleanups;
{
- register int i;
tree tem;
rtx last_ptr = NULL_RTX;
@@ -6171,7 +6170,6 @@ expand_function_end (filename, line, end_bindings)
int line;
int end_bindings;
{
- register int i;
tree link;
#ifdef TRAMPOLINE_TEMPLATE
@@ -6546,12 +6544,12 @@ thread_prologue_and_epilogue_insns (f)
rtx f ATTRIBUTE_UNUSED;
{
int insertted = 0;
+ edge e;
+ rtx seq;
#ifdef HAVE_prologue
if (HAVE_prologue)
{
- rtx seq;
-
start_sequence ();
seq = gen_prologue();
emit_insn (seq);
@@ -6581,129 +6579,47 @@ thread_prologue_and_epilogue_insns (f)
}
#endif
+ /* If the exit block has no non-fake predecessors, we don't need
+ an epilogue. */
+ for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ if ((e->flags & EDGE_FAKE) == 0)
+ break;
+ if (e == NULL)
+ goto epilogue_done;
+
#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
- edge e;
- basic_block bb = 0;
- rtx tail = get_last_insn ();
-
- /* ??? This is gastly. If function returns were not done via uses,
- but via mark_regs_live_at_end, we could use insert_insn_on_edge
- and all of this uglyness would go away. */
-
- switch (optimize)
- {
- default:
- /* If the exit block has no non-fake predecessors, we don't
- need an epilogue. Furthermore, only pay attention to the
- fallthru predecessors; if (conditional) return insns were
- generated, by definition we do not need to emit epilogue
- insns. */
-
- for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
- if ((e->flags & EDGE_FAKE) == 0
- && (e->flags & EDGE_FALLTHRU) != 0)
- break;
- if (e == NULL)
- break;
-
- /* We can't handle multiple epilogues -- if one is needed,
- we won't be able to place it multiple times.
-
- ??? Fix epilogue expanders to not assume they are the
- last thing done compiling the function. Either that
- or copy_rtx each insn.
-
- ??? Blah, it's not a simple expression to assert that
- we've exactly one fallthru exit edge. */
+ /* 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... */
- bb = e->src;
- tail = bb->end;
-
- /* ??? If the last insn of the basic block is a jump, then we
- are creating a new basic block. Wimp out and leave these
- insns outside any block. */
- if (GET_CODE (tail) == JUMP_INSN)
- bb = 0;
-
- /* FALLTHRU */
- case 0:
- {
- rtx prev, seq, first_use;
-
- /* Move the USE insns at the end of a function onto a list. */
- prev = tail;
- if (GET_CODE (prev) == BARRIER
- || GET_CODE (prev) == NOTE)
- prev = prev_nonnote_insn (prev);
-
- first_use = 0;
- if (prev
- && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == USE)
- {
- /* If the end of the block is the use, grab hold of something
- else so that we emit barriers etc in the right place. */
- if (prev == tail)
- {
- do
- tail = PREV_INSN (tail);
- while (GET_CODE (tail) == INSN
- && GET_CODE (PATTERN (tail)) == USE);
- }
-
- do
- {
- rtx use = prev;
- prev = prev_nonnote_insn (prev);
-
- remove_insn (use);
- if (first_use)
- {
- NEXT_INSN (use) = first_use;
- PREV_INSN (first_use) = use;
- }
- else
- NEXT_INSN (use) = NULL_RTX;
- first_use = use;
- }
- while (prev
- && GET_CODE (prev) == INSN
- && GET_CODE (PATTERN (prev)) == USE);
- }
-
- /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
- epilogue insns, the USE insns at the end of a function,
- the jump insn that returns, and then a BARRIER. */
+ for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+ if (e == NULL)
+ goto epilogue_done;
- if (GET_CODE (tail) != BARRIER)
- {
- prev = next_nonnote_insn (tail);
- if (!prev || GET_CODE (prev) != BARRIER)
- emit_barrier_after (tail);
- }
+ start_sequence ();
+ emit_note (NULL, NOTE_INSN_EPILOGUE_BEG);
- seq = gen_epilogue ();
- prev = tail;
- tail = emit_jump_insn_after (seq, tail);
+ seq = gen_epilogue ();
+ emit_jump_insn (seq);
- /* Insert the USE insns immediately before the return insn, which
- must be the last instruction emitted in the sequence. */
- if (first_use)
- emit_insns_before (first_use, tail);
- emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
+ /* Retain a map of the epilogue insns. */
+ if (GET_CODE (seq) != SEQUENCE)
+ seq = get_insns ();
+ epilogue = record_insns (seq);
- /* Update the tail of the basic block. */
- if (bb)
- bb->end = tail;
+ seq = gen_sequence ();
+ end_sequence();
- /* Retain a map of the epilogue insns. */
- epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
- }
- }
+ insert_insn_on_edge (seq, e);
+ insertted = 1;
}
#endif
+epilogue_done:
if (insertted)
commit_edge_insertions ();
diff --git a/gcc/gcse.c b/gcc/gcse.c
index a61463d..482a590 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -673,7 +673,8 @@ gcse_main (f, file)
/* Identify the basic block information for this function, including
successors and predecessors. */
max_gcse_regno = max_reg_num ();
- find_basic_blocks (f, max_gcse_regno, file, 1);
+ find_basic_blocks (f, max_gcse_regno, file);
+ cleanup_cfg (f);
if (file)
dump_flow_info (file);
@@ -5201,7 +5202,8 @@ delete_null_pointer_checks (f)
struct null_pointer_info npi;
/* First break the program into basic blocks. */
- find_basic_blocks (f, max_reg_num (), NULL, 1);
+ find_basic_blocks (f, max_reg_num (), NULL);
+ cleanup_cfg (f);
/* If we have only a single block, then there's nothing to do. */
if (n_basic_blocks <= 1)
diff --git a/gcc/output.h b/gcc/output.h
index dbc373d..ecd3253 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -131,7 +131,8 @@ extern void allocate_for_life_analysis PARAMS ((void));
extern int regno_uninitialized PARAMS ((int));
extern int regno_clobbered_at_setjmp PARAMS ((int));
extern void dump_flow_info PARAMS ((FILE *));
-extern void find_basic_blocks PARAMS ((rtx, int, FILE *, int));
+extern void find_basic_blocks PARAMS ((rtx, int, FILE *));
+extern void cleanup_cfg PARAMS ((rtx));
extern void calculate_loop_depth PARAMS ((FILE *));
extern void free_basic_block_vars PARAMS ((int));
extern void set_block_num PARAMS ((rtx, int));
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 2edd579..ab27407 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -430,7 +430,7 @@ reg_to_stack (first, file)
/* Ok, floating point instructions exist. If not optimizing,
build the CFG and run life analysis. */
- find_basic_blocks (first, max_reg_num (), file, 0);
+ find_basic_blocks (first, max_reg_num (), file);
count_or_remove_death_notes (NULL, 1);
life_analysis (first, max_reg_num (), file, 0);
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 189c3e7..136d966 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3216,7 +3216,8 @@ rest_of_compilation (decl)
TIMEVAR
(flow_time,
{
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ cleanup_cfg (insns);
if (optimize)
calculate_loop_depth (rtl_dump_file);
life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
@@ -3384,13 +3385,6 @@ rest_of_compilation (decl)
if (rebuild_label_notes_after_reload)
TIMEVAR (jump_time, rebuild_jump_labels (insns));
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- scheduling to operate in the epilogue. */
-
- thread_prologue_and_epilogue_insns (insns);
-
/* If optimizing and we are performing instruction scheduling after
reload, then go ahead and split insns now since we are about to
recompute flow information anyway.
@@ -3412,12 +3406,23 @@ rest_of_compilation (decl)
if (flow2_dump)
open_dump_file (".14.flow2", decl_printable_name (decl, 2));
+ TIMEVAR (flow2_time,
+ {
+ find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ });
+
+ /* On some machines, the prologue and epilogue code, or parts thereof,
+ can be represented as RTL. Doing so lets us schedule insns between
+ it and the rest of the code and also allows delayed branch
+ scheduling to operate in the epilogue. */
+ thread_prologue_and_epilogue_insns (insns);
+
if (optimize)
{
TIMEVAR
(flow2_time,
{
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+ cleanup_cfg (insns);
life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
});