flow.c (life_analysis_1): Do not clobber regs_ever_live after reload.

* flow.c (life_analysis_1): Do not clobber regs_ever_live after
        reload.  Never perform rescans of the insn chain after reload.
        (propagate_block): Do not delete insn or create new autoinc addressing
        modes after reload.
        * jump.c (jump_optimize): Unconditionally use the code that was
        previously conditional on PRESERVE_DEATH_INFO_REGNO_P.
        * reload1.c (reload): When reloading is finished, delete all
        REG_DEAD and REG_UNUSED notes.
        (emit_reload_insns): Delete all code that was conditional on
        PRESERVE_DEATH_INFO_REGNO_P.
        (no_longer_dead_regs): Delete variable.
        (reload_cse_delete_death_notes): Delete function.
        (reload_cse_no_longer_dead): Delete function.
        (reload_cse_regs_1): Delete all code to handle deletion of death
        notes.
        (reload_cse_noop_set_p): Likewise.
        (reload_cse_simplify_set): Likewise.
        (reload_cse_simplify_operands): Likewise.
        (reload_cse_move2add): Likewise.
        * reorg.c (used_spill_regs): Delete declaration.
        (max_label_num_after_reload): Delete declaration.
        (find_dead_or_set_registers): Don't assume that spill regs are
        dead at a CODE_LABEL.
        * rtlanal.c (dead_or_set_regno_p): Death notes are always accurate,
        even after reload.
        * sched.c (sched_analyze_insn): Likewise.
        (update_flow_info): Likewise.
        * haifa-sched.c (sched_analyze_insn): Likewise.
        (update_flow_info): Likewise.
        * tm.texi (PRESERVE_DEATH_INFO_REGNO_P): Delete documentation.
        * toplev.c (max_label_num_after_reload): Delete variable.
        (rest_of_compilation): Don't set max_label_num_after_reload.
        Call life_analysis after reload_cse_regs if optimizing.
        * config/gmicro/gmicro.h: Delete comment referring to
        PRESERVE_DEATH_INFO_REGNO_P.
        * config/i386/i386.h: Likewise.
        * config/m88k/m88k.h: Likewise.
        * config/m32r/m32r.h (PRESERVE_DEATH_INFO_REGNO_P): Delete definition.
        * config/sh/sh.h: Likewise.
Accurate REG_DEAD notes after reload.

Co-Authored-By: Jeffrey A Law <law@cygnus.com>

From-SVN: r23120
This commit is contained in:
Bernd Schmidt 1998-10-16 00:08:51 +00:00 committed by Jeff Law
parent 913135dfc2
commit 6764d250ec
15 changed files with 114 additions and 477 deletions

View File

@ -1,3 +1,47 @@
Thu Oct 15 23:53:29 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
Jeffrey A Law (law@cygnus.com)
* flow.c (life_analysis_1): Do not clobber regs_ever_live after
reload. Never perform rescans of the insn chain after reload.
(propagate_block): Do not delete insn or create new autoinc addressing
modes after reload.
* jump.c (jump_optimize): Unconditionally use the code that was
previously conditional on PRESERVE_DEATH_INFO_REGNO_P.
* reload1.c (reload): When reloading is finished, delete all
REG_DEAD and REG_UNUSED notes.
(emit_reload_insns): Delete all code that was conditional on
PRESERVE_DEATH_INFO_REGNO_P.
(no_longer_dead_regs): Delete variable.
(reload_cse_delete_death_notes): Delete function.
(reload_cse_no_longer_dead): Delete function.
(reload_cse_regs_1): Delete all code to handle deletion of death
notes.
(reload_cse_noop_set_p): Likewise.
(reload_cse_simplify_set): Likewise.
(reload_cse_simplify_operands): Likewise.
(reload_cse_move2add): Likewise.
* reorg.c (used_spill_regs): Delete declaration.
(max_label_num_after_reload): Delete declaration.
(find_dead_or_set_registers): Don't assume that spill regs are
dead at a CODE_LABEL.
* rtlanal.c (dead_or_set_regno_p): Death notes are always accurate,
even after reload.
* sched.c (sched_analyze_insn): Likewise.
(update_flow_info): Likewise.
* haifa-sched.c (sched_analyze_insn): Likewise.
(update_flow_info): Likewise.
* tm.texi (PRESERVE_DEATH_INFO_REGNO_P): Delete documentation.
* toplev.c (max_label_num_after_reload): Delete variable.
(rest_of_compilation): Don't set max_label_num_after_reload.
Call life_analysis after reload_cse_regs if optimizing.
* config/gmicro/gmicro.h: Delete comment referring to
PRESERVE_DEATH_INFO_REGNO_P.
* config/i386/i386.h: Likewise.
* config/m88k/m88k.h: Likewise.
* config/m32r/m32r.h (PRESERVE_DEATH_INFO_REGNO_P): Delete definition.
* config/sh/sh.h: Likewise.
Thu Oct 15 19:48:41 1998 David Edelsohn <edelsohn@mhpcc.edu>
* loop.c (strength_reduce): Restore marking bct_p as

