2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-24 20:42:10 +08:00

Makefile.in (flow.o): Depend on TREE_H.

* Makefile.in (flow.o): Depend on TREE_H.
	* basic-block.h (REG_SET_EQUAL_P): New.
	(XOR_REG_SET): New.
	(n_edges): Declare.
	(free_regset_vector): Remove declaration.
	(flow_delete_insn_chain): Declare.
	(enum update_life_extent): New.
	(update_life_info, count_or_remove_death_notes): Declare.
	* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
	Verify register live at bb->global_live_at_start before adding USE.
	* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
	(CLEAN_ALLOCA): New.
	(n_edges): New.
	(PROP_*): New flags.
	(find_basic_blocks_1): Use alloc_EXPR_LIST.
	(clear_edges): Zero n_edges.
	(make_edge): Increment n_edges.
	(split_edge): Don't allocate bb->local_set.  Increment n_edges.
	(flow_delete_insn_chain): Export.
	(delete_block): Decrement n_edges.
	(merge_blocks_nomove): Likewise.
	(life_analysis): Give life_analysis_1 PROP flags.
	(verify_wide_reg_1, verify_wide_reg): New.
	(verify_local_live_at_start): New.
	(update_life_info): Rewrite to call into propogate_block.
	(mark_reg): New.
	(mark_regs_live_at_end): After reload, if epilogue as rtl,
	always mark stack pointer.  Conditionally mark PIC register.
	After reload, mark call-saved registers, return regsiters.
	(life_analysis_1): Accept PROP flags not remove_dead_code.
	Call mark_regs_live_at_end before zeroing regs_ever_live.
	Use calculate_global_regs_live.  Copy global_live_at_end before
	calling final propagate_block.  Zero reg_next_use on exit.
	(calculate_global_regs_live): New.
	(allocate_bb_life_data): Don't allocate bb->local_set.
	(init_regset_vector, free_regset_vector): Remove.
	(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
	Test flags before every operation.  Warn if prologue/epilogue insn
	would have been deleted.
	(mark_set_regs, mark_set_1): Accept and use FLAGS.
	Use alloc_EXPR_LIST.
	(mark_used_regs): Accept and use FLAGS, not FINAL.
	Remove special handling for RETURN.
	(try_pre_increment): Use alloc_EXPR_LIST.
	(dump_flow_info): Dump n_edges.
	(unlink_insn_chain, split_hard_reg_notes): Remove.
	(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
	(find_insn_with_note, new_insn_dead_notes): Remove.
	(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
	(maybe_remove_dead_notes, prepend_reg_notes): Remove.
	(replace_insns): Remove.
	(count_or_remove_death_notes): New.
	(verify_flow_info): Abort on error after all checks.
	(remove_edge): Decrement n_edges.
	(remove_fake_edges): Tweek format.
	* haifa-sched.c (schedule_insns): Use split_all_insns.
	* output.h (update_life_info): Remove declaration.
	* recog.c (split_all_insns): From the corpse of split_block_insns,
	do the whole function block by block.  Use update_life_info.
	(recog_last_allowed_insn): New.
	(recog_next_insn): Mind it.
	(peephole2_optimize): Set it.  Walk backwards through blocks.
	Use update_life_info.
	* rtl.h (update_flow_info, replace_insns): Remove declarations.
	(split_all_insns): Declare.
	* toplev.c (rest_of_compilation): Thread prologue before flow2.
	Use split_all_insns.

	* i386.md (or -1 peep2s): Disable.

From-SVN: r29877
This commit is contained in:
Richard Henderson 1999-10-09 12:47:18 -07:00 committed by Richard Henderson
parent 1640ef3802
commit d3a923ee2e
11 changed files with 1099 additions and 1660 deletions

@ -1,3 +1,75 @@
Sat Oct 9 12:18:16 1999 Richard Henderson <rth@cygnus.com>
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
Fri Oct 8 17:49:08 1999 Richard Henderson <rth@cygnus.com>
* config/mips/mips.md (movstrsi+[123]) : Combine these into

@ -1549,7 +1549,7 @@ loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h loop.h insn-config.h \
function.h toplev.h varray.h
unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h function.h \
integrate.h $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) loop.h toplev.h varray.h
flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-config.h \
flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h insn-config.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h output.h toplev.h recog.h \
insn-flags.h function.h
combine.o : combine.c $(CONFIG_H) system.h $(RTL_H) flags.h function.h \

@ -31,6 +31,9 @@ typedef bitmap regset; /* Head of register set linked list. */
/* Copy a register set to another register set. */
#define COPY_REG_SET(TO, FROM) bitmap_copy (TO, FROM)
/* Compare two register sets. */
#define REG_SET_EQUAL_P(A, B) bitmap_equal_p (A, B)
/* `and' a register set with a second register set. */
#define AND_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_AND)
@ -41,6 +44,9 @@ typedef bitmap regset; /* Head of register set linked list. */
/* Inclusive or a register set with a second register set. */
#define IOR_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_IOR)
/* Exclusive or a register set with a second register set. */
#define XOR_REG_SET(TO, FROM) bitmap_operation (TO, TO, FROM, BITMAP_XOR)
/* Or into TO the register set FROM1 `and'ed with the complement of FROM2. */
#define IOR_AND_COMPL_REG_SET(TO, FROM1, FROM2) \
bitmap_ior_and_compl (TO, FROM1, FROM2)
@ -153,6 +159,10 @@ typedef struct basic_block_def {
extern int n_basic_blocks;
/* Number of edges in the current function. */
extern int n_edges;
/* Index by basic block number, get basic block struct info. */
extern varray_type basic_block_info;
@ -229,9 +239,6 @@ extern struct basic_block_def entry_exit_blocks[2];
#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
#define EXIT_BLOCK_PTR (&entry_exit_blocks[1])
/* from flow.c */
extern void free_regset_vector PROTO ((regset *, int nelts));
extern varray_type basic_block_for_insn;
#define BLOCK_FOR_INSN(INSN) VARRAY_BB (basic_block_for_insn, INSN_UID (INSN))
#define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0)
@ -249,6 +256,7 @@ extern void insert_insn_on_edge PROTO ((rtx, edge));
extern void commit_edge_insertions PROTO ((void));
extern void remove_fake_edges PROTO ((void));
extern void add_noreturn_fake_exit_edges PROTO ((void));
extern void flow_delete_insn_chain PROTO((rtx, rtx));
/* This structure maintains an edge list vector. */
struct edge_list
@ -291,6 +299,15 @@ extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
extern void compute_flow_dominators PROTO ((sbitmap *, sbitmap *));
extern void compute_immediate_dominators PROTO ((int *, sbitmap *));
enum update_life_extent
{
UPDATE_LIFE_GLOBAL = 0,
UPDATE_LIFE_LOCAL = 1
};
extern void update_life_info PROTO ((sbitmap, enum update_life_extent));
extern int count_or_remove_death_notes PROTO ((sbitmap, int));
/* In lcm.c */
extern void pre_lcm PROTO ((int, int, int_list_ptr *,
int_list_ptr *,

@ -11721,11 +11721,17 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
if (place == 0)
{
for (tem = prev_nonnote_insn (i3);
place == 0 && tem
&& (GET_CODE (tem) == INSN || GET_CODE (tem) == CALL_INSN);
tem = prev_nonnote_insn (tem))
basic_block bb = BASIC_BLOCK (this_basic_block);
for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
{
if (GET_RTX_CLASS (GET_CODE (tem)) != 'i')
{
if (tem == bb->head)
break;
continue;
}
/* If the register is being set at TEM, see if that is all
TEM is doing. If so, delete TEM. Otherwise, make this
into a REG_UNUSED note instead. */
@ -11740,8 +11746,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
if (set != 0)
for (inner_dest = SET_DEST (set);
GET_CODE (inner_dest) == STRICT_LOW_PART
|| GET_CODE (inner_dest) == SUBREG
|| GET_CODE (inner_dest) == ZERO_EXTRACT;
|| GET_CODE (inner_dest) == SUBREG
|| GET_CODE (inner_dest) == ZERO_EXTRACT;
inner_dest = XEXP (inner_dest, 0))
;
@ -11789,7 +11795,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
distribute_links (LOG_LINKS (cc0_setter));
PUT_CODE (cc0_setter, NOTE);
NOTE_LINE_NUMBER (cc0_setter) = NOTE_INSN_DELETED;
NOTE_LINE_NUMBER (cc0_setter)
= NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (cc0_setter) = 0;
}
#endif
@ -11818,48 +11825,64 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
REGNO (XEXP (note, 0))))
place = tem;
break;
}
}
else if (reg_referenced_p (XEXP (note, 0), PATTERN (tem))
|| (GET_CODE (tem) == CALL_INSN
&& find_reg_fusage (tem, USE, XEXP (note, 0))))
{
place = tem;
}
}
else if (reg_referenced_p (XEXP (note, 0), PATTERN (tem))
|| (GET_CODE (tem) == CALL_INSN
&& find_reg_fusage (tem, USE, XEXP (note, 0))))
{
place = tem;
/* If we are doing a 3->2 combination, and we have a
register which formerly died in i3 and was not used
by i2, which now no longer dies in i3 and is used in
i2 but does not die in i2, and place is between i2
and i3, then we may need to move a link from place to
i2. */
if (i2 && INSN_UID (place) <= max_uid_cuid
&& INSN_CUID (place) > INSN_CUID (i2)
&& from_insn && INSN_CUID (from_insn) > INSN_CUID (i2)
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
{
rtx links = LOG_LINKS (place);
LOG_LINKS (place) = 0;
distribute_links (links);
}
/* If we are doing a 3->2 combination, and we have a
register which formerly died in i3 and was not used
by i2, which now no longer dies in i3 and is used in
i2 but does not die in i2, and place is between i2
and i3, then we may need to move a link from place to
i2. */
if (i2 && INSN_UID (place) <= max_uid_cuid
&& INSN_CUID (place) > INSN_CUID (i2)
&& from_insn && INSN_CUID (from_insn) > INSN_CUID (i2)
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
{
rtx links = LOG_LINKS (place);
LOG_LINKS (place) = 0;
distribute_links (links);
}
break;
}
if (tem == bb->head)
break;
}
}
/* If we haven't found an insn for the death note and it
is still a REG_DEAD note, but we have hit a CODE_LABEL,
insert a USE insn for the register at that label and
put the death node there. This prevents problems with
call-state tracking in caller-save.c. */
if (REG_NOTE_KIND (note) == REG_DEAD && place == 0 && tem != 0)
{
place
= emit_insn_after (gen_rtx_USE (VOIDmode, XEXP (note, 0)),
tem);
/* We haven't found an insn for the death note and it
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.
/* If this insn was emitted between blocks, then update
BLOCK_HEAD of the current block to include it. */
if (BLOCK_END (this_basic_block - 1) == tem)
BLOCK_HEAD (this_basic_block) = place;
??? If the register was live, we ought to mark for later
global life update. Cop out like the previous code and
just add a hook for the death note to live on. */
if (REG_NOTE_KIND (note) == REG_DEAD && place == 0)
{
int regno = REGNO (XEXP (note, 0));
if (REGNO_REG_SET_P (bb->global_live_at_start, regno))
{
rtx die = gen_rtx_USE (VOIDmode, XEXP (note, 0));
place = bb->head;
if (GET_CODE (place) != CODE_LABEL
&& GET_CODE (place) != NOTE)
{
place = emit_insn_before (die, place);
bb->head = place;
}
else
{
place = emit_insn_after (die, place);
}
}
}
}
@ -11869,7 +11892,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
which is what `dead_or_set_p' checks, so also check for it being
set partially. */
if (place && REG_NOTE_KIND (note) == REG_DEAD)
{
int regno = REGNO (XEXP (note, 0));

@ -8146,11 +8146,14 @@
(clobber (reg:CC 17))])]
"")
;; ??? Rewrite these to not introduce the false dependancy.
;; Currently they'll trip update_life_info's sanity checks.
;; For HI and SI modes, or $-1,reg is smaller than mov $-1,reg.
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(const_int -1))]
"(optimize_size || TARGET_PENTIUM)
"0 && (optimize_size || TARGET_PENTIUM)
&& reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
[(parallel [(set (match_dup 0)
(ior:SI (match_dup 0) (const_int -1)))
@ -8160,7 +8163,7 @@
(define_peephole2
[(set (match_operand:HI 0 "register_operand" "")
(const_int -1))]
"(optimize_size || TARGET_PENTIUM)
"0 && (optimize_size || TARGET_PENTIUM)
&& reg_dead_p (insn, gen_rtx_REG (CCmode, FLAGS_REG))"
[(parallel [(set (match_dup 0)
(ior:HI (match_dup 0) (const_int -1)))

2266
gcc/flow.c

File diff suppressed because it is too large Load Diff

@ -7773,9 +7773,7 @@ schedule_insns (dump_file)
/* Initialize issue_rate. */
issue_rate = ISSUE_RATE;
/* Do the splitting first for all blocks. */
for (b = 0; b < n_basic_blocks; b++)
split_block_insns (b, 1);
split_all_insns (1);
max_uid = (get_max_uid () + 1);

@ -135,7 +135,6 @@ extern void find_basic_blocks PROTO((rtx, int, FILE *, int));
extern void free_basic_block_vars PROTO((int));
extern void set_block_num PROTO((rtx, int));
extern void life_analysis PROTO((rtx, int, FILE *, int));
extern void update_life_info PROTO((rtx, rtx, rtx, rtx, rtx));
#endif
/* Functions in varasm.c. */

@ -2562,88 +2562,104 @@ reg_fits_class_p (operand, class, offset, mode)
return 0;
}
/* Do the splitting of insns in the block B. Only try to actually split if
DO_SPLIT is true; otherwise, just remove nops. */
/* Split all insns in the function. If UPD_LIFE, update life info after. */
void
split_block_insns (b, do_split)
int b;
int do_split;
split_all_insns (upd_life)
int upd_life;
{
rtx insn, next;
sbitmap blocks;
int changed;
int i;
for (insn = BLOCK_HEAD (b);; insn = next)
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
changed = 0;
for (i = n_basic_blocks - 1; i >= 0; --i)
{
rtx set;
basic_block bb = BASIC_BLOCK (i);
rtx insn, next;
/* Can't use `next_real_insn' because that
might go across CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
if (GET_CODE (insn) != INSN)
for (insn = bb->head; insn ; insn = next)
{
if (insn == BLOCK_END (b))
break;
rtx set;
continue;
}
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
if (GET_CODE (insn) != INSN)
;
/* Don't split no-op move insns. These should silently disappear
later in final. Splitting such insns would break the code
that handles REG_NO_CONFLICT blocks. */
set = single_set (insn);
if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set)))
{
if (insn == BLOCK_END (b))
break;
/* Don't split no-op move insns. These should silently
disappear later in final. Splitting such insns would
break the code that handles REG_NO_CONFLICT blocks. */
/* Nops get in the way while scheduling, so delete them now if
register allocation has already been done. It is too risky
to try to do this before register allocation, and there are
unlikely to be very many nops then anyways. */
if (reload_completed)
else if ((set = single_set (insn)) != NULL
&& rtx_equal_p (SET_SRC (set), SET_DEST (set)))
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
continue;
}
if (do_split)
{
/* Split insns here to get max fine-grain parallelism. */
rtx first = PREV_INSN (insn);
rtx notes = REG_NOTES (insn);
rtx last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
/* try_split returns the NOTE that INSN became. */
first = NEXT_INSN (first);
#ifdef INSN_SCHEDULING
update_life_info (notes, first, last, insn, insn);
#endif
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (insn == BLOCK_HEAD (b))
BLOCK_HEAD (b) = first;
if (insn == BLOCK_END (b))
/* Nops get in the way while scheduling, so delete them
now if register allocation has already been done. It
is too risky to try to do this before register
allocation, and there are unlikely to be very many
nops then anyways. */
if (reload_completed)
{
BLOCK_END (b) = last;
break;
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
}
else
{
/* Split insns here to get max fine-grain parallelism. */
rtx first = PREV_INSN (insn);
rtx last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
SET_BIT (blocks, i);
changed = 1;
/* try_split returns the NOTE that INSN became. */
first = NEXT_INSN (first);
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
if (insn == bb->end)
{
bb->end = last;
break;
}
}
}
if (insn == bb->end)
break;
}
if (insn == BLOCK_END (b))
break;
/* ??? When we're called from just after reload, the CFG is in bad
shape, and we may have fallen off the end. This could be fixed
by having reload not try to delete unreachable code. Otherwise
assert we found the end insn. */
if (insn == NULL && upd_life)
abort ();
}
if (changed && upd_life)
{
count_or_remove_death_notes (blocks, 1);
update_life_info (blocks, UPDATE_LIFE_LOCAL);
}
sbitmap_free (blocks);
}
#ifdef HAVE_peephole2
/* This is the last insn we'll allow recog_next_insn to consider. */
static rtx recog_last_allowed_insn;
/* Return the Nth non-note insn after INSN, or return NULL_RTX if it does
not exist. Used by the recognizer to find the next insn to match in a
multi-insn pattern. */
@ -2652,17 +2668,20 @@ recog_next_insn (insn, n)
rtx insn;
int n;
{
while (insn != NULL_RTX && n > 0)
if (insn != NULL_RTX)
{
insn = next_nonnote_insn (insn);
while (n > 0)
{
if (insn == recog_last_allowed_insn)
return NULL_RTX;
if (insn == NULL_RTX)
return insn;
insn = NEXT_INSN (insn);
if (insn == NULL_RTX)
break;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
return NULL_RTX;
n--;
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
n -= 1;
}
}
return insn;
@ -2673,38 +2692,64 @@ void
peephole2_optimize (dump_file)
FILE *dump_file ATTRIBUTE_UNUSED;
{
rtx insn;
rtx epilogue_insn = 0;
rtx insn, prev;
int i, changed;
sbitmap blocks;
for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn))
/* ??? TODO: Arrange with resource.c to start at bb->global_live_at_end
and backtrack insn by insn as we proceed through the block. In this
way we'll not need to keep searching forward from the beginning of
basic blocks to find register life info. */
init_resource_info (NULL);
blocks = sbitmap_alloc (n_basic_blocks);
sbitmap_zero (blocks);
changed = 0;
for (i = n_basic_blocks - 1; i >= 0; --i)
{
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
basic_block bb = BASIC_BLOCK (i);
/* Since we don't update life info until the very end, we can't
allow matching instructions that we've replaced before. Walk
backward through the basic block so that we don't have to
care about subsequent life info; recog_last_allowed_insn to
restrict how far forward we will allow the match to proceed. */
recog_last_allowed_insn = bb->end;
for (insn = bb->end; ; insn = prev)
{
epilogue_insn = insn;
break;
}
}
init_resource_info (epilogue_insn);
for (insn = get_insns (); insn != NULL;
insn = next_nonnote_insn (insn))
{
if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
{
rtx last_insn;
rtx before = PREV_INSN (insn);
rtx try = peephole2_insns (PATTERN (insn), insn, &last_insn);
if (try != NULL)
prev = PREV_INSN (insn);
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
replace_insns (insn, last_insn, try, NULL_RTX);
insn = NEXT_INSN (before);
rtx try, last_insn;
try = peephole2_insns (PATTERN (insn), insn, &last_insn);
if (try != NULL)
{
flow_delete_insn_chain (insn, last_insn);
try = emit_insn_after (try, prev);
if (last_insn == bb->end)
bb->end = try;
if (insn == bb->head)
bb->head = NEXT_INSN (prev);
recog_last_allowed_insn = prev;
SET_BIT (blocks, i);
changed = 1;
}
}
if (insn == bb->head)
break;
}
}
free_resource_info ();
count_or_remove_death_notes (blocks, 1);
update_life_info (blocks, UPDATE_LIFE_LOCAL);
}
#endif

