/* Search an insn for pseudo regs that must be in hard regs and are not.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
sri.icode = CODE_FOR_nothing;
sri.prev_sri = prev_sri;
rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
- icode = sri.icode;
+ icode = (enum insn_code) sri.icode;
/* If we don't need any secondary registers, done. */
if (rclass == NO_REGS && icode == CODE_FOR_nothing)
sri.icode = CODE_FOR_nothing;
sri.prev_sri = NULL;
rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
- icode = sri.icode;
+ icode = (enum insn_code) sri.icode;
/* If there are no secondary reloads at all, we return NO_REGS.
If an intermediate register is needed, we return its class. */
if (bad || !good)
continue;
- cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+ cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class);
if ((reg_class_size[rclass] > best_size
&& (best_cost < 0 || best_cost >= cost))
|| best_cost > cost)
{
- best_class = rclass;
+ best_class = (enum reg_class) rclass;
best_size = reg_class_size[rclass];
- best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+ best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass,
+ dest_class);
}
}
else
remove_address_replacements (rld[i].in);
}
- rld[i].in = in;
- rld[i].in_reg = in_reg;
+ /* When emitting reloads we don't necessarily look at the in-
+ and outmode, but also directly at the operands (in and out).
+ So we can't simply overwrite them with whatever we have found
+ for this (to-be-merged) reload, we have to "merge" that too.
+ Reusing another reload already verified that we deal with the
+ same operands, just possibly in different modes. So we
+ overwrite the operands only when the new mode is larger.
+ See also PR33613. */
+ if (!rld[i].in
+ || GET_MODE_SIZE (GET_MODE (in))
+ > GET_MODE_SIZE (GET_MODE (rld[i].in)))
+ rld[i].in = in;
+ if (!rld[i].in_reg
+ || (in_reg
+ && GET_MODE_SIZE (GET_MODE (in_reg))
+ > GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
+ rld[i].in_reg = in_reg;
}
if (out != 0)
{
- rld[i].out = out;
- rld[i].out_reg = outloc ? *outloc : 0;
+ if (!rld[i].out
+ || (out
+ && GET_MODE_SIZE (GET_MODE (out))
+ > GET_MODE_SIZE (GET_MODE (rld[i].out))))
+ rld[i].out = out;
+ if (outloc
+ && (!rld[i].out_reg
+ || GET_MODE_SIZE (GET_MODE (*outloc))
+ > GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
+ rld[i].out_reg = *outloc;
}
if (reg_class_subset_p (rclass, rld[i].rclass))
rld[i].rclass = rclass;
value for the incoming operand (same as outgoing one). */
if (rld[i].reg_rtx == out
&& (REG_P (in) || CONSTANT_P (in))
- && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
+ && 0 != find_equiv_reg (in, this_insn, NO_REGS, REGNO (out),
static_reload_reg_p, i, inmode))
rld[i].in = out;
}
&& reg_mentioned_p (XEXP (note, 0), in)
/* Check that a former pseudo is valid; see find_dummy_reload. */
&& (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
- || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
- ORIGINAL_REGNO (XEXP (note, 0)))
+ || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+ ORIGINAL_REGNO (XEXP (note, 0)))
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
&& ! refers_to_regno_for_reload_p (regno,
end_hard_regno (rel_mode,
can ignore the conflict). We must never introduce writes
to such hardregs, as they would clobber the other live
pseudo. See PR 20973. */
- || (!bitmap_bit_p (DF_LIVE_OUT (ENTRY_BLOCK_PTR),
+ || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
ORIGINAL_REGNO (in))
/* Similarly, only do this if we can be sure that the death
note is still valid. global can assign some hardreg to
int
strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
{
+#ifdef GO_IF_LEGITIMATE_ADDRESS
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
win:
return 1;
+#else
+ return targetm.legitimate_address_p (mode, addr, 1);
+#endif
}
\f
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
offset = XEXP (offset, 0);
if (GET_CODE (offset) == PLUS)
{
- if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+ if (CONST_INT_P (XEXP (offset, 0)))
{
base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
offset = XEXP (offset, 0);
}
- else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+ else if (CONST_INT_P (XEXP (offset, 1)))
{
base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
offset = XEXP (offset, 1);
offset = const0_rtx;
}
}
- else if (GET_CODE (offset) != CONST_INT)
+ else if (!CONST_INT_P (offset))
{
base = gen_rtx_PLUS (GET_MODE (base), base, offset);
offset = const0_rtx;
if (all_const && GET_CODE (base) == PLUS)
base = gen_rtx_CONST (GET_MODE (base), base);
- gcc_assert (GET_CODE (offset) == CONST_INT);
+ gcc_assert (CONST_INT_P (offset));
val.start = INTVAL (offset);
val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
int no_input_reloads = 0, no_output_reloads = 0;
int n_alternatives;
- int this_alternative[MAX_RECOG_OPERANDS];
+ enum reg_class 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];
if (REG_P (SUBREG_REG (operand))
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
- if (!subreg_offset_representable_p
- (REGNO (SUBREG_REG (operand)),
- GET_MODE (SUBREG_REG (operand)),
- SUBREG_BYTE (operand),
- GET_MODE (operand)))
- force_reload = 1;
+ if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand)) < 0)
+ force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
force_reload = 1;
}
- this_alternative[i] = (int) NO_REGS;
+ this_alternative[i] = NO_REGS;
this_alternative_win[i] = 0;
this_alternative_match_win[i] = 0;
this_alternative_offmemok[i] = 0;
this combination, because we can't reload it. */
if (this_alternative_offmemok[m]
&& MEM_P (recog_data.operand[m])
- && this_alternative[m] == (int) NO_REGS
+ && this_alternative[m] == NO_REGS
&& ! this_alternative_win[m])
bad = 1;
if (this_alternative_win[m])
losers++;
this_alternative_win[m] = 0;
- if (this_alternative[m] == (int) NO_REGS)
+ if (this_alternative[m] == 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.
case 'p':
/* All necessary reloads for an address_operand
were handled in find_reloads_address. */
- this_alternative[i]
- = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+ this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
+ SCRATCH);
win = 1;
badop = 0;
break;
break;
case 's':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
|| (GET_CODE (operand) == CONST_DOUBLE
&& GET_MODE (operand) == VOIDmode))
break;
break;
case 'n':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
|| (GET_CODE (operand) == CONST_DOUBLE
&& GET_MODE (operand) == VOIDmode))
win = 1;
case 'N':
case 'O':
case 'P':
- if (GET_CODE (operand) == CONST_INT
+ if (CONST_INT_P (operand)
&& CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
win = 1;
break;
case 'r':
this_alternative[i]
- = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+ = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
goto reg;
default:
/* If we didn't already win, we can reload
the address into a base register. */
- this_alternative[i]
- = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+ this_alternative[i] = base_reg_class (VOIDmode,
+ ADDRESS,
+ SCRATCH);
badop = 0;
break;
}
}
this_alternative[i]
- = (int) (reg_class_subunion
- [this_alternative[i]]
- [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
+ = (reg_class_subunion
+ [this_alternative[i]]
+ [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
reg:
if (GET_MODE (operand) == BLKmode)
break;
/* If this operand could be handled with a reg,
and some reg is allowed, then this operand can be handled. */
- if (winreg && this_alternative[i] != (int) NO_REGS)
+ if (winreg && this_alternative[i] != NO_REGS)
badop = 0;
/* Record which operands fit this alternative. */
bad = 1;
/* Alternative loses if it has no regs for a reg operand. */
if (REG_P (operand)
- && this_alternative[i] == (int) NO_REGS
+ && this_alternative[i] == NO_REGS
&& this_alternative_matches[i] < 0)
bad = 1;
precisely the same as in the code below that calls
force_const_mem. */
if (CONST_POOL_OK_P (operand)
- && ((PREFERRED_RELOAD_CLASS (operand,
- (enum reg_class) this_alternative[i])
+ && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
== NO_REGS)
|| no_input_reloads)
&& operand_mode[i] != VOIDmode)
{
const_to_mem = 1;
- if (this_alternative[i] != (int) NO_REGS)
+ if (this_alternative[i] != NO_REGS)
losers++;
}
LIMIT_RELOAD_CLASS, but we don't check that
here. */
- if (! CONSTANT_P (operand)
- && (enum reg_class) this_alternative[i] != NO_REGS)
+ if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
{
- if (PREFERRED_RELOAD_CLASS
- (operand, (enum reg_class) this_alternative[i])
+ if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
== NO_REGS)
reject = 600;
#ifdef PREFERRED_OUTPUT_RELOAD_CLASS
if (operand_type[i] == RELOAD_FOR_OUTPUT
- && PREFERRED_OUTPUT_RELOAD_CLASS
- (operand, (enum reg_class) this_alternative[i])
- == NO_REGS)
+ && (PREFERRED_OUTPUT_RELOAD_CLASS (operand,
+ this_alternative[i])
+ == NO_REGS))
reject = 600;
#endif
}
because we might otherwise exhaust the class. */
if (! win && ! did_match
- && this_alternative[i] != (int) NO_REGS
+ && this_alternative[i] != NO_REGS
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& reg_class_size [(int) preferred_class[i]] > 0
&& ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
common case anyway. */
if (reg_class_subset_p (preferred_class[i],
this_alternative[i]))
- this_alternative[i] = (int) preferred_class[i];
+ this_alternative[i] = preferred_class[i];
else
reject += (2 + 2 * pref_or_nothing[i]);
}
/* Any constants that aren't allowed and can't be reloaded
into registers are here changed into memory references. */
for (i = 0; i < noperands; i++)
- if (! goal_alternative_win[i]
- && CONST_POOL_OK_P (recog_data.operand[i])
- && ((PREFERRED_RELOAD_CLASS (recog_data.operand[i],
- (enum reg_class) goal_alternative[i])
- == NO_REGS)
- || no_input_reloads)
- && operand_mode[i] != VOIDmode)
+ if (! goal_alternative_win[i])
{
- int this_address_reloaded;
+ rtx op = recog_data.operand[i];
+ rtx subreg = NULL_RTX;
+ rtx plus = NULL_RTX;
+ enum machine_mode mode = operand_mode[i];
+
+ /* Reloads of SUBREGs of CONSTANT RTXs are handled later in
+ push_reload so we have to let them pass here. */
+ if (GET_CODE (op) == SUBREG)
+ {
+ subreg = op;
+ op = SUBREG_REG (op);
+ mode = GET_MODE (op);
+ }
- this_address_reloaded = 0;
- substed_operand[i] = recog_data.operand[i]
- = find_reloads_toplev (force_const_mem (operand_mode[i],
- recog_data.operand[i]),
- i, address_type[i], ind_levels, 0, insn,
- &this_address_reloaded);
- if (alternative_allows_const_pool_ref (this_address_reloaded == 0
- ? substed_operand[i]
- : NULL,
- recog_data.constraints[i],
- goal_alternative_number))
- goal_alternative_win[i] = 1;
- }
+ if (GET_CODE (op) == PLUS)
+ {
+ plus = op;
+ op = XEXP (op, 1);
+ }
- /* Likewise any invalid constants appearing as operand of a PLUS
- that is to be reloaded. */
- for (i = 0; i < noperands; i++)
- if (! goal_alternative_win[i]
- && GET_CODE (recog_data.operand[i]) == PLUS
- && CONST_POOL_OK_P (XEXP (recog_data.operand[i], 1))
- && (PREFERRED_RELOAD_CLASS (XEXP (recog_data.operand[i], 1),
- (enum reg_class) goal_alternative[i])
- == NO_REGS)
- && operand_mode[i] != VOIDmode)
- {
- rtx tem = force_const_mem (operand_mode[i],
- XEXP (recog_data.operand[i], 1));
- tem = gen_rtx_PLUS (operand_mode[i],
- XEXP (recog_data.operand[i], 0), tem);
+ if (CONST_POOL_OK_P (op)
+ && ((PREFERRED_RELOAD_CLASS (op,
+ (enum reg_class) goal_alternative[i])
+ == NO_REGS)
+ || no_input_reloads)
+ && mode != VOIDmode)
+ {
+ int this_address_reloaded;
+ rtx tem = force_const_mem (mode, op);
- substed_operand[i] = recog_data.operand[i]
- = find_reloads_toplev (tem, i, address_type[i],
- ind_levels, 0, insn, NULL);
+ /* If we stripped a SUBREG or a PLUS above add it back. */
+ if (plus != NULL_RTX)
+ tem = gen_rtx_PLUS (mode, XEXP (plus, 0), tem);
+
+ if (subreg != NULL_RTX)
+ tem = gen_rtx_SUBREG (operand_mode[i], tem, SUBREG_BYTE (subreg));
+
+ this_address_reloaded = 0;
+ substed_operand[i] = recog_data.operand[i]
+ = find_reloads_toplev (tem, i, address_type[i], ind_levels,
+ 0, insn, &this_address_reloaded);
+
+ /* If the alternative accepts constant pool refs directly
+ there will be no reload needed at all. */
+ if (plus == NULL_RTX
+ && subreg == NULL_RTX
+ && alternative_allows_const_pool_ref (this_address_reloaded == 0
+ ? substed_operand[i]
+ : NULL,
+ recog_data.constraints[i],
+ goal_alternative_number))
+ goal_alternative_win[i] = 1;
+ }
}
/* Record the values of the earlyclobber operands for the caller. */
/* If we detected error and replaced asm instruction by USE, forget about the
reloads. */
if (GET_CODE (PATTERN (insn)) == USE
- && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+ && CONST_INT_P (XEXP (PATTERN (insn), 0)))
n_reloads = 0;
/* Perhaps an output reload can be combined with another
is null. */
static bool
-alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+ const char *constraint, int altnum)
{
int c;
/* We must rerun eliminate_regs, in case the elimination
offsets have changed. */
rtx tem
- = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
+ = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX),
+ 0);
/* If TEM might contain a pseudo, we must copy it to avoid
modifying it when we do the substitution for the reload. */
/* But first quickly dispose of a common case. */
if (GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (ad, 1))
&& REG_P (XEXP (ad, 0))
&& reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
return 0;
|| ! (REG_P (XEXP (tem, 0))
|| (GET_CODE (XEXP (tem, 0)) == PLUS
&& REG_P (XEXP (XEXP (tem, 0), 0))
- && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
+ && CONST_INT_P (XEXP (XEXP (tem, 0), 1)))))
{
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
else if (GET_CODE (ad) == PLUS
&& REG_P (XEXP (ad, 0))
&& REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (ad, 1))
&& regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
CONST_INT))
inner_code = GET_CODE (XEXP (ad, 0));
if (!(GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (ad, 1))
&& (inner_code == PLUS || inner_code == LO_SUM)))
continue;
case PLUS:
/* Quickly dispose of a common case. */
if (XEXP (ad, 0) == frame_pointer_rtx
- && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (ad, 1)))
return ad;
break;
if (mode == VOIDmode)
mode = Pmode;
- if (GET_CODE (x) == CONST_INT)
+ if (CONST_INT_P (x))
return plus_constant (y, INTVAL (x));
- else if (GET_CODE (y) == CONST_INT)
+ else if (CONST_INT_P (y))
return plus_constant (x, INTVAL (y));
else if (CONSTANT_P (x))
tem = x, x = y, y = tem;
base = XEXP (tem, 0);
if (GET_CODE (base) == PLUS)
{
- if (GET_CODE (XEXP (base, 1)) == CONST_INT
+ if (CONST_INT_P (XEXP (base, 1))
&& INTVAL (XEXP (base, 1)) % outer_size != 0)
return x;
base = XEXP (base, 0);
/* For some processors an address may be valid in the
original mode but not in a smaller mode. For
example, ARM accepts a scaled index register in
- SImode but not in HImode. Similarly, the address may
- have been valid before the subreg offset was added,
- but not afterwards. find_reloads_address
- assumes that we pass it a valid address, and doesn't
- force a reload. This will probably be fine if
- find_reloads_address finds some reloads. But if it
- doesn't find any, then we may have just converted a
- valid address into an invalid one. Check for that
- here. */
- if (reloaded != 1
- && !strict_memory_address_p (GET_MODE (tem),
- XEXP (tem, 0)))
+ SImode but not in HImode. Note that this is only
+ a problem if the address in reg_equiv_mem is already
+ 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. Note that
+ this may not work in the general case, but it seems
+ to cover the cases where this situation currently
+ occurs. A more general fix might be to reload the
+ *value* instead of the address, but this would not
+ 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
+ && reg_equiv_mem[regno] != 0
+ && !strict_memory_address_p (GET_MODE (x),
+ XEXP (reg_equiv_mem[regno], 0)))
push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
base_reg_class (GET_MODE (tem), MEM, SCRATCH),
GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 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 && GET_CODE (SUBREG_REG (x)) == MEM)
+ else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
return refers_to_mem_for_reload_p (in);
else if (GET_CODE (x) == SUBREG)
{
|| (REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
- && GET_CODE (goal) == CONST_INT
+ && CONST_INT_P (goal)
&& 0 != (goaltry
= operand_subword (XEXP (tem, 0), 0, 0,
VOIDmode))
&& REG_P (SET_DEST (pat))
&& GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
&& SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
- && GET_CODE (goal) == CONST_INT
+ && CONST_INT_P (goal)
&& 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
VOIDmode))
&& rtx_equal_p (goal, goaltry)
&& GET_CODE (XEXP (addr, 1)) == PLUS
&& XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
&& XEXP (addr, 0) == inced
- && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (XEXP (addr, 1), 1)))
{
i = INTVAL (XEXP (XEXP (addr, 1), 1));
return i < 0 ? -i : i;