a register. */
enum reg_class preferred_class[MAX_RECOG_OPERANDS];
char pref_or_nothing[MAX_RECOG_OPERANDS];
- /* Nonzero for a MEM operand whose entire address needs a reload. */
+ /* Nonzero for a MEM operand whose entire address needs a reload.
+ May be -1 to indicate the entire address may or may not need a reload. */
int address_reloaded[MAX_RECOG_OPERANDS];
- /* Nonzero for an address operand that needs to be completely reloaded. */
+ /* Nonzero for an address operand that needs to be completely reloaded.
+ May be -1 to indicate the entire operand may or may not need a reload. */
int address_operand_reloaded[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use for operand. */
enum reload_type operand_type[MAX_RECOG_OPERANDS];
{
/* Operands don't match. */
rtx value;
+ int loc1, loc2;
/* Retroactively mark the operand we had to match
as a loser, if it wasn't already. */
if (this_alternative_win[m])
if (this_alternative[m] == (int) NO_REGS)
bad = 1;
/* But count the pair only once in the total badness of
- this alternative, if the pair can be a dummy reload. */
+ this alternative, if the pair can be a dummy reload.
+ The pointers in operand_loc are not swapped; swap
+ them by hand if necessary. */
+ if (swapped && i == commutative)
+ loc1 = commutative + 1;
+ else if (swapped && i == commutative + 1)
+ loc1 = commutative;
+ else
+ loc1 = i;
+ if (swapped && m == commutative)
+ loc2 = commutative + 1;
+ else if (swapped && m == commutative + 1)
+ loc2 = commutative;
+ else
+ loc2 = m;
value
= find_dummy_reload (recog_data.operand[i],
recog_data.operand[m],
- recog_data.operand_loc[i],
- recog_data.operand_loc[m],
+ recog_data.operand_loc[loc1],
+ recog_data.operand_loc[loc2],
operand_mode[i], operand_mode[m],
this_alternative[m], -1,
this_alternative_earlyclobber[m]);
: offsettable_nonstrict_memref_p (operand))
/* A reloaded address is offsettable because it is now
just a simple register indirect. */
- || address_reloaded[i]))
+ || address_reloaded[i] == 1))
|| (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
/* If the address was already reloaded,
we win as well. */
else if (MEM_P (operand)
- && address_reloaded[i])
+ && address_reloaded[i] == 1)
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
}
else if (goal_alternative_matched[i] < 0
&& goal_alternative_matches[i] < 0
- && !address_operand_reloaded[i]
+ && address_operand_reloaded[i] != 1
&& optimize)
{
/* For each non-matching operand that's a MEM or a pseudo-register
to determine if we may generate output reloads, and where to put USEs
for pseudos that we have to replace with stack slots.
- Value is nonzero if this address is reloaded or replaced as a whole.
- This is interesting to the caller if the address is an autoincrement.
+ Value is one if this address is reloaded or replaced as a whole; it is
+ zero if the top level of this address was not reloaded or replaced, and
+ it is -1 if it may or may not have been reloaded or replaced.
Note that there is no verification that the address will be valid after
this routine does its work. Instead, we rely on the fact that the address
{
int regno;
int removed_and = 0;
+ int op_index;
rtx tem;
/* If the address is a register, see if it is a legitimate address and
*memrefloc = copy_rtx (*memrefloc);
XEXP (*memrefloc, 0) = ad;
move_replacements (&ad, &XEXP (*memrefloc, 0));
- return 1;
+ return -1;
}
while (0);
#endif
Handle all base registers here, not just fp/ap/sp, because on some
targets (namely SPARC) we can also get invalid addresses from preventive
- subreg big-endian corrections made by find_reloads_toplev.
+ subreg big-endian corrections made by find_reloads_toplev. We
+ can also get expressions involving LO_SUM (rather than PLUS) from
+ find_reloads_subreg_address.
If we decide to do something, it must be that `double_reg_address_ok'
is true. We generate a reload of the base register + constant and
This is safe because we know the address isn't shared.
We check for the base register as both the first and second operand of
- the innermost PLUS. */
-
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && REG_P (XEXP (XEXP (ad, 0), 0))
- && REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
- || XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
-#endif
- || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
+ the innermost PLUS and/or LO_SUM. */
+
+ for (op_index = 0; op_index < 2; ++op_index)
{
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- plus_constant (XEXP (XEXP (ad, 0), 0),
- INTVAL (XEXP (ad, 1))),
- XEXP (XEXP (ad, 0), 1));
- find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
- type, 0, insn);
+ rtx operand;
- return 0;
- }
+ if (!(GET_CODE (ad) == PLUS
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && (GET_CODE (XEXP (ad, 0)) == PLUS
+ || GET_CODE (XEXP (ad, 0)) == LO_SUM)))
+ continue;
- else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && GET_CODE (XEXP (ad, 0)) == PLUS
- && REG_P (XEXP (XEXP (ad, 0), 1))
- && REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
- && (REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
- || XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
+ operand = XEXP (XEXP (ad, 0), op_index);
+ if (!REG_P (operand) || REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+ continue;
+
+ if ((REG_MODE_OK_FOR_BASE_P (operand, mode)
+ || operand == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
+ || operand == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
+ || operand == arg_pointer_rtx
#endif
- || XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
- && ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
- {
- *loc = ad = gen_rtx_PLUS (GET_MODE (ad),
- XEXP (XEXP (ad, 0), 0),
- plus_constant (XEXP (XEXP (ad, 0), 1),
- INTVAL (XEXP (ad, 1))));
- find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
- MODE_BASE_REG_CLASS (mode),
- GET_MODE (ad), opnum, type, ind_levels);
- find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
- type, 0, insn);
+ || operand == stack_pointer_rtx)
+ && ! maybe_memory_address_p (mode, ad,
+ &XEXP (XEXP (ad, 0), op_index)))
+ {
+ rtx offset_reg;
+ rtx addend;
+
+ offset_reg = plus_constant (operand, INTVAL (XEXP (ad, 1)));
+ addend = XEXP (XEXP (ad, 0), 1 - op_index);
+
+ /* Form the adjusted address. */
+ if (GET_CODE (XEXP (ad, 0)) == PLUS)
+ ad = gen_rtx_PLUS (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
+ op_index == 0 ? addend : offset_reg);
+ else
+ ad = gen_rtx_LO_SUM (GET_MODE (ad),
+ op_index == 0 ? offset_reg : addend,
+ op_index == 0 ? addend : offset_reg);
+ *loc = ad;
+
+ find_reloads_address_part (XEXP (ad, op_index),
+ &XEXP (ad, op_index),
+ MODE_BASE_REG_CLASS (mode),
+ GET_MODE (ad), opnum, type, ind_levels);
+ find_reloads_address_1 (mode,
+ XEXP (ad, 1 - op_index), 1,
+ &XEXP (ad, 1 - op_index), opnum,
+ type, 0, insn);
- return 0;
+ return 0;
+ }
}
/* See if address becomes valid when an eliminable register