View File

@ -241,7 +241,6 @@ extern int target_flags;
/* #define OVERLAPPING_REGNO_P(REGNO) */
/* #define INSN_CLOBBERS_REGNO_P(INSN,REGNO) */
/* #define PRESERVE_DEATH_INFO_REGNO_P(REGNO) */
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.

View File

@ -834,11 +834,6 @@ enum reg_class
#define STACK_TOP_P(xop) (REG_P (xop) && REGNO (xop) == FIRST_STACK_REG)
/* Try to maintain the accuracy of the death notes for regs satisfying the
following. Important for stack like regs, to know when to pop. */
/* #define PRESERVE_DEATH_INFO_REGNO_P(x) FP_REGNO_P(x) */
/* 1 if register REGNO can magically overlap other regs.
Note that nonzero values work only in very special circumstances. */

View File

@ -2077,9 +2077,6 @@ extern int conditional_move_operand PROTO((Rtx, int));
extern int carry_compare_operand PROTO((Rtx, int));
extern char *emit_cond_move PROTO((Rtx *, Rtx));
/* Needed by a peephole optimisation. */
#define PRESERVE_DEATH_INFO_REGNO_P(regno) (regno < FIRST_PSEUDO_REGISTER)
extern char * m32r_output_block_move PROTO((Rtx, Rtx *));
extern int m32r_block_immediate_operand PROTO((Rtx, int));
extern void m32r_expand_block_move PROTO((Rtx *));

View File

@ -648,7 +648,6 @@ extern char * reg_names[];
/* These interfaces that don't apply to the m88000. */
/* OVERLAPPING_REGNO_P(REGNO) 0 */
/* INSN_CLOBBERS_REGNO_P(INSN, REGNO) 0 */
/* PRESERVE_DEATH_INFO_REGNO_P(REGNO) 0 */
/* True if register is an extended register. */
#define XRF_REGNO_P(N) ((N) < FIRST_PSEUDO_REGISTER && (N) >= FIRST_EXTENDED_REGISTER)

View File

