summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-07-23 14:08:12 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2001-07-23 14:08:12 +0000
commitb08cd5843569977ca1c079e1dd269a55fdaa2995 (patch)
tree3dbb57e04c149a6d0f4908ed9c0351fc46670790 /gcc
parent4bfc3ff0532c344a3e605297432468d95e4e33c0 (diff)
downloadgcc-b08cd5843569977ca1c079e1dd269a55fdaa2995.tar.gz
* basic-block.h (find_sub_basic_block): Declare.
* flow.c (make_edges): New arguments MIN and MAX; (find_sub_basic_blocks): Revamp to use make_edges and purge_dead_edges. (find_basic_blocks): Update call of find_sub_basic_block. * recog.c (split_all_insns): Always expect CFG to be consistent; call find_sub_basic_blocks in case something has changed. * toplev.c (rest_of_compilation): Always call split_all_insns once CFG has been built. * basic-block.h (delete_noop_moves): Declare. * combine.c (combine_instructions): Call it. (recog_for_combine): Tolerate noop moves (distribute_notes): Force refresh when register dies at noop move. * flow.c (delete_noop_moves): Use BB structure; delete JUMP insns too. (life_analysis): Update delete_noop_moves call. (set_noop_p): Move too ... * rtlanal.c (noop_move_p): ... here. * rtl.h (noop_move_p): Declare. * basic-block.h (purge_all_dead_edges, purge_dead_edges): New functions. * toplev.c (rest_of_compilation): Conditionally call purge_all_dead_edges after combine. * gcse.c (cprop_cc0_jump, cprop_insn): New argument "basic_block". (cprop_jump): Likewise; call purge_dead_edges if substitution suceeded. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44267 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog30
-rw-r--r--gcc/basic-block.h4
-rw-r--r--gcc/combine.c30
-rw-r--r--gcc/flow.c220
-rw-r--r--gcc/gcse.c22
-rw-r--r--gcc/recog.c27
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c39
-rw-r--r--gcc/toplev.c17
9 files changed, 247 insertions, 143 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b400b34f1f6..5de1093c069 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,33 @@
+Mon Jul 23 16:03:19 CEST 2001 Jan Hubicka <jh@suse.cz>
+
+ * basic-block.h (find_sub_basic_block): Declare.
+ * flow.c (make_edges): New arguments MIN and MAX;
+ (find_sub_basic_blocks): Revamp to use make_edges
+ and purge_dead_edges.
+ (find_basic_blocks): Update call of find_sub_basic_block.
+
+ * recog.c (split_all_insns): Always expect CFG to be consistent;
+ call find_sub_basic_blocks in case something has changed.
+ * toplev.c (rest_of_compilation): Always call split_all_insns once CFG
+ has been built.
+
+ * basic-block.h (delete_noop_moves): Declare.
+ * combine.c (combine_instructions): Call it.
+ (recog_for_combine): Tolerate noop moves
+ (distribute_notes): Force refresh when register dies at noop move.
+ * flow.c (delete_noop_moves): Use BB structure; delete JUMP insns
+ too.
+ (life_analysis): Update delete_noop_moves call.
+ (set_noop_p): Move too ...
+ * rtlanal.c (noop_move_p): ... here.
+ * rtl.h (noop_move_p): Declare.
+
+ * basic-block.h (purge_all_dead_edges, purge_dead_edges): New functions.
+ * toplev.c (rest_of_compilation): Conditionally call purge_all_dead_edges
+ after combine.
+ * gcse.c (cprop_cc0_jump, cprop_insn): New argument "basic_block".
+ (cprop_jump): Likewise; call purge_dead_edges if substitution suceeded.
+
2001-07-23 Hans-Peter Nilsson <hp@bitrange.com>
* reload.c (push_reload): Fix typo in comment.
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 6a6039eff04..b6e8c11a16b 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -597,10 +597,14 @@ extern void debug_regset PARAMS ((regset));
extern void allocate_reg_life_data PARAMS ((void));
extern void allocate_bb_life_data PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void));
+extern void delete_noop_moves PARAMS ((rtx));
extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
extern rtx block_label PARAMS ((basic_block));
extern bool forwarder_block_p PARAMS ((basic_block));
+extern void purge_all_dead_edges PARAMS ((void));
+extern void purge_dead_edges PARAMS ((basic_block));
+extern void find_sub_basic_blocks PARAMS ((basic_block));
/* This function is always defined so it can be called from the
diff --git a/gcc/combine.c b/gcc/combine.c
index 724e9ef1397..633d0acfd70 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -713,6 +713,8 @@ combine_instructions (f, nregs)
}
}
+ delete_noop_moves (f);
+
if (need_refresh)
{
compute_bb_for_insn (get_max_uid ());
@@ -9598,8 +9600,12 @@ recog_for_combine (pnewpat, insn, pnotes)
old_notes = REG_NOTES (insn);
REG_NOTES (insn) = 0;
- /* Is the result of combination a valid instruction? */
- insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+ /* Is the result of combination a valid instruction?
+ Recognize all noop sets, these will be killed by followup pass. */
+ if (GET_CODE (pat) == SET && set_noop_p (pat))
+ insn_code_number = INT_MAX;
+ else
+ insn_code_number = recog (pat, insn, &num_clobbers_to_add);
/* If it isn't, there is the possibility that we previously had an insn
that clobbered some register as a side effect, but the combined
@@ -9624,7 +9630,11 @@ recog_for_combine (pnewpat, insn, pnotes)
if (pos == 1)
pat = XVECEXP (pat, 0, 0);
- insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+ /* Recognize all noop sets, these will be killed by followup pass. */
+ if (GET_CODE (pat) == SET && set_noop_p (pat))
+ insn_code_number = INT_MAX;
+ else
+ insn_code_number = recog (pat, insn, &num_clobbers_to_add);
}
REG_NOTES (insn) = old_notes;
@@ -12325,10 +12335,16 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
is still a REG_DEAD note, but we have hit the beginning
of the block. If the existing life info says the reg
was dead, there's nothing left to do. Otherwise, we'll
- need to do a global life update after combine. */
- if (REG_NOTE_KIND (note) == REG_DEAD && place == 0
- && REGNO_REG_SET_P (bb->global_live_at_start,
- REGNO (XEXP (note, 0))))
+ need to do a global life update after combine.
+
+ Similary we need to update in case insn is an dead set
+ we are about to remove soon.
+ */
+ if (REG_NOTE_KIND (note) == REG_DEAD
+ && ((place && noop_move_p (place))
+ || (place == 0
+ && REGNO_REG_SET_P (bb->global_live_at_start,
+ REGNO (XEXP (note, 0))))))
{
SET_BIT (refresh_blocks, this_basic_block);
need_refresh = 1;
diff --git a/gcc/flow.c b/gcc/flow.c
index 8d795a79358..ac5cee53eed 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -374,7 +374,7 @@ static int flow_find_cross_jump PARAMS ((int, basic_block, basic_block,
static int count_basic_blocks PARAMS ((rtx));
static void find_basic_blocks_1 PARAMS ((rtx));
static rtx find_label_refs PARAMS ((rtx, rtx));
-static void make_edges PARAMS ((rtx));
+static void make_edges PARAMS ((rtx, int, int));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
rtx, int));
static void make_eh_edge PARAMS ((sbitmap *, basic_block, rtx));
@@ -401,8 +401,6 @@ static void tidy_fallthru_edges PARAMS ((void));
static int verify_wide_reg_1 PARAMS ((rtx *, void *));
static void verify_wide_reg PARAMS ((int, rtx, rtx));
static void verify_local_live_at_start PARAMS ((regset, basic_block));
-static int noop_move_p PARAMS ((rtx));
-static void delete_noop_moves PARAMS ((rtx));
static void notice_stack_pointer_modification_1 PARAMS ((rtx, rtx, void *));
static void notice_stack_pointer_modification PARAMS ((rtx));
static void mark_reg PARAMS ((rtx, void *));
@@ -483,7 +481,6 @@ static void flow_loop_tree_node_add PARAMS ((struct loop *, struct loop *));
static void flow_loops_tree_build PARAMS ((struct loops *));
static int flow_loop_level_compute PARAMS ((struct loop *, int));
static int flow_loops_level_compute PARAMS ((struct loops *));
-static void find_sub_basic_blocks PARAMS ((basic_block));
/* Find basic blocks of the current function.
F is the first insn of the function and NREGS the number of register
@@ -543,7 +540,7 @@ find_basic_blocks (f, nregs, file)
compute_bb_for_insn (max_uid);
/* Discover the edges of our cfg. */
- make_edges (label_value_list);
+ make_edges (label_value_list, 0, n_basic_blocks - 1);
/* Do very simple cleanup now, for the benefit of code that runs between
here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns. */
@@ -705,39 +702,30 @@ find_label_refs (f, lvl)
/* Assume that someone emitted code with control flow instructions to the
basic block. Update the data structure. */
-static void
+void
find_sub_basic_blocks (bb)
basic_block bb;
{
- rtx first_insn = bb->head, insn;
+ rtx insn = bb->head;
rtx end = bb->end;
- edge succ_list = bb->succ;
rtx jump_insn = NULL_RTX;
int created = 0;
int barrier = 0;
edge falltru = 0;
- basic_block first_bb = bb, last_bb;
- int i;
+ basic_block first_bb = bb;
+
+ if (insn == bb->end)
+ return;
- if (GET_CODE (first_insn) == LABEL_REF)
- first_insn = NEXT_INSN (first_insn);
- first_insn = NEXT_INSN (first_insn);
- bb->succ = NULL;
+ if (GET_CODE (insn) == CODE_LABEL)
+ insn = NEXT_INSN (insn);
- insn = first_insn;
/* Scan insn chain and try to find new basic block boundaries. */
- while (insn != end)
+ while (1)
{
enum rtx_code code = GET_CODE (insn);
switch (code)
{
- case JUMP_INSN:
- /* We need some special care for those expressions. */
- if (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- abort();
- jump_insn = insn;
- break;
case BARRIER:
if (!jump_insn)
abort ();
@@ -749,8 +737,7 @@ find_sub_basic_blocks (bb)
if (jump_insn)
bb->end = jump_insn;
bb = falltru->dest;
- if (barrier)
- remove_edge (falltru);
+ remove_edge (falltru);
barrier = 0;
jump_insn = 0;
created = 1;
@@ -758,6 +745,7 @@ find_sub_basic_blocks (bb)
make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
break;
case INSN:
+ case JUMP_INSN:
/* In case we've previously split insn on the JUMP_INSN, move the
block header to proper place. */
if (jump_insn)
@@ -765,42 +753,39 @@ find_sub_basic_blocks (bb)
falltru = split_block (bb, PREV_INSN (insn));
bb->end = jump_insn;
bb = falltru->dest;
- if (barrier)
- abort ();
+ remove_edge (falltru);
jump_insn = 0;
}
+ /* We need some special care for those expressions. */
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ abort();
+ jump_insn = insn;
+ }
+ break;
default:
break;
}
+ if (insn == end)
+ break;
insn = NEXT_INSN (insn);
}
- /* Last basic block must end in the original BB end. */
- if (jump_insn)
- abort ();
- /* Wire in the original edges for last basic block. */
- if (created)
- {
- bb->succ = succ_list;
- while (succ_list)
- succ_list->src = bb, succ_list = succ_list->succ_next;
- }
- else
- bb->succ = succ_list;
+ /* In case we've got barrier at the end of new insn stream, put it
+ outside basic block. */
+ if (GET_CODE (bb->end) == BARRIER)
+ bb->end = PREV_INSN (bb->end);
+
+ /* We've possibly replaced the conditional jump by conditional jump
+ followed by cleanup at fallthru edge, so the outgoing edges may
+ be dead. */
+ purge_dead_edges (bb);
/* Now re-scan and wire in all edges. This expect simple (conditional)
jumps at the end of each new basic blocks. */
- last_bb = bb;
- for (i = first_bb->index; i < last_bb->index; i++)
- {
- bb = BASIC_BLOCK (i);
- if (GET_CODE (bb->end) == JUMP_INSN)
- {
- mark_jump_label (PATTERN (bb->end), bb->end, 0);
- make_label_edge (NULL, bb, JUMP_LABEL (bb->end), 0);
- }
- insn = NEXT_INSN (insn);
- }
+ make_edges (NULL, first_bb->index, bb->index - 1);
}
/* Find all basic blocks of the function whose first insn is F.
@@ -1166,7 +1151,7 @@ clear_edges ()
n_edges = 0;
}
-/* Identify the edges between basic blocks.
+/* Identify the edges between basic blocks MIN to MAX.
NONLOCAL_LABEL_LIST is a list of non-local labels in the function. Blocks
that are otherwise unreachable may be reachable with a non-local goto.
@@ -1175,8 +1160,9 @@ clear_edges ()
the list of exception regions active at the end of the basic block. */
static void
-make_edges (label_value_list)
+make_edges (label_value_list, min, max)
rtx label_value_list;
+ int min, max;
{
int i;
sbitmap *edge_cache = NULL;
@@ -1196,7 +1182,7 @@ make_edges (label_value_list)
/* By nature of the way these get numbered, block 0 is always the entry. */
make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
- for (i = 0; i < n_basic_blocks; ++i)
+ for (i = min; i <= max; ++i)
{
basic_block bb = BASIC_BLOCK (i);
rtx insn, x;
@@ -4317,58 +4303,28 @@ free_basic_block_vars (keep_head_end_p)
}
}
-/* Return nonzero if an insn consists only of SETs, each of which only sets a
- value to itself. */
-
-static int
-noop_move_p (insn)
- rtx insn;
-{
- rtx pat = PATTERN (insn);
-
- /* Insns carrying these notes are useful later on. */
- if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
- return 0;
-
- if (GET_CODE (pat) == SET && set_noop_p (pat))
- return 1;
-
- if (GET_CODE (pat) == PARALLEL)
- {
- int i;
- /* If nothing but SETs of registers to themselves,
- this insn can also be deleted. */
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx tem = XVECEXP (pat, 0, i);
-
- if (GET_CODE (tem) == USE
- || GET_CODE (tem) == CLOBBER)
- continue;
-
- if (GET_CODE (tem) != SET || ! set_noop_p (tem))
- return 0;
- }
-
- return 1;
- }
- return 0;
-}
-
/* Delete any insns that copy a register to itself. */
-static void
+void
delete_noop_moves (f)
- rtx f;
+ rtx f ATTRIBUTE_UNUSED;
{
- rtx insn;
- for (insn = f; insn; insn = NEXT_INSN (insn))
+ int i;
+ rtx insn, next;
+ basic_block bb;
+
+ for (i = 0; i < n_basic_blocks; i++)
{
- if (GET_CODE (insn) == INSN && noop_move_p (insn))
+ bb = BASIC_BLOCK (i);
+ for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = next)
{
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
+ next = NEXT_INSN (insn);
+ if (INSN_P (insn) && noop_move_p (insn))
+ {
+ if (insn == bb->end)
+ bb->end = PREV_INSN (insn);
+ flow_delete_insn (insn);
+ }
}
}
}
@@ -9814,3 +9770,69 @@ init_flow ()
flow_firstobj = (char *) obstack_alloc (&flow_obstack, 0);
}
}
+
+/* Assume that the preceeding pass has possibly eliminated jump instructions
+ or converted the unconditional jumps. Eliminate the edges from CFG. */
+
+void
+purge_dead_edges (bb)
+ basic_block bb;
+{
+ edge e, next;
+ rtx insn = bb->end;
+ if (GET_CODE (insn) == JUMP_INSN && !simplejump_p (insn))
+ return;
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ for (e = bb->succ; e; e = next)
+ {
+ next = e->succ_next;
+ if (e->dest == EXIT_BLOCK_PTR || e->dest->head != JUMP_LABEL (insn))
+ remove_edge (e);
+ }
+ if (bb->succ && bb->succ->succ_next)
+ abort ();
+ if (!bb->succ)
+ return;
+ bb->succ->probability = REG_BR_PROB_BASE;
+ bb->succ->count = bb->count;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
+ return;
+ }
+ /* If we don't see a jump insn, we don't know exactly why the block would
+ have been broken at this point. Look for a simple, non-fallthru edge,
+ as these are only created by conditional branches. If we find such an
+ edge we know that there used to be a jump here and can then safely
+ remove all non-fallthru edges. */
+ for (e = bb->succ; e && (e->flags & (EDGE_COMPLEX | EDGE_FALLTHRU));
+ e = e->succ_next);
+ if (!e)
+ return;
+ for (e = bb->succ; e; e = next)
+ {
+ next = e->succ_next;
+ if (!(e->flags & EDGE_FALLTHRU))
+ remove_edge (e);
+ }
+ if (!bb->succ || bb->succ->succ_next)
+ abort ();
+ bb->succ->probability = REG_BR_PROB_BASE;
+ bb->succ->count = bb->count;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, "Purged non-fallthru edges from bb %i\n",
+ bb->index);
+ return;
+}
+
+/* Search all basic blocks for potentionally dead edges and purge them. */
+
+void
+purge_all_dead_edges ()
+{
+ int i;
+ for (i = 0; i < n_basic_blocks; i++)
+ purge_dead_edges (BASIC_BLOCK (i));
+}
diff --git a/gcc/gcse.c b/gcc/gcse.c
index d9f106c27b8..7592204c11f 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -605,14 +605,14 @@ static void compute_cprop_data PARAMS ((void));
static void find_used_regs PARAMS ((rtx *, void *));
static int try_replace_reg PARAMS ((rtx, rtx, rtx));
static struct expr *find_avail_set PARAMS ((int, rtx));
-static int cprop_jump PARAMS ((rtx, rtx, rtx));
+static int cprop_jump PARAMS ((basic_block, rtx, rtx, rtx));
#ifdef HAVE_cc0
-static int cprop_cc0_jump PARAMS ((rtx, struct reg_use *, rtx));
+static int cprop_cc0_jump PARAMS ((basic_block, rtx, struct reg_use *, rtx));
#endif
static void mems_conflict_for_gcse_p PARAMS ((rtx, rtx, void *));
static int load_killed_in_block_p PARAMS ((basic_block, int, rtx, int));
static void canon_list_insert PARAMS ((rtx, rtx, void *));
-static int cprop_insn PARAMS ((rtx, int));
+static int cprop_insn PARAMS ((basic_block, rtx, int));
static int cprop PARAMS ((int));
static int one_cprop_pass PARAMS ((int, int));
static void alloc_pre_mem PARAMS ((int, int));
@@ -4015,10 +4015,11 @@ find_avail_set (regno, insn)
nonzero if a change was made. We know INSN has just a SET. */
static int
-cprop_jump (insn, from, src)
+cprop_jump (bb, insn, from, src)
rtx insn;
rtx from;
rtx src;
+ basic_block bb;
{
rtx set = PATTERN (insn);
rtx new = simplify_replace_rtx (SET_SRC (set), from, src);
@@ -4059,6 +4060,7 @@ cprop_jump (insn, from, src)
print_rtl (gcse_file, src);
fprintf (gcse_file, "\n");
}
+ purge_dead_edges (bb);
return 1;
}
@@ -4072,7 +4074,8 @@ cprop_jump (insn, from, src)
Returns nonzero if a change was made. */
static int
-cprop_cc0_jump (insn, reg_used, src)
+cprop_cc0_jump (bb, insn, reg_used, src)
+ basic_block bb;
rtx insn;
struct reg_use *reg_used;
rtx src;
@@ -4083,7 +4086,7 @@ cprop_cc0_jump (insn, reg_used, src)
rtx new_src = simplify_replace_rtx (SET_SRC (PATTERN (insn)),
reg_used->reg_rtx, src);
- if (! cprop_jump (jump, cc0_rtx, new_src))
+ if (! cprop_jump (bb, jump, cc0_rtx, new_src))
return 0;
/* If we succeeded, delete the cc0 setter. */
@@ -4099,7 +4102,8 @@ cprop_cc0_jump (insn, reg_used, src)
The result is non-zero if a change was made. */
static int
-cprop_insn (insn, alter_jumps)
+cprop_insn (bb, insn, alter_jumps)
+ basic_block bb;
rtx insn;
int alter_jumps;
{
@@ -4183,7 +4187,7 @@ cprop_insn (insn, alter_jumps)
&& GET_CODE (insn) == JUMP_INSN
&& condjump_p (insn)
&& ! simplejump_p (insn))
- changed |= cprop_jump (insn, reg_used->reg_rtx, src);
+ changed |= cprop_jump (bb, insn, reg_used->reg_rtx, src);
#ifdef HAVE_cc0
/* Similar code for machines that use a pair of CC0 setter and
@@ -4252,7 +4256,7 @@ cprop (alter_jumps)
insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
- changed |= cprop_insn (insn, alter_jumps);
+ changed |= cprop_insn (BASIC_BLOCK (bb), insn, alter_jumps);
/* Keep track of everything modified by this insn. */
/* ??? Need to be careful w.r.t. mods done to INSN. Don't
diff --git a/gcc/recog.c b/gcc/recog.c
index ef30528bd9e..b4b9b9d5bc2 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2725,22 +2725,6 @@ split_all_insns (upd_life)
int changed;
int i;
- if (!upd_life)
- {
- rtx next, insn;
-
- for (insn = get_insns (); insn ; insn = next)
- {
- rtx last;
-
- /* Can't use `next_real_insn' because that might go across
- CODE_LABELS and short-out basic blocks. */
- next = NEXT_INSN (insn);
- last = split_insn (insn);
- }
- return;
- }
-
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
changed = 0;
@@ -2775,12 +2759,21 @@ split_all_insns (upd_life)
abort ();
}
- if (changed && upd_life)
+ if (changed)
{
compute_bb_for_insn (get_max_uid ());
+ for (i = 0; i < n_basic_blocks; i++)
+ find_sub_basic_blocks (BASIC_BLOCK (i));
+ }
+
+ if (changed && upd_life)
+ {
count_or_remove_death_notes (blocks, 1);
update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
}
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
sbitmap_free (blocks);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index e9227b14079..278e9d06976 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1387,6 +1387,7 @@ extern int reg_set_p PARAMS ((rtx, rtx));
extern rtx single_set_2 PARAMS ((rtx, rtx));
extern int multiple_sets PARAMS ((rtx));
extern int set_noop_p PARAMS ((rtx));
+extern int noop_move_p PARAMS ((rtx));
extern rtx find_last_value PARAMS ((rtx, rtx *, rtx, int));
extern int refers_to_regno_p PARAMS ((unsigned int, unsigned int,
rtx, rtx *));
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 2f9696cc1fc..c9152ab0f8e 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1020,6 +1020,45 @@ set_noop_p (set)
return (GET_CODE (src) == REG && GET_CODE (dst) == REG
&& REGNO (src) == REGNO (dst));
}
+
+/* Return nonzero if an insn consists only of SETs, each of which only sets a
+ value to itself. */
+
+int
+noop_move_p (insn)
+ rtx insn;
+{
+ rtx pat = PATTERN (insn);
+
+ /* Insns carrying these notes are useful later on. */
+ if (find_reg_note (insn, REG_EQUAL, NULL_RTX))
+ return 0;
+
+ if (GET_CODE (pat) == SET && set_noop_p (pat))
+ return 1;
+
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ int i;
+ /* If nothing but SETs of registers to themselves,
+ this insn can also be deleted. */
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx tem = XVECEXP (pat, 0, i);
+
+ if (GET_CODE (tem) == USE
+ || GET_CODE (tem) == CLOBBER)
+ continue;
+
+ if (GET_CODE (tem) != SET || ! set_noop_p (tem))
+ return 0;
+ }
+
+ return 1;
+ }
+ return 0;
+}
+
/* Return the last thing that X was assigned from before *PINSN. If VALID_TO
is not NULL_RTX then verify that the object is not modified up to VALID_TO.
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 13a5d059b0c..613ef0da17a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3265,7 +3265,7 @@ rest_of_compilation (decl)
timevar_pop (TV_JUMP);
timevar_push (TV_FLOW);
- find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+ purge_all_dead_edges ();
cleanup_cfg (CLEANUP_EXPENSIVE);
/* Blimey. We've got to have the CFG up to date for the call to
@@ -3441,16 +3441,6 @@ rest_of_compilation (decl)
timevar_pop (TV_RELOAD_CSE_REGS);
}
- /* If optimizing, then go ahead and split insns now since we are about
- to recompute flow information anyway. */
- if (optimize > 0)
- {
- int old_labelnum = max_label_num ();
-
- split_all_insns (0);
- rebuild_label_notes_after_reload |= old_labelnum != max_label_num ();
- }
-
/* Register allocation and reloading may have turned an indirect jump into
a direct jump. If so, we must rebuild the JUMP_LABEL fields of
jumping instructions. */
@@ -3470,6 +3460,11 @@ rest_of_compilation (decl)
open_dump_file (DFI_flow2, decl);
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+
+ /* If optimizing, then go ahead and split insns now. */
+ if (optimize > 0)
+ split_all_insns (0);
+
cleanup_cfg (0);
/* On some machines, the prologue and epilogue code, or parts thereof,