@ -1168,8 +1168,7 @@ extern enum reg_class reg_alternate_class PROTO((int));
extern rtx get_first_nonparm_insn PROTO((void));
extern void split_block_insns PROTO((int, int));
extern void update_flow_info PROTO((rtx, rtx, rtx, rtx));
extern void split_all_insns PROTO((int));
#define MAX_SAVED_CONST_INT 64
extern rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
@ -1542,7 +1541,6 @@ extern void print_rtl_with_bb PROTO ((FILE *, rtx));
extern void dump_flow_info PROTO ((FILE *));
#endif
extern void free_bb_mem PROTO ((void));
extern void replace_insns PROTO ((rtx, rtx, rtx, rtx));
/* In expmed.c */
extern void init_expmed PROTO ((void));

@ -4149,6 +4149,13 @@ 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.
@ -4156,26 +4163,7 @@ rest_of_compilation (decl)
reload_cse_regs may expose more splitting opportunities, expecially
for double-word operations. */
if (optimize > 0 && flag_schedule_insns_after_reload)
{
rtx insn;
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
rtx last;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
last = try_split (PATTERN (insn), insn, 1);
if (last != insn)
{
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
}
}
}
split_all_insns (0);
if (global_reg_dump)
{
@ -4204,13 +4192,6 @@ rest_of_compilation (decl)
flow2_completed = 1;
/* 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 (flow2_dump)
{
close_dump_file (print_rtl_with_bb, insns);