fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
- int val;
+ int val, j;
switch (fmt[i])
{
case 'w':
case '0':
break;
+ case 'E':
+ if (XVECLEN (x, i) != XVECLEN (y, i))
+ return 0;
+ for (j = XVECLEN (x, i) - 1; j >= 0; --j)
+ {
+ val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j));
+ if (val == 0)
+ return 0;
+ if (val == 2)
+ success_2 = 1;
+ }
+ break;
+
/* It is believed that rtx's at this level will never
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
substed_operand[i] = recog_operand[i]
= reg_equiv_mem[regno];
#endif
- if (reg_equiv_address[regno] != 0)
+ if (reg_equiv_address[regno] != 0
+ && (set == 0 || &SET_DEST (set) != recog_operand_loc[i]))
{
/* If reg_equiv_address is not a constant address, copy it,
since it may be shared. */
&& this_alternative_matches[i] < 0)
bad = 1;
+#if 0
/* If this is a pseudo-register that is set in the previous
insns, there's a good chance that it will already be in a
spill register and we can use that spill register. So
- make this case cheaper. */
+ make this case cheaper.
+
+ Disabled for egcs. egcs has better inheritance code and
+ this change causes problems with the improved reload
+ inheritance code. */
if (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& REGNO (operand) == last_output_reload_regno)
reject--;
+#endif
/* If this is a constant that is reloaded into the desired
class by copying it to memory first, count that as another
actually fail are extremely rare, so it turns out to be better to fix
the problem here by not generating cases that choose_reload_regs will
fail for. */
-
+ /* There is a similar problem with RELOAD_FOR_INPUT_ADDRESS /
+ RELOAD_FOR_OUTPUT_ADDRESS when there is more than one of a kind for
+ a single operand.
+ We can reduce the register pressure by exploiting that a
+ RELOAD_FOR_X_ADDR_ADDR that precedes all RELOAD_FOR_X_ADDRESS reloads
+ does not conflict with any of them. */
{
- int op_addr_reloads = 0;
- for (i = 0; i < n_reloads; i++)
- if (reload_when_needed[i] == RELOAD_FOR_OPERAND_ADDRESS)
- op_addr_reloads++;
+ int first_op_addr_num = -2;
+ int first_inpaddr_num[MAX_RECOG_OPERANDS];
+ int first_outpaddr_num[MAX_RECOG_OPERANDS];
+ int need_change= 0;
+ /* We use last_op_addr_reload and the contents of the above arrays
+ first as flags - -2 means no instance encountered, -1 means exactly
+ one instance encountered.
+ If more than one instance has been encountered, we store the reload
+ number of the first reload of the kind in question; reload numbers
+ are known to be non-negative. */
+ for (i = 0; i < noperands; i++)
+ first_inpaddr_num[i] = first_outpaddr_num[i] = -2;
+ for (i = n_reloads - 1; i >= 0; i--)
+ {
+ switch (reload_when_needed[i])
+ {
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ if (! ++first_op_addr_num)
+ {
+ first_op_addr_num= i;
+ need_change = 1;
+ }
+ break;
+ case RELOAD_FOR_INPUT_ADDRESS:
+ if (! ++first_inpaddr_num[reload_opnum[i]])
+ {
+ first_inpaddr_num[reload_opnum[i]] = i;
+ need_change = 1;
+ }
+ break;
+ case RELOAD_FOR_OUTPUT_ADDRESS:
+ if (! ++first_outpaddr_num[reload_opnum[i]])
+ {
+ first_outpaddr_num[reload_opnum[i]] = i;
+ need_change = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
- if (op_addr_reloads > 1)
- for (i = 0; i < n_reloads; i++)
- if (reload_when_needed[i] == RELOAD_FOR_OPADDR_ADDR)
- reload_when_needed[i] = RELOAD_FOR_OPERAND_ADDRESS;
+ if (need_change)
+ {
+ for (i = 0; i < n_reloads; i++)
+ {
+ int first_num, type;
+
+ switch (reload_when_needed[i])
+ {
+ case RELOAD_FOR_OPADDR_ADDR:
+ first_num = first_op_addr_num;
+ type = RELOAD_FOR_OPERAND_ADDRESS;
+ break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ first_num = first_inpaddr_num[reload_opnum[i]];
+ type = RELOAD_FOR_INPUT_ADDRESS;
+ break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ first_num = first_outpaddr_num[reload_opnum[i]];
+ type = RELOAD_FOR_OUTPUT_ADDRESS;
+ break;
+ default:
+ continue;
+ }
+ if (i > first_num)
+ reload_when_needed[i] = type;
+ }
+ }
}
/* See if we have any reloads that are now allowed to be merged
{
int regno, endregno;
- if (GET_CODE (x) == SUBREG)
+ /* Overly conservative. */
+ if (GET_CODE (x) == STRICT_LOW_PART)
+ x = XEXP (x, 0);
+
+ /* If either argument is a constant, then modifying X can not affect IN. */
+ if (CONSTANT_P (x) || CONSTANT_P (in))
+ return 0;
+ else if (GET_CODE (x) == SUBREG)
{
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
abort ();
}
}
- else if (CONSTANT_P (x))
- return 0;
else if (GET_CODE (x) == MEM)
return refers_to_mem_for_reload_p (in);
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
&& (valueno = true_regnum (valtry = SET_SRC (pat))) >= 0)
||
(goal_const && rtx_equal_p (SET_SRC (pat), goal)
+ /* When looking for stack pointer + const,
+ make sure we don't use a stack adjust. */
+ && !reg_overlap_mentioned_for_reload_p (SET_DEST (pat), goal)
&& (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0)
|| (goal_mem
&& (valueno = true_regnum (valtry = SET_DEST (pat))) >= 0
if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
{
+ pat = PATTERN (p);
+
+ /* Watch out for unspec_volatile, and volatile asms. */
+ if (volatile_insn_p (pat))
+ return 0;
+
/* If this insn P stores in either GOAL or VALUE, return 0.
If GOAL is a memory ref and this insn writes memory, return 0.
If GOAL is a memory ref and its address is not constant,
and this insn P changes a register used in GOAL, return 0. */
- pat = PATTERN (p);
if (GET_CODE (pat) == SET || GET_CODE (pat) == CLOBBER)
{
register rtx dest = SET_DEST (pat);
if (goal_mem_addr_varies
&& reg_overlap_mentioned_for_reload_p (dest, goal))
return 0;
+ if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
+ return 0;
}
else if (goal_mem && GET_CODE (dest) == MEM
&& ! push_operand (dest, GET_MODE (dest)))
&& reg_overlap_mentioned_for_reload_p (dest,
goal))
return 0;
+ if (xregno == STACK_POINTER_REGNUM && need_stable_sp)
+ return 0;
}
else if (goal_mem && GET_CODE (dest) == MEM
&& ! push_operand (dest, GET_MODE (dest)))