@ -158,8 +158,6 @@ extern int target_flags;
#define TARGET_DEFAULT (0)
#define PRESERVE_DEATH_INFO_REGNO_P(regno) (TARGET_RELAX || optimize)
#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \
do { \
if (SIZE) \

View File

@ -1347,6 +1347,7 @@ life_analysis_1 (f, nregs)
possibly excluding those that are used after they are set. */
regset *basic_block_significant;
register int i;
char save_regs_ever_live[FIRST_PSEUDO_REGISTER];
struct obstack flow_obstack;
@ -1354,6 +1355,16 @@ life_analysis_1 (f, nregs)
max_regno = nregs;
/* The post-reload life analysis have (on a global basis) the same registers
live as was computed by reload itself.
Otherwise elimination offsets and such may be incorrect.
Reload will make some registers as live even though they do not appear
in the rtl. */
if (reload_completed)
bcopy (regs_ever_live, save_regs_ever_live, (sizeof (regs_ever_live)));
bzero (regs_ever_live, sizeof regs_ever_live);
/* Allocate and zero out many data structures
@ -1436,7 +1447,8 @@ life_analysis_1 (f, nregs)
basic_block_live_at_end[i], 0, j,
{
consider = 1;
if (REGNO_REG_SET_P (basic_block_significant[i], j))
if (!reload_completed
&& REGNO_REG_SET_P (basic_block_significant[i], j))
{
must_rescan = 1;
goto done;
@ -1581,6 +1593,9 @@ life_analysis_1 (f, nregs)
}
});
/* Restore regs_ever_live that was provided by reload. */
if (reload_completed)
bcopy (save_regs_ever_live, regs_ever_live, (sizeof (regs_ever_live)));
free_regset_vector (basic_block_live_at_end, n_basic_blocks);
free_regset_vector (basic_block_new_live_at_end, n_basic_blocks);
@ -1792,7 +1807,7 @@ propagate_block (old, first, last, final, significant, bnum)
"delete" it by turning it into a NOTE of type NOTE_INSN_DELETED.
We could really delete it with delete_insn, but that
can cause trouble for first or last insn in a basic block. */
if (final && insn_is_dead)
if (!reload_completed && final && insn_is_dead)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
@ -1832,7 +1847,8 @@ propagate_block (old, first, last, final, significant, bnum)
register rtx x = single_set (insn);
/* Does this instruction increment or decrement a register? */
if (final && x != 0
if (!reload_completed
&& final && x != 0
&& GET_CODE (SET_DEST (x)) == REG
&& (GET_CODE (SET_SRC (x)) == PLUS
|| GET_CODE (SET_SRC (x)) == MINUS)

View File

@ -3767,27 +3767,6 @@ sched_analyze_insn (x, insn, loop_notes)
}
/* After reload, it is possible for an instruction to have a REG_DEAD note
for a register that actually dies a few instructions earlier. For
example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
In this case, we must consider the insn to use the register mentioned
in the REG_DEAD note. Otherwise, we may accidentally move this insn
after another insn that sets the register, thus getting obviously invalid
rtl. This confuses reorg which believes that REG_DEAD notes are still
meaningful.
??? We would get better code if we fixed reload to put the REG_DEAD
notes in the right places, but that may not be worth the effort. */
if (reload_completed)
{
rtx note;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_DEAD)
sched_analyze_2 (XEXP (note, 0), insn);
}
EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
{
/* reg_last_sets[r] is now a list of insns */
@ -8007,16 +7986,7 @@ update_flow_info (notes, first, last, orig_insn)
register that was not needed by this instantiation of the
pattern, so we can safely ignore it. */
if (insn == first)
{
/* After reload, REG_DEAD notes come sometimes an
instruction after the register actually dies. */
if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
{
XEXP (note, 1) = REG_NOTES (insn);
REG_NOTES (insn) = note;
break;
}
{
if (REG_NOTE_KIND (note) != REG_UNUSED)
abort ();

View File

@ -480,12 +480,9 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
remove_death (dreg, trial);
break;
}
#ifdef PRESERVE_DEATH_INFO_REGNO_P
/* Deleting insn could lose a death-note for SREG
so don't do it if final needs accurate
death-notes. */
if (PRESERVE_DEATH_INFO_REGNO_P (sreg)
&& (trial = find_regno_note (insn, REG_DEAD, sreg)))
/* Deleting insn could lose a death-note for SREG. */
if ((trial = find_regno_note (insn, REG_DEAD, sreg)))
{
/* Change this into a USE so that we won't emit
code for it, but still can keep the note. */
@ -497,7 +494,6 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
XEXP (trial, 1) = NULL_RTX;
}
else
#endif
delete_insn (insn);
}
}

View File

@ -416,8 +416,6 @@ static int reload_cse_simplify_set PROTO((rtx, rtx));
static int reload_cse_simplify_operands PROTO((rtx));
static void reload_cse_check_clobber PROTO((rtx, rtx));
static void reload_cse_record_set PROTO((rtx, rtx));
static void reload_cse_delete_death_notes PROTO((rtx));
static void reload_cse_no_longer_dead PROTO((int, enum machine_mode));
static void reload_combine PROTO((void));
static void reload_combine_note_use PROTO((rtx *, rtx));
static void reload_combine_note_store PROTO((rtx, rtx));
@ -1206,17 +1204,13 @@ reload (first, global, dumpfile)
}
/* Make a pass over all the insns and delete all USEs which we inserted
only to tag a REG_EQUAL note on them; if PRESERVE_DEATH_INFO_REGNO_P
is defined, also remove death notes for things that are no longer
registers or no longer die in the insn (e.g., an input and output
pseudo being tied). */
only to tag a REG_EQUAL note on them. Also remove all REG_DEAD and
REG_UNUSED notes. */
for (insn = first; insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
#ifdef PRESERVE_DEATH_INFO_REGNO_P
rtx note, next;
#endif
rtx *pnote;
if (GET_CODE (PATTERN (insn)) == USE
&& find_reg_note (insn, REG_EQUAL, NULL_RTX))
@ -1226,16 +1220,16 @@ reload (first, global, dumpfile)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
continue;
}
#ifdef PRESERVE_DEATH_INFO_REGNO_P
for (note = REG_NOTES (insn); note; note = next)
pnote = &REG_NOTES (insn);
while (*pnote != 0)
{
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_DEAD
&& (GET_CODE (XEXP (note, 0)) != REG
|| reg_set_p (XEXP (note, 0), PATTERN (insn))))
remove_note (insn, note);
if (REG_NOTE_KIND (*pnote) == REG_DEAD
|| REG_NOTE_KIND (*pnote) == REG_UNUSED)
*pnote = XEXP (*pnote, 1);
else
pnote = &XEXP (*pnote, 1);
}
#endif
}
/* If we are doing stack checking, give a warning if this function's
@ -6902,28 +6896,6 @@ emit_reload_insns (chain)
gen_reload (reloadreg, oldequiv, reload_opnum[j],
reload_when_needed[j]);
#if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
/* We may have to make a REG_DEAD note for the secondary reload
register in the insns we just made. Find the last insn that
mentioned the register. */
if (! special && second_reload_reg
&& PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reload_reg)))
{
rtx prev;
for (prev = get_last_insn (); prev;
prev = PREV_INSN (prev))
if (GET_RTX_CLASS (GET_CODE (prev) == 'i')
&& reg_overlap_mentioned_for_reload_p (second_reload_reg,
PATTERN (prev)))
{
REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_DEAD,
second_reload_reg,
REG_NOTES (prev));
break;
}
}
#endif
}
this_reload_insn = get_last_insn ();
@ -6945,118 +6917,6 @@ emit_reload_insns (chain)
reload_in[j]
= regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
}
/* Add a note saying the input reload reg
dies in this insn, if anyone cares. */
#ifdef PRESERVE_DEATH_INFO_REGNO_P
if (old != 0
&& reload_reg_rtx[j] != old
&& reload_reg_rtx[j] != 0
&& reload_out[j] == 0
&& ! reload_inherited[j]
&& PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j])))
{
register rtx reloadreg = reload_reg_rtx[j];
#if 0
/* We can't abort here because we need to support this for sched.c.
It's not terrible to miss a REG_DEAD note, but we should try
to figure out how to do this correctly. */
/* The code below is incorrect for address-only reloads. */
if (reload_when_needed[j] != RELOAD_OTHER
&& reload_when_needed[j] != RELOAD_FOR_INPUT)
abort ();
#endif
/* Add a death note to this insn, for an input reload. */
if ((reload_when_needed[j] == RELOAD_OTHER
|| reload_when_needed[j] == RELOAD_FOR_INPUT)
&& ! dead_or_set_p (insn, reloadreg))
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_DEAD,
reloadreg, REG_NOTES (insn));
}
/* When we inherit a reload, the last marked death of the reload reg
may no longer really be a death. */
if (reload_reg_rtx[j] != 0
&& PRESERVE_DEATH_INFO_REGNO_P (REGNO (reload_reg_rtx[j]))
&& reload_inherited[j])
{
/* Handle inheriting an output reload.
Remove the death note from the output reload insn. */
if (reload_spill_index[j] >= 0
&& GET_CODE (reload_in[j]) == REG
&& spill_reg_store[reload_spill_index[j]] != 0
&& find_regno_note (spill_reg_store[reload_spill_index[j]],
REG_DEAD, REGNO (reload_reg_rtx[j])))
remove_death (REGNO (reload_reg_rtx[j]),
spill_reg_store[reload_spill_index[j]]);
/* Likewise for input reloads that were inherited. */
else if (reload_spill_index[j] >= 0
&& GET_CODE (reload_in[j]) == REG
&& spill_reg_store[reload_spill_index[j]] == 0
&& reload_inheritance_insn[j] != 0
&& find_regno_note (reload_inheritance_insn[j], REG_DEAD,
REGNO (reload_reg_rtx[j])))
remove_death (REGNO (reload_reg_rtx[j]),
reload_inheritance_insn[j]);
else
{
rtx prev;
/* We got this register from find_equiv_reg.
Search back for its last death note and get rid of it.
But don't search back too far.
Don't go past a place where this reg is set,
since a death note before that remains valid. */
for (prev = PREV_INSN (insn);
prev && GET_CODE (prev) != CODE_LABEL;
prev = PREV_INSN (prev))
if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
&& dead_or_set_p (prev, reload_reg_rtx[j]))
{
if (find_regno_note (prev, REG_DEAD,
REGNO (reload_reg_rtx[j])))
remove_death (REGNO (reload_reg_rtx[j]), prev);
break;
}
}
}
/* We might have used find_equiv_reg above to choose an alternate
place from which to reload. If so, and it died, we need to remove
that death and move it to one of the insns we just made. */
if (oldequiv_reg != 0
&& PRESERVE_DEATH_INFO_REGNO_P (true_regnum (oldequiv_reg)))
{
rtx prev, prev1;
for (prev = PREV_INSN (insn); prev && GET_CODE (prev) != CODE_LABEL;
prev = PREV_INSN (prev))
if (GET_RTX_CLASS (GET_CODE (prev)) == 'i'
&& dead_or_set_p (prev, oldequiv_reg))
{
if (find_regno_note (prev, REG_DEAD, REGNO (oldequiv_reg)))
{
for (prev1 = this_reload_insn;
prev1; prev1 = PREV_INSN (prev1))
if (GET_RTX_CLASS (GET_CODE (prev1) == 'i')
&& reg_overlap_mentioned_for_reload_p (oldequiv_reg,
PATTERN (prev1)))
{
REG_NOTES (prev1) = gen_rtx_EXPR_LIST (REG_DEAD,
oldequiv_reg,
REG_NOTES (prev1));
break;
}
remove_death (REGNO (oldequiv_reg), prev);
}
break;
}
}
#endif
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
@ -7262,30 +7122,6 @@ emit_reload_insns (chain)
reload_when_needed[j]);
}
#ifdef PRESERVE_DEATH_INFO_REGNO_P
/* If final will look at death notes for this reg,
put one on the last output-reload insn to use it. Similarly
for any secondary register. */
if (PRESERVE_DEATH_INFO_REGNO_P (REGNO (reloadreg)))
for (p = get_last_insn (); p; p = PREV_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& reg_overlap_mentioned_for_reload_p (reloadreg,
PATTERN (p)))
REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
reloadreg, REG_NOTES (p));
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
if (! special && second_reloadreg
&& PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reloadreg)))
for (p = get_last_insn (); p; p = PREV_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
&& reg_overlap_mentioned_for_reload_p (second_reloadreg,
PATTERN (p)))
REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_DEAD,
second_reloadreg,
REG_NOTES (p));
#endif
#endif
/* Look at all insns we emitted, just to be safe. */
for (p = get_insns (); p; p = NEXT_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
@ -7410,50 +7246,6 @@ emit_reload_insns (chain)
basic_block_end[chain->block] = PREV_INSN (following_insn);
}
/* Move death notes from INSN
to output-operand-address and output reload insns. */
#ifdef PRESERVE_DEATH_INFO_REGNO_P
{
rtx insn1;
/* Loop over those insns, last ones first. */
for (insn1 = PREV_INSN (following_insn); insn1 != insn;
insn1 = PREV_INSN (insn1))
if (GET_CODE (insn1) == INSN && GET_CODE (PATTERN (insn1)) == SET)
{
rtx source = SET_SRC (PATTERN (insn1));
rtx dest = SET_DEST (PATTERN (insn1));
/* The note we will examine next. */
rtx reg_notes = REG_NOTES (insn);
/* The place that pointed to this note. */
rtx *prev_reg_note = &REG_NOTES (insn);
/* If the note is for something used in the source of this
reload insn, or in the output address, move the note. */
while (reg_notes)
{
rtx next_reg_notes = XEXP (reg_notes, 1);
if (REG_NOTE_KIND (reg_notes) == REG_DEAD
&& GET_CODE (XEXP (reg_notes, 0)) == REG
&& ((GET_CODE (dest) != REG
&& reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
dest))
|| reg_overlap_mentioned_for_reload_p (XEXP (reg_notes, 0),
source)))
{
*prev_reg_note = next_reg_notes;
XEXP (reg_notes, 1) = REG_NOTES (insn1);
REG_NOTES (insn1) = reg_notes;
}
else
prev_reg_note = &XEXP (reg_notes, 1);
reg_notes = next_reg_notes;
}
}
}
#endif
/* For all the spill regs newly reloaded in this instruction,
record what they were reloaded from, so subsequent instructions
can inherit the reloads.
@ -8183,13 +7975,6 @@ static rtx *reg_values;
static rtx invalidate_regno_rtx;
/* This is a set of registers for which we must remove REG_DEAD notes in
previous insns, because our modifications made them invalid. That can
happen if we introduced the register into the current insn, or we deleted
the current insn which used to set the register. */
static HARD_REG_SET no_longer_dead_regs;
/* Invalidate any entries in reg_values which depend on REGNO,
including those for REGNO itself. This is called if REGNO is
changing. If CLOBBER is true, then always forget anything we
@ -8392,55 +8177,6 @@ reload_cse_invalidate_rtx (dest, ignore)
reload_cse_invalidate_mem (dest);
}
/* Possibly delete death notes on the insns before INSN if modifying INSN
extended the lifespan of the registers. */
static void
reload_cse_delete_death_notes (insn)
rtx insn;
{
int dreg;
for (dreg = 0; dreg < FIRST_PSEUDO_REGISTER; dreg++)
{
rtx trial;
if (! TEST_HARD_REG_BIT (no_longer_dead_regs, dreg))
continue;
for (trial = prev_nonnote_insn (insn);
(trial
&& GET_CODE (trial) != CODE_LABEL
&& GET_CODE (trial) != BARRIER);
trial = prev_nonnote_insn (trial))
{
if (find_regno_note (trial, REG_DEAD, dreg))
{
remove_death (dreg, trial);
break;
}
}
}
}
/* Record that the current insn uses hard reg REGNO in mode MODE. This
will be used in reload_cse_delete_death_notes to delete prior REG_DEAD
notes for this register. */
static void
reload_cse_no_longer_dead (regno, mode)
int regno;
enum machine_mode mode;
{
int nregs = HARD_REGNO_NREGS (regno, mode);
while (nregs-- > 0)
{
SET_HARD_REG_BIT (no_longer_dead_regs, regno);
regno++;
}
}
/* Do a very simple CSE pass over the hard registers.
This function detects no-op moves where we happened to assign two
@ -8513,8 +8249,6 @@ reload_cse_regs_1 (first)
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
CLEAR_HARD_REG_SET (no_longer_dead_regs);
/* If this is a call instruction, forget anything stored in a
call clobbered register, or, if this is not a const call, in
memory. */
@ -8555,20 +8289,18 @@ reload_cse_regs_1 (first)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
reload_cse_delete_death_notes (insn);
/* We're done with this insn. */
continue;
}
/* It's not a no-op, but we can try to simplify it. */
CLEAR_HARD_REG_SET (no_longer_dead_regs);
count += reload_cse_simplify_set (body, insn);
if (count > 0 && apply_change_group ())
reload_cse_delete_death_notes (insn);
else if (reload_cse_simplify_operands (insn))
reload_cse_delete_death_notes (insn);
if (count > 0)
apply_change_group ();
else
reload_cse_simplify_operands (insn);
reload_cse_record_set (body, body);
}
@ -8612,22 +8344,20 @@ reload_cse_regs_1 (first)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
reload_cse_delete_death_notes (insn);
/* We're done with this insn. */
continue;
}
/* It's not a no-op, but we can try to simplify it. */
CLEAR_HARD_REG_SET (no_longer_dead_regs);
for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
if (GET_CODE (XVECEXP (body, 0, i)) == SET)
count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
if (count > 0 && apply_change_group ())
reload_cse_delete_death_notes (insn);
else if (reload_cse_simplify_operands (insn))
reload_cse_delete_death_notes (insn);
if (count > 0)
apply_change_group ();
else
reload_cse_simplify_operands (insn);
/* Look through the PARALLEL and record the values being
set, if possible. Also handle any CLOBBERs. */
@ -8806,14 +8536,6 @@ reload_cse_noop_set_p (set, insn)
ret = 1;
}
/* If we can delete this SET, then we need to look for an earlier
REG_DEAD note on DREG, and remove it if it exists. */
if (ret && dreg >= 0)
{
if (! find_regno_note (insn, REG_UNUSED, dreg))
reload_cse_no_longer_dead (dreg, dest_mode);
}
return ret;
}
@ -8873,11 +8595,8 @@ reload_cse_simplify_set (set, insn)
storage. */
push_obstacks (&reload_obstack, &reload_obstack);
if (validated && ! find_regno_note (insn, REG_UNUSED, i))
{
reload_cse_no_longer_dead (i, dest_mode);
return 1;
}
if (validated)
return 1;
}
}
return 0;
@ -9082,7 +8801,6 @@ reload_cse_simplify_operands (insn)
/* Substitute the operands as determined by op_alt_regno for the best
alternative. */
j = alternative_order[0];
CLEAR_HARD_REG_SET (no_longer_dead_regs);
/* Pop back to the real obstacks while changing the insn. */
pop_obstacks ();
@ -9093,7 +8811,6 @@ reload_cse_simplify_operands (insn)
if (op_alt_regno[i][j] == -1)
continue;
reload_cse_no_longer_dead (op_alt_regno[i][j], mode);
validate_change (insn, recog_operand_loc[i],
gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
}
@ -9106,7 +8823,6 @@ reload_cse_simplify_operands (insn)
if (op_alt_regno[op][j] == -1)
continue;
reload_cse_no_longer_dead (op_alt_regno[op][j], mode);
validate_change (insn, recog_dup_loc[i],
gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
}
@ -9693,8 +9409,7 @@ static int reg_base_reg[FIRST_PSEUDO_REGISTER];
static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
/* move2add_luid is linearily increased while scanning the instructions
from first to last. It is used to set reg_set_luid in
reload_cse_move2add and move2add_note_store, and to set reg_death_luid
(local variable of reload_cse_move2add) . */
reload_cse_move2add and move2add_note_store. */
static int move2add_luid;
static void
@ -9704,16 +9419,10 @@ reload_cse_move2add (first)
int i;
rtx insn;
int last_label_luid;
/* reg_death and reg_death_luid are solely used to remove stale REG_DEAD
notes. */
int reg_death_luid[FIRST_PSEUDO_REGISTER];
rtx reg_death[FIRST_PSEUDO_REGISTER];
for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
{
reg_set_luid[i] = 0;
reg_death_luid[i] = 0;
}
reg_set_luid[i] = 0;
last_label_luid = 0;
move2add_luid = 1;
for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
@ -9768,8 +9477,6 @@ reload_cse_move2add (first)
&& have_add2_insn (GET_MODE (reg)))
success = validate_change (insn, &PATTERN (insn),
gen_add2_insn (reg, new_src), 0);
if (success && reg_death_luid[regno] > reg_set_luid[regno])
remove_death (regno, reg_death[regno]);
reg_set_luid[regno] = move2add_luid;
reg_mode[regno] = GET_MODE (reg);
reg_offset[regno] = src;
@ -9818,8 +9525,6 @@ reload_cse_move2add (first)
gen_add2_insn (reg, new_src), 0);
if (success)
{
if (reg_death_luid[regno] > reg_set_luid[regno])
remove_death (regno, reg_death[regno]);
/* INSN might be the first insn in a basic block
if the preceding insn is a conditional jump
or a possible-throwing call. */
@ -9851,18 +9556,6 @@ reload_cse_move2add (first)
reg_offset[regno] = note;
}
}
/* Remember any REG_DEAD notes so that we can remove them
later if necessary. */
else if (REG_NOTE_KIND (note) == REG_DEAD
&& GET_CODE (XEXP (note, 0)) == REG)
{
int regno = REGNO (XEXP (note, 0));
if (regno < FIRST_PSEUDO_REGISTER)
{
reg_death[regno] = insn;
reg_death_luid[regno] = move2add_luid;
}
}
}
note_stores (PATTERN (insn), move2add_note_store);
/* If this is a CALL_INSN, all call used registers are stored with

View File

@ -131,12 +131,6 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "insn-attr.h"
/* Import list of registers used as spill regs from reload. */
extern HARD_REG_SET used_spill_regs;
/* Import highest label used in function at end of reload. */
extern int max_label_num_after_reload;
#ifdef DELAY_SLOTS
@ -2584,14 +2578,6 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
CLEAR_HARD_REG_SET (pending_dead_regs);
if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
{
/* All spill registers are dead at a label, so kill all of the
ones that aren't needed also. */
COPY_HARD_REG_SET (scratch, used_spill_regs);
AND_COMPL_HARD_REG_SET (scratch, needed.regs);
AND_COMPL_HARD_REG_SET (res->regs, scratch);
}
continue;
case BARRIER:

