Commit 5adf6da0 by J"orn Rennecke Committed by Joern Rennecke

reload1.c (reload_cse_regs_1): Renamed from reload_cse_regs.

	* reload1.c (reload_cse_regs_1): Renamed from reload_cse_regs.
	(reload_cse_regs): New function body: call reload_cse_regs_1,
	reload_combine, reload_cse_move2add.
	When doing expensive_optimizations, call reload_cse_regs_1 a
	second time after reload_cse_move2add.
	(reload_combine, reload_combine_note_store): New functions.
	(reload_combine_note_use): New function.
	(reload_cse_move2add, move2add_note_store): New functions.

From-SVN: r22570
parent f6b58262
Thu Sep 24 21:22:39 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
* reload1.c (reload_cse_regs_1): Renamed from reload_cse_regs.
(reload_cse_regs): New function body: call reload_cse_regs_1,
reload_combine, reload_cse_move2add.
When doing expensive_optimizations, call reload_cse_regs_1 a
second time after reload_cse_move2add.
(reload_combine, reload_combine_note_store): New functions.
(reload_combine_note_use): New function.
(reload_cse_move2add, move2add_note_store): New functions.
Thu Sep 24 18:48:43 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
* reload.c (find_reloads): In code to promote RELOAD_FOR_X_ADDR_ADDR
......
......@@ -391,6 +391,7 @@ static void emit_reload_insns PROTO((rtx, int));
static void delete_output_reload PROTO((rtx, int, rtx));
static void inc_for_reload PROTO((rtx, rtx, int));
static int constraint_accepts_reg_p PROTO((char *, rtx));
static void reload_cse_regs_1 PROTO((rtx));
static void reload_cse_invalidate_regno PROTO((int, enum machine_mode, int));
static int reload_cse_mem_conflict_p PROTO((rtx, rtx));
static void reload_cse_invalidate_mem PROTO((rtx));
......@@ -403,6 +404,11 @@ 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));
static void reload_cse_move2add PROTO((rtx));
static void move2add_note_store PROTO((rtx, rtx));
/* Initialize the reload pass once per compilation. */
......@@ -8330,8 +8336,8 @@ reload_cse_no_longer_dead (regno, mode)
hard register. It then replaces the operand with the hard register
if possible, much like an optional reload would. */
void
reload_cse_regs (first)
static void
reload_cse_regs_1 (first)
rtx first;
{
char *firstobj;
......@@ -8547,6 +8553,19 @@ reload_cse_regs (first)
pop_obstacks ();
}
/* Call cse / combine like post-reload optimization phases.
FIRST is the first instruction. */
void
reload_cse_regs (first)
rtx first;
{
reload_cse_regs_1 (first);
reload_combine ();
reload_cse_move2add (first);
if (flag_expensive_optimizations)
reload_cse_regs_1 (first);
}
/* Return whether the values known for REGNO are equal to VAL. MODE
is the mode of the object that VAL is being copied to; this matters
if VAL is a CONST_INT. */
......@@ -9144,3 +9163,670 @@ reload_cse_record_set (set, body)
abort ();
}
}
/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
addressing now.
This code might also be useful when reload gave up on reg+reg addresssing
because of clashes between the return register and INDEX_REG_CLASS. */
/* The maximum number of uses of a register we can keep track of to
replace them with reg+reg addressing. */
#define RELOAD_COMBINE_MAX_USES 6
/* INSN is the insn where a register has ben used, and USEP points to the
location of the register within the rtl. */
struct reg_use { rtx insn, *usep; };
/* If the register is used in some unknown fashion, USE_INDEX is negative.
If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
indicates where it becomes live again.
Otherwise, USE_INDEX is the index of the last encountered use of the
register (which is first among these we have seen since we scan backwards),
OFFSET contains the constant offset that is added to the register in
all encountered uses, and USE_RUID indicates the first encountered, i.e.
last, of these uses. */
static struct
{
struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
int use_index;
rtx offset;
int store_ruid;
int use_ruid;
} reg_state[FIRST_PSEUDO_REGISTER];
/* Reverse linear uid. This is increased in reload_combine while scanning
the instructions from last to first. It is used to set last_label_ruid
and the store_ruid / use_ruid fields in reg_state. */
static int reload_combine_ruid;
static void
reload_combine ()
{
rtx insn, set;
int first_index_reg = 1, last_index_reg = 0;
int i;
int last_label_ruid;
/* If reg+reg can be used in offsetable memory adresses, the main chunk of
reload has already used it where appropriate, so there is no use in
trying to generate it now. */
if (double_reg_address_ok && reload_address_index_reg_class != NO_REGS)
return;
/* To avoid wasting too much time later searching for an index register,
determine the minimum and maximum index register numbers. */
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
{
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i))
{
if (! last_index_reg)
last_index_reg = i;
first_index_reg = i;
}
}
/* If no index register is available, we can quit now. */
if (first_index_reg > last_index_reg)
return;
/* Initialize last_label_ruid, reload_combine_ruid and reg_state. */
last_label_ruid = reload_combine_ruid = 0;
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
{
if (fixed_regs[i])
reg_state[i].use_index = -1;
else
{
reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[i].store_ruid = reload_combine_ruid;
}
}
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
{
rtx note;
/* We cannot do our optimization across labels. Invalidating all the use
information we have would be costly, so we just note where the label
is and then later disable any optimization that would cross it. */
if (GET_CODE (insn) == CODE_LABEL)
last_label_ruid = reload_combine_ruid;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
reload_combine_ruid++;
/* Look for (set (REGX) (CONST_INT))
(set (REGX) (PLUS (REGX) (REGY)))
...
... (MEM (REGX)) ...
and convert it to
(set (REGZ) (CONST_INT))
...
... (MEM (PLUS (REGZ) (REGY)))... .
First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
and that we know all uses of REGX before it dies. */
if (set
&& GET_CODE (SET_DEST (set)) == REG
&& (HARD_REGNO_NREGS (REGNO (SET_DEST (set)),
GET_MODE (SET_DEST (set)))
== 1)
&& GET_CODE (SET_SRC (set)) == PLUS
&& GET_CODE (XEXP (SET_SRC (set), 1)) == REG
&& rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
&& last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
{
rtx reg = SET_DEST (set);
rtx plus = SET_SRC (set);
rtx base = XEXP (plus, 1);
rtx prev = prev_nonnote_insn (insn);
rtx prev_set = prev ? single_set (prev) : NULL_RTX;
int regno = REGNO (reg);
rtx const_reg;
rtx reg_sum = NULL_RTX;
/* Now, we need an index register.
We'll set index_reg to this index register, const_reg to the
register that is to be loaded with the constant
(denoted as REGZ in the substitution illustration above),
and reg_sum to the register-register that we want to use to
substitute uses of REG (typically in MEMs) with.
First check REG and BASE for being index registers;
we can use them even if they are not dead. */
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
|| TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
REGNO (base)))
{
const_reg = reg;
reg_sum = plus;
}
else
{
/* Otherwise, look for a free index register. Since we have
checked above that neiter REG nor BASE are index registers,
if we find anything at all, it will be different from these
two registers. */
for (i = first_index_reg; i <= last_index_reg; i++)
{
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
&& reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
&& reg_state[i].store_ruid <= reg_state[regno].use_ruid
&& HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1)
{
rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
const_reg = index_reg;
reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
break;
}
}
}
if (prev_set
&& GET_CODE (SET_SRC (prev_set)) == CONST_INT
&& rtx_equal_p (SET_DEST (prev_set), reg)
&& reg_state[regno].use_index >= 0
&& reg_sum)
{
int i;
/* Change destination register and - if necessary - the
constant value in PREV, the constant loading instruction. */
validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
if (reg_state[regno].offset != const0_rtx)
validate_change (prev,
&SET_SRC (prev_set),
GEN_INT (INTVAL (SET_SRC (prev_set))
+ INTVAL (reg_state[regno].offset)),
1);
/* Now for every use of REG that we have recorded, replace REG
with REG_SUM. */
for (i = reg_state[regno].use_index;
i < RELOAD_COMBINE_MAX_USES; i++)
validate_change (reg_state[regno].reg_use[i].insn,
reg_state[regno].reg_use[i].usep,
reg_sum, 1);
if (apply_change_group ())
{
rtx *np;
/* Delete the reg-reg addition. */
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
if (reg_state[regno].offset != const0_rtx)
{
/* Previous REG_EQUIV / REG_EQUAL notes for PREV
are now invalid. */
for (np = &REG_NOTES (prev); *np; )
{
if (REG_NOTE_KIND (*np) == REG_EQUAL
|| REG_NOTE_KIND (*np) == REG_EQUIV)
*np = XEXP (*np, 1);
else
np = &XEXP (*np, 1);
}
}
reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[REGNO (const_reg)].store_ruid = reload_combine_ruid;
continue;
}
}
}
note_stores (PATTERN (insn), reload_combine_note_store);
if (GET_CODE (insn) == CALL_INSN)
{
rtx link;
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
{
if (call_used_regs[i])
{
reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[i].store_ruid = reload_combine_ruid;
}
}
for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
link = XEXP (link, 1))
{
rtx use = XEXP (link, 0);
int regno = REGNO (XEXP (use, 0));
if (GET_CODE (use) == CLOBBER)
{
reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[regno].store_ruid = reload_combine_ruid;
}
else
reg_state[regno].use_index = -1;
}
}
if (GET_CODE (insn) == JUMP_INSN)
{
/* Non-spill registers might be used at the call destination in
some unknown fashion, so we have to mark the unknown use. */
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
{
if (! TEST_HARD_REG_BIT (used_spill_regs, i))
reg_state[i].use_index = -1;
}
}
reload_combine_note_use (&PATTERN (insn), insn);
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{
if (REG_NOTE_KIND (note) == REG_INC
&& GET_CODE (XEXP (note, 0)) == REG)
reg_state[REGNO (XEXP (note, 0))].use_index = -1;
}
}
}
/* Check if DST is a register or a subreg of a register; if it is,
update reg_state[regno].store_ruid and reg_state[regno].use_index
accordingly. Called via note_stores from reload_combine.
The second argument, SET, is ignored. */
static void
reload_combine_note_store (dst, set)
rtx dst, set;
{
int regno = 0;
int i;
unsigned size = GET_MODE_SIZE (GET_MODE (dst));
if (GET_CODE (dst) == SUBREG)
{
regno = SUBREG_WORD (dst);
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG)
return;
regno += REGNO (dst);
/* note_stores might have stripped a STRICT_LOW_PART, so we have to be
careful with registers / register parts that are not full words. */
if (size < UNITS_PER_WORD)
reg_state[regno].use_index = -1;
else
{
for (i = size / UNITS_PER_WORD - 1 + regno; i >= regno; i--)
{
reg_state[i].store_ruid = reload_combine_ruid;
reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
}
}
}
/* XP points to a piece of rtl that has to be checked for any uses of
registers.
*XP is the pattern of INSN, or a part of it.
Called from reload_combine, and recursively by itself. */
static void
reload_combine_note_use (xp, insn)
rtx *xp, insn;
{
rtx x = *xp;
enum rtx_code code = x->code;
char *fmt;
int i, j;
rtx offset = const0_rtx; /* For the REG case below. */
switch (code)
{
case SET:
if (GET_CODE (SET_DEST (x)) == REG)
{
reload_combine_note_use (&SET_SRC (x), insn);
return;
}
break;
case CLOBBER:
if (GET_CODE (SET_DEST (x)) == REG)
return;
break;
case PLUS:
/* We are interested in (plus (reg) (const_int)) . */
if (GET_CODE (XEXP (x, 0)) != REG || GET_CODE (XEXP (x, 1)) != CONST_INT)
break;
offset = XEXP (x, 1);
x = XEXP (x, 0);
/* Fall through. */
case REG:
{
int regno = REGNO (x);
int use_index;
/* Some spurious USEs of pseudo registers might remain.
Just ignore them. */
if (regno >= FIRST_PSEUDO_REGISTER)
return;
/* If this register is already used in some unknown fashion, we
can't do anything.
If we decrement the index from zero to -1, we can't store more
uses, so this register becomes used in an unknown fashion. */
use_index = --reg_state[regno].use_index;
if (use_index < 0)
return;
if (use_index != RELOAD_COMBINE_MAX_USES - 1)
{
/* We have found another use for a register that is already
used later. Check if the offsets match; if not, mark the
register as used in an unknown fashion. */
if (! rtx_equal_p (offset, reg_state[regno].offset))
{
reg_state[regno].use_index = -1;
return;
}
}
else
{
/* This is the first use of this register we have seen since we
marked it as dead. */
reg_state[regno].offset = offset;
reg_state[regno].use_ruid = reload_combine_ruid;
}
reg_state[regno].reg_use[use_index].insn = insn;
reg_state[regno].reg_use[use_index].usep = xp;
return;
}
default:
break;
}
/* Recursively process the components of X. */
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
reload_combine_note_use (&XEXP (x, i), insn);
else if (fmt[i] == 'E')
{
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
reload_combine_note_use (&XVECEXP (x, i, j), insn);
}
}
}
/* See if we can reduce the cost of a constant by replacing a move with
an add. */
/* We cannot do our optimization across labels. Invalidating all the
information about register contents we have would be costly, so we
use last_label_luid (local variable of reload_cse_move2add) to note
where the label is and then later disable any optimization that would
cross it.
reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
reg_set_luid[n] is larger than last_label_luid[n] . */
static int reg_set_luid[FIRST_PSEUDO_REGISTER];
/* reg_offset[n] has to be CONST_INT for it and reg_base_reg[n] /
reg_mode[n] to be valid.
If reg_offset[n] is a CONST_INT and reg_base_reg[n] is negative, register n
has been set to reg_offset[n] in mode reg_mode[n] .
If reg_offset[n] is a CONST_INT and reg_base_reg[n] is non-negative,
register n has been set to the sum of reg_offset[n] and register
reg_base_reg[n], calculated in mode reg_mode[n] . */
static rtx reg_offset[FIRST_PSEUDO_REGISTER];
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) . */
static int move2add_luid;
static void
reload_cse_move2add (first)
rtx 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;
}
last_label_luid = 0;
move2add_luid = 1;
for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
{
rtx pat, note;
if (GET_CODE (insn) == CODE_LABEL)
last_label_luid = move2add_luid;
if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
continue;
pat = PATTERN (insn);
/* For simplicity, we only perform this optimization on
straightforward SETs. */
if (GET_CODE (pat) == SET
&& GET_CODE (SET_DEST (pat)) == REG)
{
rtx reg = SET_DEST (pat);
int regno = REGNO (reg);
rtx src = SET_SRC (pat);
/* Check if we have valid information on the contents of this
register in the mode of REG. */
/* ??? We don't know how zero / sign extension is handled, hence
we can't go from a narrower to a wider mode. */
if (reg_set_luid[regno] > last_label_luid
&& (GET_MODE_SIZE (GET_MODE (reg))
<= GET_MODE_SIZE (reg_mode[regno]))
&& GET_CODE (reg_offset[regno]) == CONST_INT)
{
/* Try to transform (set (REGX) (CONST_INT A))
...
(set (REGX) (CONST_INT B))
to
(set (REGX) (CONST_INT A))
...
(set (REGX) (plus (REGX) (CONST_INT B-A))) */
if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
{
int success = 0;
rtx new_src = GEN_INT (INTVAL (src)
- INTVAL (reg_offset[regno]));
/* (set (reg) (plus (reg) (const_int 0))) is not canonical;
use (set (reg) (reg)) instead.
We don't delete this insn, nor do we convert it into a
note, to avoid losing register notes or the return
value flag. jump2 already knowns how to get rid of
no-op moves. */
if (new_src == const0_rtx)
success = validate_change (insn, &SET_SRC (pat), reg, 0);
else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
&& 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;
continue;
}
/* Try to transform (set (REGX) (REGY))
(set (REGX) (PLUS (REGX) (CONST_INT A)))
...
(set (REGX) (REGY))
(set (REGX) (PLUS (REGX) (CONST_INT B)))
to
(REGX) (REGY))
(set (REGX) (PLUS (REGX) (CONST_INT A)))
...
(set (REGX) (plus (REGX) (CONST_INT B-A))) */
else if (GET_CODE (src) == REG
&& reg_base_reg[regno] == REGNO (src)
&& reg_set_luid[regno] > reg_set_luid[REGNO (src)])
{
rtx next = next_nonnote_insn (insn);
rtx set;
if (next)
set = single_set (next);
if (next
&& set
&& SET_DEST (set) == reg
&& GET_CODE (SET_SRC (set)) == PLUS
&& XEXP (SET_SRC (set), 0) == reg
&& GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
{
rtx src2 = SET_SRC (set);
rtx src3 = XEXP (SET_SRC (set), 1);
rtx new_src = GEN_INT (INTVAL (src3)
- INTVAL (reg_offset[regno]));
int success = 0;
if (new_src == const0_rtx)
/* See above why we create (set (reg) (reg)) here. */
success
= validate_change (next, &SET_SRC (set), reg, 0);
else if ((rtx_cost (new_src, PLUS)
< 2 + rtx_cost (src3, SET))
&& have_add2_insn (GET_MODE (reg)))
success
= validate_change (next, &PATTERN (next),
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. */
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
insn = next;
reg_set_luid[regno] = move2add_luid;
reg_mode[regno] = GET_MODE (reg);
reg_offset[regno] = src3;
continue;
}
}
}
}
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{
if (REG_NOTE_KIND (note) == REG_INC
&& GET_CODE (XEXP (note, 0)) == REG)
{
/* Indicate that this register has been recently written to,
but the exact contents are not available. */
int regno = REGNO (XEXP (note, 0));
if (regno < FIRST_PSEUDO_REGISTER)
{
reg_set_luid[regno] = move2add_luid;
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
unknown values. */
if (GET_CODE (insn) == CALL_INSN)
{
for (i = FIRST_PSEUDO_REGISTER-1; i >= 0; i--)
{
if (call_used_regs[i])
{
reg_set_luid[i] = move2add_luid;
reg_offset[i] = insn; /* Invalidate contents. */
}
}
}
}
}
/* SET is a SET or CLOBBER that sets DST.
Update reg_set_luid, reg_offset and reg_base_reg accordingly.
Called from reload_cse_move2add via note_stores. */
static void
move2add_note_store (dst, set)
rtx dst, set;
{
int regno = 0;
int i;
enum machine_mode mode = GET_MODE (dst);
if (GET_CODE (dst) == SUBREG)
{
regno = SUBREG_WORD (dst);
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG)
return;
regno += REGNO (dst);
if (HARD_REGNO_NREGS (regno, mode) == 1 && GET_CODE (set) == SET)
{
rtx src = SET_SRC (set);
reg_mode[regno] = mode;
switch (GET_CODE (src))
{
case PLUS:
{
rtx src0 = XEXP (src, 0);
if (GET_CODE (src0) == REG)
{
if (REGNO (src0) != regno
|| reg_offset[regno] != const0_rtx)
{
reg_base_reg[regno] = REGNO (src0);
reg_set_luid[regno] = move2add_luid;
}
reg_offset[regno] = XEXP (src, 1);
break;
}
reg_set_luid[regno] = move2add_luid;
reg_offset[regno] = set; /* Invalidate contents. */
break;
}
case REG:
reg_base_reg[regno] = REGNO (SET_SRC (set));
reg_offset[regno] = const0_rtx;
reg_set_luid[regno] = move2add_luid;
break;
default:
reg_base_reg[regno] = -1;
reg_offset[regno] = SET_SRC (set);
reg_set_luid[regno] = move2add_luid;
break;
}
}
else
{
for (i = regno + HARD_REGNO_NREGS (regno, mode) - 1; i >= regno; i--)
{
/* Indicate that this register has been recently written to,
but the exact contents are not available. */
reg_set_luid[i] = move2add_luid;
reg_offset[i] = dst;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment