reload.c (find_reloads_subreg_address): New function, broken out of find_reloads_toplev.

* reload.c (find_reloads_subreg_address): New function, broken out of
	find_reloads_toplev.
	(find_reloads_toplev, find_reloads_address_1): Use it.

From-SVN: r25169
This commit is contained in:
J"orn Rennecke 1999-02-12 13:12:48 +00:00 committed by Joern Rennecke
parent 01d5caad02
commit 22505ad8f3
2 changed files with 91 additions and 28 deletions

View File

@ -1,3 +1,9 @@
Fri Feb 12 21:09:51 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
* reload.c (find_reloads_subreg_address): New function, broken out of
find_reloads_toplev.
(find_reloads_toplev, find_reloads_address_1): Use it.
Fri Feb 12 13:20:52 1999 Jeffrey A Law (law@cygnus.com)
* h8300.md (zero_extendhisi2 H8/300 variant): Correctly handle

View File

@ -338,6 +338,8 @@ static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
enum machine_mode, int,
enum reload_type, int));
static rtx find_reloads_subreg_address PROTO((rtx, int, int, enum reload_type,
int, rtx));
static int find_inc_amount PROTO((rtx, rtx));
static int loc_mentioned_in_p PROTO((rtx *, rtx));
@ -4483,34 +4485,8 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn)
XEXP (reg_equiv_mem[regno], 0))
|| ! offsettable_memref_p (reg_equiv_mem[regno])
|| num_not_at_initial_offset))))
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
/* We must rerun eliminate_regs, in case the elimination
offsets have changed. */
rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0,
NULL_RTX),
0);
if (BYTES_BIG_ENDIAN)
{
int size;
size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
offset += MIN (size, UNITS_PER_WORD);
size = GET_MODE_SIZE (GET_MODE (x));
offset -= MIN (size, UNITS_PER_WORD);
}
addr = plus_constant (addr, offset);
x = gen_rtx_MEM (GET_MODE (x), addr);
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
find_reloads_address (GET_MODE (x), &x,
XEXP (x, 0),
&XEXP (x, 0), opnum, type, ind_levels, insn);
/* If this is not a toplevel operand, find_reloads doesn't see this
substitution. We have to emit a USE of the pseudo so that
delete_output_reload can see it. */
if (replace_reloads && recog_operand[opnum] != x)
emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
}
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
insn);
}
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@ -5519,6 +5495,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
x = find_reloads_subreg_address (x, 0, opnum, type,
ind_levels, insn);
push_reload (x, NULL_RTX, loc, NULL_PTR, class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
@ -5615,6 +5593,85 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
mode, VOIDmode, 0, 0, opnum, type);
}
/* X, a subreg of a pseudo, is a part of an address that needs to be
reloaded.
If the pseudo is equivalent to a memory location that cannot be directly
addressed, make the necessary address reloads.
If address reloads have been necessary, or if the address is changed
by register elimination, return the rtx of the memory location;
otherwise, return X.
If FORCE_REPLACE is nonzero, unconditionally replace the subreg with the
memory location.
OPNUM and TYPE identify the purpose of the reload.
IND_LEVELS says how many levels of indirect addressing are
supported at this point in the address.
INSN, if nonzero, is the insn in which we do the reload. It is used
to determine where to put USEs for pseudos that we have to replace with
stack slots. */
static rtx
find_reloads_subreg_address (x, force_replace, opnum, type,
ind_levels, insn)
rtx x;
int force_replace;
int opnum;
enum reload_type type;
int ind_levels;
rtx insn;
{
int regno = REGNO (SUBREG_REG (x));
if (reg_equiv_memory_loc[regno])
{
/* If the address is not directly addressable, or if the address is not
offsettable, then it must be replaced. */
if (! force_replace
&& (reg_equiv_address[regno]
|| ! offsettable_memref_p (reg_equiv_mem[regno])))
force_replace = 1;
if (force_replace || num_not_at_initial_offset)
{
rtx tem = make_memloc (SUBREG_REG (x), regno);
/* If the address changes because of register elimination, then
it must be replaced. */
if (force_replace
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
{
int size;
size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
offset += MIN (size, UNITS_PER_WORD);
size = GET_MODE_SIZE (GET_MODE (x));
offset -= MIN (size, UNITS_PER_WORD);
}
XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
PUT_MODE (tem, GET_MODE (x));
x = tem;
find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
that delete_output_reload can see it. */
if (replace_reloads && recog_operand[opnum] != x)
emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
}
}
}
return x;
}
/* Substitute into the current INSN the registers into which we have reloaded
the things that need reloading. The array `replacements'
says contains the locations of all pointers that must be changed