View File

@ -1194,30 +1194,21 @@ dead_or_set_regno_p (insn, test_regno)
int regno, endregno;
rtx link;
/* REG_READ notes are not normally maintained after reload, so we
ignore them if the are invalid. */
if (! reload_completed
#ifdef PRESERVE_DEATH_INFO_REGNO_P
|| PRESERVE_DEATH_INFO_REGNO_P (test_regno)
#endif
)
/* See if there is a death note for something that includes
TEST_REGNO. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
{
/* See if there is a death note for something that includes
TEST_REGNO. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
{
if (REG_NOTE_KIND (link) != REG_DEAD
|| GET_CODE (XEXP (link, 0)) != REG)
continue;
if (REG_NOTE_KIND (link) != REG_DEAD
|| GET_CODE (XEXP (link, 0)) != REG)
continue;
regno = REGNO (XEXP (link, 0));
endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
: regno + HARD_REGNO_NREGS (regno,
GET_MODE (XEXP (link, 0))));
regno = REGNO (XEXP (link, 0));
endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
: regno + HARD_REGNO_NREGS (regno,
GET_MODE (XEXP (link, 0))));
if (test_regno >= regno && test_regno < endregno)
return 1;
}
if (test_regno >= regno && test_regno < endregno)
return 1;
}
if (GET_CODE (insn) == CALL_INSN
@ -1231,7 +1222,7 @@ dead_or_set_regno_p (insn, test_regno)
/* A value is totally replaced if it is the destination or the
destination is a SUBREG of REGNO that does not change the number of
words in it. */
if (GET_CODE (dest) == SUBREG
if (GET_CODE (dest) == SUBREG
&& (((GET_MODE_SIZE (GET_MODE (dest))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))

View File

@ -1554,27 +1554,6 @@ sched_analyze_insn (x, insn, loop_notes)
REG_NOTES (insn) = loop_notes;
}
/* After reload, it is possible for an instruction to have a REG_DEAD note
for a register that actually dies a few instructions earlier. For
example, this can happen with SECONDARY_MEMORY_NEEDED reloads.
In this case, we must consider the insn to use the register mentioned
in the REG_DEAD note. Otherwise, we may accidentally move this insn
after another insn that sets the register, thus getting obviously invalid
rtl. This confuses reorg which believes that REG_DEAD notes are still
meaningful.
??? We would get better code if we fixed reload to put the REG_DEAD
notes in the right places, but that may not be worth the effort. */
if (reload_completed)
{
rtx note;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_DEAD)
sched_analyze_2 (XEXP (note, 0), insn);
}
EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
{
reg_last_sets[i] = insn;
@ -3849,16 +3828,7 @@ update_flow_info (notes, first, last, orig_insn)
register that was not needed by this instantiation of the
pattern, so we can safely ignore it. */
if (insn == first)
{
/* After reload, REG_DEAD notes come sometimes an
instruction after the register actually dies. */
if (reload_completed && REG_NOTE_KIND (note) == REG_DEAD)
{
XEXP (note, 1) = REG_NOTES (insn);
REG_NOTES (insn) = note;
break;
}
{
if (REG_NOTE_KIND (note) != REG_UNUSED)
abort ();

View File

@ -1684,24 +1684,6 @@ If this macro is not defined, it means that no insn clobbers registers
mysteriously. This is the usual situation; all else being equal,
it is best for the RTL expression to show all the activity.
@cindex death notes
@findex PRESERVE_DEATH_INFO_REGNO_P
@item PRESERVE_DEATH_INFO_REGNO_P (@var{regno})
If defined, this is a C expression whose value is nonzero if correct
@code{REG_DEAD} notes are needed for hard register number @var{regno}
after reload.
You would arrange to preserve death info for a register when some of the
code in the machine description which is executed to write the assembler
code looks at the death notes. This is necessary only when the actual
hardware feature which GNU CC thinks of as a register is not actually a
register of the usual sort. (It might, for example, be a hardware
stack.)
It is also useful for peepholes and linker relaxation.
If this macro is not defined, it means that no death notes need to be
preserved, and some may even be incorrect. This is the usual situation.
@end table
@node Register Classes

View File

@ -355,10 +355,6 @@ lang_expand_expr_t lang_expand_expr = 0;
void (*incomplete_decl_finalize_hook) PROTO((tree)) = 0;
/* Highest label number used at the end of reload. */
int max_label_num_after_reload;
/* Nonzero if generating code to do profiling. */
int profile_flag = 0;
@ -3756,10 +3752,6 @@ rest_of_compilation (decl)
if (global_reg_dump)
open_dump_file (".greg", decl_printable_name (decl, 2));
/* Save the last label number used so far, so reorg can tell
when it's safe to kill spill regs. */
max_label_num_after_reload = max_label_num ();
/* Unless we did stupid register allocation,
allocate remaining pseudo-regs, then do the reload pass
fixing up any insns that are invalid. */
@ -3782,6 +3774,15 @@ rest_of_compilation (decl)
if (optimize > 0)
reload_cse_regs (insns);
/* Re-create the death notes which were deleted during reload. */
if (optimize)
TIMEVAR
(flow_time,
{
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
life_analysis (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