basic-block.h (find_sub_basic_block): Declare.
* 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. From-SVN: r44267
This commit is contained in:
parent
4edc91ae51
commit
0005550b58
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
220
gcc/flow.c
220
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 (GET_CODE (first_insn) == LABEL_REF)
|
||||
first_insn = NEXT_INSN (first_insn);
|
||||
first_insn = NEXT_INSN (first_insn);
|
||||
bb->succ = NULL;
|
||||
if (insn == bb->end)
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
|
22
gcc/gcse.c
22
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
|
||||
|
27
gcc/recog.c
27
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);
|
||||
}
|
||||
|
@ -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 *));
|
||||
|
@ -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.
|
||||
|
17
gcc/toplev.c
17
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user