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:
parent
01d5caad02
commit
22505ad8f3
|
@ -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)
|
Fri Feb 12 13:20:52 1999 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
* h8300.md (zero_extendhisi2 H8/300 variant): Correctly handle
|
* h8300.md (zero_extendhisi2 H8/300 variant): Correctly handle
|
||||||
|
|
113
gcc/reload.c
113
gcc/reload.c
|
@ -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,
|
static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
|
||||||
enum machine_mode, int,
|
enum machine_mode, int,
|
||||||
enum reload_type, 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 find_inc_amount PROTO((rtx, rtx));
|
||||||
static int loc_mentioned_in_p 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))
|
XEXP (reg_equiv_mem[regno], 0))
|
||||||
|| ! offsettable_memref_p (reg_equiv_mem[regno])
|
|| ! offsettable_memref_p (reg_equiv_mem[regno])
|
||||||
|| num_not_at_initial_offset))))
|
|| num_not_at_initial_offset))))
|
||||||
{
|
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
|
||||||
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
|
insn);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
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)))
|
if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
|
||||||
> reg_class_size[class])
|
> 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,
|
push_reload (x, NULL_RTX, loc, NULL_PTR, class,
|
||||||
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
|
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -5615,6 +5593,85 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
|
||||||
mode, VOIDmode, 0, 0, opnum, type);
|
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
|
/* Substitute into the current INSN the registers into which we have reloaded
|
||||||
the things that need reloading. The array `replacements'
|
the things that need reloading. The array `replacements'
|
||||||
says contains the locations of all pointers that must be changed
|
says contains the locations of all pointers that must be changed
|
||||||
|
|
Loading…
Reference in New Issue