can not use secondary reloads, you must work around the problem some
other way.
- Allow this when MODE is not reload_mode and assume that the generated
- code handles this case (it does on the Alpha, which is the only place
- this currently happens). */
+ Allow this when a reload_in/out pattern is being used. I.e. assume
+ that the generated code handles this case. */
- if (in_p && class == reload_class && mode == reload_mode)
+ if (in_p && class == reload_class && icode == CODE_FOR_nothing
+ && t_icode == CODE_FOR_nothing)
abort ();
/* If we need a tertiary reload, see if we have one we can reuse or else
void
clear_secondary_mem ()
{
- bzero ((char *) secondary_memlocs, sizeof secondary_memlocs);
+ memset ((char *) secondary_memlocs, 0, sizeof secondary_memlocs);
}
#endif /* SECONDARY_MEMORY_NEEDED */
\f
if (in != 0 && GET_CODE (in) == SUBREG
&& (SUBREG_WORD (in) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
- && class != CLASS_CANNOT_CHANGE_MODE
+ && (class != CLASS_CANNOT_CHANGE_MODE
+ || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
if (out != 0 && GET_CODE (out) == SUBREG
&& (SUBREG_WORD (out) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
- && class != CLASS_CANNOT_CHANGE_MODE
+ && (class != CLASS_CANNOT_CHANGE_MODE
+ || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
+ outmode))
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
char reload_flags[MAX_RELOADS];
int something_changed = 0;
- bzero (reload_flags, sizeof reload_flags);
+ memset (reload_flags, 0, sizeof reload_flags);
for (i = 0, j = 0; i < n_replacements; i++)
{
if (loc_mentioned_in_p (replacements[i].where, in_rtx))
int no_input_reloads = 0, no_output_reloads = 0;
int n_alternatives;
int this_alternative[MAX_RECOG_OPERANDS];
+ char this_alternative_match_win[MAX_RECOG_OPERANDS];
char this_alternative_win[MAX_RECOG_OPERANDS];
char this_alternative_offmemok[MAX_RECOG_OPERANDS];
char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
int operand_reloadnum[MAX_RECOG_OPERANDS];
int goal_alternative_matches[MAX_RECOG_OPERANDS];
int goal_alternative_matched[MAX_RECOG_OPERANDS];
+ char goal_alternative_match_win[MAX_RECOG_OPERANDS];
char goal_alternative_win[MAX_RECOG_OPERANDS];
char goal_alternative_offmemok[MAX_RECOG_OPERANDS];
char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
/* The eliminated forms of any secondary memory locations are per-insn, so
clear them out here. */
- bzero ((char *) secondary_memlocs_elim, sizeof secondary_memlocs_elim);
+ memset ((char *) secondary_memlocs_elim, 0, sizeof secondary_memlocs_elim);
#endif
/* Dispose quickly of (set (reg..) (reg..)) if both have hard regs and it
{
register char *p = constraints[i];
register int win = 0;
+ int did_match = 0;
/* 0 => this operand can be reloaded somehow for this alternative */
int badop = 1;
/* 0 => this operand can be reloaded if the alternative allows regs. */
this_alternative[i] = (int) NO_REGS;
this_alternative_win[i] = 0;
+ this_alternative_match_win[i] = 0;
this_alternative_offmemok[i] = 0;
this_alternative_earlyclobber[i] = 0;
this_alternative_matches[i] = -1;
&& ! this_alternative_win[c])
bad = 1;
- win = this_alternative_win[c];
+ did_match = this_alternative_win[c];
}
else
{
operand also had to match the same thing as this
operand, we don't know how to do that. So reject this
alternative. */
- if (! win || force_reload)
+ if (! did_match || force_reload)
for (j = 0; j < i; j++)
if (this_alternative_matches[j]
== this_alternative_matches[i])
badop = 1;
-
break;
case 'p':
this_alternative_earlyclobber[i] = earlyclobber;
if (win && ! force_reload)
this_alternative_win[i] = 1;
+ else if (did_match && ! force_reload)
+ this_alternative_match_win[i] = 1;
else
{
int const_to_mem = 0;
Don't do this if the preferred class has only one register
because we might otherwise exhaust the class. */
- if (! win && this_alternative[i] != (int) NO_REGS
+ if (! win && ! did_match
+ && this_alternative[i] != (int) NO_REGS
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& reg_class_size[(int) preferred_class[i]] > 1)
{
for (i = 0; i < noperands; i++)
if (this_alternative_earlyclobber[i]
- && this_alternative_win[i])
+ && (this_alternative_win[i] || this_alternative_match_win[i]))
{
struct decomposition early_data;
{
losers++;
this_alternative_win[j] = 0;
+ this_alternative_match_win[j] = 0;
}
else
break;
{
losers++;
this_alternative_win[i] = 0;
+ this_alternative_match_win[j] = 0;
for (j = 0; j < noperands; j++)
if (this_alternative_matches[j] == i
- && this_alternative_win[j])
+ && this_alternative_match_win[j])
{
this_alternative_win[j] = 0;
+ this_alternative_match_win[j] = 0;
losers++;
}
}
}
for (i = 0; i < noperands; i++)
{
- goal_alternative_win[i] = 1;
+ goal_alternative_win[i] = this_alternative_win[i];
+ goal_alternative_match_win[i] = this_alternative_match_win[i];
goal_alternative[i] = this_alternative[i];
goal_alternative_offmemok[i] = this_alternative_offmemok[i];
goal_alternative_matches[i] = this_alternative_matches[i];
{
goal_alternative[i] = this_alternative[i];
goal_alternative_win[i] = this_alternative_win[i];
+ goal_alternative_match_win[i] = this_alternative_match_win[i];
goal_alternative_offmemok[i] = this_alternative_offmemok[i];
goal_alternative_matches[i] = this_alternative_matches[i];
goal_alternative_earlyclobber[i]
for (i = 0; i < noperands; i++)
goal_alternative_matched[i] = -1;
-
+
for (i = 0; i < noperands; i++)
if (! goal_alternative_win[i]
&& goal_alternative_matches[i] >= 0)
goal_alternative_matched[goal_alternative_matches[i]] = i;
+ for (i = 0; i < noperands; i++)
+ goal_alternative_win[i] |= goal_alternative_match_win[i];
+
/* If the best alternative is with operands 1 and 2 swapped,
consider them swapped before reporting the reloads. Update the
operand numbers of any reloads already pushed. */
else if (regno < FIRST_PSEUDO_REGISTER
&& REGNO_MODE_OK_FOR_BASE_P (regno, mode)
- && ! regno_clobbered_p (regno, this_insn))
+ && ! regno_clobbered_p (regno, this_insn, mode, 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
if (REG_P (XEXP (op1, 0)))
{
- register int regno = REGNO (XEXP (op1, 0));
+ rtx link;
+ int regno = REGNO (XEXP (op1, 0));
+ int reloadnum;
/* A register that is incremented cannot be constant! */
if (regno >= FIRST_PSEUDO_REGISTER
write back the value after reading it, hence we actually
need two registers. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, type,
+ &XEXP (tem, 0), opnum,
+ RELOAD_OTHER,
ind_levels, insn);
/* Then reload the memory location into a base
register. */
- push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0),
- BASE_REG_CLASS, GET_MODE (x), GET_MODE (x),
- 0, 0, opnum, RELOAD_OTHER);
- break;
+ reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+ &XEXP (op1, 0), BASE_REG_CLASS,
+ GET_MODE (x), GET_MODE (x), 0,
+ 0, opnum, RELOAD_OTHER);
+ goto reg_inc;
}
}
/* We require a base register here... */
if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
{
- push_reload (XEXP (op1, 0), XEXP (x, 0),
- &XEXP (op1, 0), &XEXP (x, 0),
- BASE_REG_CLASS,
- GET_MODE (x), GET_MODE (x), 0, 0,
- opnum, RELOAD_OTHER);
+ reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+ &XEXP (op1, 0), &XEXP (x, 0),
+ BASE_REG_CLASS,
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
}
+
+ /* Update the REG_INC notes. */
+ reg_inc:
+ for (link = REG_NOTES (this_insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_INC
+ && REGNO (XEXP (link, 0)) == regno)
+ push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
}
else
abort ();
&& ((*insn_data[icode].operand[1].predicate)
(equiv, Pmode))))
{
- loc = &XEXP (x, 0);
+ /* We use the original pseudo for loc, so that
+ emit_reload_insns() knows which pseudo this
+ reload refers to and updates the pseudo rtx, not
+ its equivalent memory location, as well as the
+ corresponding entry in reg_last_reload_reg. */
+ loc = &XEXP (x_orig, 0);
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
(context ? INDEX_REG_CLASS : BASE_REG_CLASS),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
-
- /* If we created a new MEM based on reg_equiv_mem[REGNO], then
- LOC above is part of the new MEM, not the MEM in INSN.
-
- We must also replace the address of the MEM in INSN. */
- if (&XEXP (x_orig, 0) != loc)
- push_replacement (&XEXP (x_orig, 0), reloadnum, VOIDmode);
-
}
else
{
in this insn, reload it into some other register to be safe.
The CLOBBER is supposed to make the register unavailable
from before this insn to after it. */
- if (regno_clobbered_p (regno, this_insn))
+ if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
(context ? INDEX_REG_CLASS : BASE_REG_CLASS),
{
rtx tem;
- /* If this is a CONST_INT, it could have been created by a
- plus_constant call in eliminate_regs, which means it may be
- on the reload_obstack. reload_obstack will be freed later, so
- we can't allow such RTL to be put in the constant pool. There
- is code in force_const_mem to check for this case, but it doesn't
- work because we have already popped off the reload_obstack, so
- rtl_obstack == saveable_obstack is true at this point. */
- if (GET_CODE (x) == CONST_INT)
- tem = x = force_const_mem (mode, GEN_INT (INTVAL (x)));
- else
- tem = x = force_const_mem (mode, x);
-
+ tem = x = force_const_mem (mode, x);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
opnum, type, ind_levels, 0);
}
{
rtx tem;
- /* See comment above. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- tem = force_const_mem (GET_MODE (x), GEN_INT (INTVAL (XEXP (x, 1))));
- else
- tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
-
+ tem = force_const_mem (GET_MODE (x), XEXP (x, 1));
x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), tem);
find_reloads_address (mode, &tem, XEXP (tem, 0), &XEXP (tem, 0),
opnum, type, ind_levels, 0);
&& (valtry
= operand_subword (SET_DEST (pat), 1, 0, VOIDmode))
&& (valueno = true_regnum (valtry)) >= 0)))
- if (other >= 0
- ? valueno == other
- : ((unsigned) valueno < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[(int) class],
- valueno)))
- {
- value = valtry;
- where = p;
- break;
- }
+ {
+ if (other >= 0)
+ {
+ if (valueno != other)
+ continue;
+ }
+ else if ((unsigned) valueno >= FIRST_PSEUDO_REGISTER)
+ continue;
+ else
+ {
+ int i;
+
+ for (i = HARD_REGNO_NREGS (valueno, mode) - 1; i >= 0; i--)
+ if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+ valueno + i))
+ break;
+ if (i >= 0)
+ continue;
+ }
+ value = valtry;
+ where = p;
+ break;
+ }
}
}
return 0;
}
\f
-/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
+/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
+ If SETS is nonzero, also consider SETs. */
int
-regno_clobbered_p (regno, insn)
+regno_clobbered_p (regno, insn, mode, sets)
unsigned int regno;
rtx insn;
+ enum machine_mode mode;
+ int sets;
{
- if (GET_CODE (PATTERN (insn)) == CLOBBER
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ int endregno = regno + nregs;
+
+ if ((GET_CODE (PATTERN (insn)) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
&& GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
- return REGNO (XEXP (PATTERN (insn), 0)) == regno;
+ {
+ int test = REGNO (XEXP (PATTERN (insn), 0));
+
+ return test >= regno && test < endregno;
+ }
if (GET_CODE (PATTERN (insn)) == PARALLEL)
{
for (; i >= 0; i--)
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG
- && REGNO (XEXP (elt, 0)) == regno)
- return 1;
+ if ((GET_CODE (elt) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
+ && GET_CODE (XEXP (elt, 0)) == REG)
+ {
+ int test = REGNO (XEXP (elt, 0));
+
+ if (test >= regno && test < endregno)
+ return 1;
+ }
}
}
fprintf (f, ", optional");
if (rld[r].nongroup)
- fprintf (stderr, ", nongroup");
+ fprintf (f, ", nongroup");
if (rld[r].inc != 0)
fprintf (f, ", inc by %d", rld[r].inc);
prefix = "\n\t";
if (rld[r].secondary_in_icode != CODE_FOR_nothing)
{
- fprintf (stderr, "%ssecondary_in_icode = %s", prefix,
+ fprintf (f, "%ssecondary_in_icode = %s", prefix,
insn_data[rld[r].secondary_in_icode].name);
prefix = ", ";
}
if (rld[r].secondary_out_icode != CODE_FOR_nothing)
- fprintf (stderr, "%ssecondary_out_icode = %s", prefix,
+ fprintf (f, "%ssecondary_out_icode = %s", prefix,
insn_data[rld[r].secondary_out_icode].name);
fprintf (f, "\n");