Commit 80de67b8 by Ulrich Weigand Committed by Ulrich Weigand

reload.c (find_reloads_subreg_address): Remove FORCE_REPLACE parameter.

	* reload.c (find_reloads_subreg_address): Remove FORCE_REPLACE
	parameter.  Always replace normal subreg with memory reference
	whenever possible.  Return NULL otherwise.
	(find_reloads_toplev): Always call find_reloads_subreg_address
	for subregs of registers equivalent to a memory location.
	Only recurse further if find_reloads_subreg_address fails.
	(find_reloads_address_1): Only call find_reloads_subreg_address
	for subregs of registers equivalent to a memory location.
	Properly handle failure of find_reloads_subreg_address.

From-SVN: r192499
parent 16e82b25
2012-10-16 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* reload.c (find_reloads_subreg_address): Remove FORCE_REPLACE
parameter. Always replace normal subreg with memory reference
whenever possible. Return NULL otherwise.
(find_reloads_toplev): Always call find_reloads_subreg_address
for subregs of registers equivalent to a memory location.
Only recurse further if find_reloads_subreg_address fails.
(find_reloads_address_1): Only call find_reloads_subreg_address
for subregs of registers equivalent to a memory location.
Properly handle failure of find_reloads_subreg_address.
2012-10-16 Jakub Jelinek <jakub@redhat.com> 2012-10-16 Jakub Jelinek <jakub@redhat.com>
PR debug/54796 PR debug/54796
...@@ -282,7 +282,7 @@ static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int, ...@@ -282,7 +282,7 @@ static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
static void find_reloads_address_part (rtx, rtx *, enum reg_class, static void find_reloads_address_part (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 (rtx, int, int, enum reload_type, static rtx find_reloads_subreg_address (rtx, int, enum reload_type,
int, rtx, int *); int, rtx, int *);
static void copy_replacements_1 (rtx *, rtx *, int); static void copy_replacements_1 (rtx *, rtx *, int);
static int find_inc_amount (rtx, rtx); static int find_inc_amount (rtx, rtx);
...@@ -4810,31 +4810,19 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type, ...@@ -4810,31 +4810,19 @@ find_reloads_toplev (rtx x, int opnum, enum reload_type type,
} }
/* If the subreg contains a reg that will be converted to a mem, /* If the subreg contains a reg that will be converted to a mem,
convert the subreg to a narrower memref now. attempt to convert the whole subreg to a (narrower or wider)
Otherwise, we would get (subreg (mem ...) ...), memory reference instead. If this succeeds, we're done --
which would force reload of the mem. otherwise fall through to check whether the inner reg still
needs address reloads anyway. */
We also need to do this if there is an equivalent MEM that is
not offsettable. In that case, alter_subreg would produce an
invalid address on big-endian machines.
For machines that extend byte loads, we must not reload using
a wider mode if we have a paradoxical SUBREG. find_reloads will
force a reload in that case. So we should not do anything here. */
if (regno >= FIRST_PSEUDO_REGISTER if (regno >= FIRST_PSEUDO_REGISTER
#ifdef LOAD_EXTEND_OP && reg_equiv_memory_loc (regno) != 0)
&& !paradoxical_subreg_p (x) {
#endif tem = find_reloads_subreg_address (x, opnum, type, ind_levels,
&& (reg_equiv_address (regno) != 0
|| (reg_equiv_mem (regno) != 0
&& (! strict_memory_address_addr_space_p
(GET_MODE (x), XEXP (reg_equiv_mem (regno), 0),
MEM_ADDR_SPACE (reg_equiv_mem (regno)))
|| ! offsettable_memref_p (reg_equiv_mem (regno))
|| num_not_at_initial_offset))))
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
insn, address_reloaded); insn, address_reloaded);
if (tem)
return tem;
}
} }
for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
...@@ -6070,15 +6058,34 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as, ...@@ -6070,15 +6058,34 @@ find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
if (ira_reg_class_max_nregs [rclass][GET_MODE (SUBREG_REG (x))] if (ira_reg_class_max_nregs [rclass][GET_MODE (SUBREG_REG (x))]
> reg_class_size[(int) rclass]) > reg_class_size[(int) rclass])
{ {
x = find_reloads_subreg_address (x, 0, opnum, /* If the inner register will be replaced by a memory
reference, we can do this only if we can replace the
whole subreg by a (narrower) memory reference. If
this is not possible, fall through and reload just
the inner register (including address reloads). */
if (reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
{
rtx tem = find_reloads_subreg_address (x, opnum,
ADDR_TYPE (type), ADDR_TYPE (type),
ind_levels, insn, NULL); ind_levels, insn,
NULL);
if (tem)
{
push_reload (tem, NULL_RTX, loc, (rtx*) 0, rclass,
GET_MODE (tem), VOIDmode, 0, 0,
opnum, type);
return 1;
}
}
else
{
push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass, push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
GET_MODE (x), VOIDmode, 0, 0, opnum, type); GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1; return 1;
} }
} }
} }
}
break; break;
default: default:
...@@ -6152,17 +6159,12 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, ...@@ -6152,17 +6159,12 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
} }
/* X, a subreg of a pseudo, is a part of an address that needs to be /* X, a subreg of a pseudo, is a part of an address that needs to be
reloaded. reloaded, and the pseusdo is equivalent to a memory location.
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 Attempt to replace the whole subreg by a (possibly narrower or wider)
by register elimination, return the rtx of the memory location; memory reference. If this is possible, return this new memory
otherwise, return X. reference, and push all required address reloads. Otherwise,
return NULL.
If FORCE_REPLACE is nonzero, unconditionally replace the subreg with the
memory location.
OPNUM and TYPE identify the purpose of the reload. OPNUM and TYPE identify the purpose of the reload.
...@@ -6174,73 +6176,58 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass, ...@@ -6174,73 +6176,58 @@ find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
stack slots. */ stack slots. */
static rtx static rtx
find_reloads_subreg_address (rtx x, int force_replace, int opnum, find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
enum reload_type type, int ind_levels, rtx insn, int ind_levels, rtx insn, int *address_reloaded)
int *address_reloaded)
{ {
enum machine_mode outer_mode = GET_MODE (x);
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
int regno = REGNO (SUBREG_REG (x)); int regno = REGNO (SUBREG_REG (x));
int reloaded = 0; int reloaded = 0;
rtx tem, orig;
int offset;
if (reg_equiv_memory_loc (regno)) gcc_assert (reg_equiv_memory_loc (regno) != 0);
{
/* 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) /* We cannot replace the subreg with a modified memory reference if:
{
rtx tem = make_memloc (SUBREG_REG (x), regno);
/* If the address changes because of register elimination, then - we have a paradoxical subreg that implicitly acts as a zero or
it must be replaced. */ sign extension operation due to LOAD_EXTEND_OP;
if (force_replace
|| ! rtx_equal_p (tem, reg_equiv_mem (regno)))
{
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
rtx orig = tem;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not - we have a subreg that is implicitly supposed to act on the full
hold the correct (negative) byte offset. */ register due to WORD_REGISTER_OPERATIONS (see also eliminate_regs);
if (BYTES_BIG_ENDIAN && outer_size > inner_size)
offset = inner_size - outer_size;
else
offset = SUBREG_BYTE (x);
XEXP (tem, 0) = plus_constant (GET_MODE (XEXP (tem, 0)), - the address of the equivalent memory location is mode-dependent; or
XEXP (tem, 0), offset);
PUT_MODE (tem, GET_MODE (x));
if (MEM_OFFSET_KNOWN_P (tem))
set_mem_offset (tem, MEM_OFFSET (tem) + offset);
if (MEM_SIZE_KNOWN_P (tem)
&& MEM_SIZE (tem) != (HOST_WIDE_INT) outer_size)
set_mem_size (tem, outer_size);
/* If this was a paradoxical subreg that we replaced, the - we have a paradoxical subreg and the resulting memory is not
resulting memory must be sufficiently aligned to allow sufficiently aligned to allow access in the wider mode.
us to widen the mode of the memory. */
if (outer_size > inner_size)
{
rtx base;
base = XEXP (tem, 0); In addition, we choose not to perform the replacement for *any*
if (GET_CODE (base) == PLUS) paradoxical subreg, even if it were possible in principle. This
{ is to avoid generating wider memory references than necessary.
if (CONST_INT_P (XEXP (base, 1))
&& INTVAL (XEXP (base, 1)) % outer_size != 0) This corresponds to how previous versions of reload used to handle
return x; paradoxical subregs where no address reload was required. */
base = XEXP (base, 0);
} if (paradoxical_subreg_p (x))
if (!REG_P (base) return NULL;
|| (REGNO_POINTER_ALIGN (REGNO (base))
< outer_size * BITS_PER_UNIT)) #ifdef WORD_REGISTER_OPERATIONS
return x; if (GET_MODE_SIZE (outer_mode) < GET_MODE_SIZE (inner_mode)
} && ((GET_MODE_SIZE (outer_mode) - 1) / UNITS_PER_WORD
== (GET_MODE_SIZE (inner_mode) - 1) / UNITS_PER_WORD))
return NULL;
#endif
/* Since we don't attempt to handle paradoxical subregs, we can just
call into simplify_subreg, which will handle all remaining checks
for us. */
orig = make_memloc (SUBREG_REG (x), regno);
offset = SUBREG_BYTE (x);
tem = simplify_subreg (outer_mode, orig, inner_mode, offset);
if (!tem || !MEM_P (tem))
return NULL;
/* Now push all required address reloads, if any. */
reloaded = find_reloads_address (GET_MODE (tem), &tem, reloaded = find_reloads_address (GET_MODE (tem), &tem,
XEXP (tem, 0), &XEXP (tem, 0), XEXP (tem, 0), &XEXP (tem, 0),
opnum, type, ind_levels, insn); opnum, type, ind_levels, insn);
...@@ -6248,25 +6235,21 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, ...@@ -6248,25 +6235,21 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
if (!offset && !rtx_equal_p (tem, orig)) if (!offset && !rtx_equal_p (tem, orig))
push_reg_equiv_alt_mem (regno, tem); push_reg_equiv_alt_mem (regno, tem);
/* For some processors an address may be valid in the /* For some processors an address may be valid in the original mode but
original mode but not in a smaller mode. For not in a smaller mode. For example, ARM accepts a scaled index register
example, ARM accepts a scaled index register in in SImode but not in HImode. Note that this is only a problem if the
SImode but not in HImode. Note that this is only address in reg_equiv_mem is already invalid in the new mode; other
a problem if the address in reg_equiv_mem is already cases would be fixed by find_reloads_address as usual.
invalid in the new mode; other cases would be fixed
by find_reloads_address as usual. ??? We attempt to handle such cases here by doing an additional reload
of the full address after the usual processing by find_reloads_address.
??? We attempt to handle such cases here by doing an Note that this may not work in the general case, but it seems to cover
additional reload of the full address after the the cases where this situation currently occurs. A more general fix
usual processing by find_reloads_address. Note that might be to reload the *value* instead of the address, but this would
this may not work in the general case, but it seems not be expected by the callers of this routine as-is.
to cover the cases where this situation currently
occurs. A more general fix might be to reload the If find_reloads_address already completed replaced the address, there
*value* instead of the address, but this would not is nothing further to do. */
be expected by the callers of this routine as-is.
If find_reloads_address already completed replaced
the address, there is nothing further to do. */
if (reloaded == 0 if (reloaded == 0
&& reg_equiv_mem (regno) != 0 && reg_equiv_mem (regno) != 0
&& !strict_memory_address_addr_space_p && !strict_memory_address_addr_space_p
...@@ -6274,31 +6257,25 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum, ...@@ -6274,31 +6257,25 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
MEM_ADDR_SPACE (reg_equiv_mem (regno)))) MEM_ADDR_SPACE (reg_equiv_mem (regno))))
{ {
push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0, push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
base_reg_class (GET_MODE (tem), base_reg_class (GET_MODE (tem), MEM_ADDR_SPACE (tem),
MEM_ADDR_SPACE (tem),
MEM, SCRATCH), MEM, SCRATCH),
GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0, opnum, type);
opnum, type);
reloaded = 1; reloaded = 1;
} }
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so /* If this is not a toplevel operand, find_reloads doesn't see this
that delete_output_reload can see it. */ substitution. We have to emit a USE of the pseudo so that
delete_output_reload can see it. */
if (replace_reloads && recog_data.operand[opnum] != x) if (replace_reloads && recog_data.operand[opnum] != x)
/* We mark the USE with QImode so that we recognize it /* We mark the USE with QImode so that we recognize it as one that
as one that can be safely deleted at the end of can be safely deleted at the end of reload. */
reload. */ PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn),
PUT_MODE (emit_insn_before (gen_rtx_USE (VOIDmode, QImode);
SUBREG_REG (x)),
insn), QImode);
x = tem;
}
}
}
if (address_reloaded) if (address_reloaded)
*address_reloaded = reloaded; *address_reloaded = reloaded;
return x; return tem;
} }
/* Substitute into the current INSN the registers into which we have reloaded /* Substitute into the current INSN the registers into which we have reloaded
......
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