/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
: type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS
: RELOAD_OTHER);
- find_reloads_address (mode, (rtx*)0, XEXP (loc, 0), &XEXP (loc, 0),
+ find_reloads_address (mode, (rtx*) 0, XEXP (loc, 0), &XEXP (loc, 0),
opnum, type, 0, 0);
}
default:
break;
- }
+ }
/* If we are reloading a (SUBREG constant ...), really reload just the
inside expression in its own mode. Similarly for (SUBREG (PLUS ...)).
order as the reloads. Thus if the outer reload is also of type
RELOAD_OTHER, we are guaranteed that this inner reload will be
output before the outer reload. */
- push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *)0,
+ push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *) 0,
in_class, VOIDmode, VOIDmode, 0, 0, opnum, type);
dont_remove_subreg = 1;
}
if (earlyclobber_operand_p (rld[output_reload].out))
return;
+ /* If there is a reload for part of the address of this operand, we would
+ need to chnage it to RELOAD_FOR_OTHER_ADDRESS. But that would extend
+ its life to the point where doing this combine would not lower the
+ number of spill registers needed. */
+ for (i = 0; i < n_reloads; i++)
+ if ((rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
+ || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
+ && rld[i].opnum == rld[output_reload].opnum)
+ return;
+
/* Check each input reload; can we combine it? */
for (i = 0; i < n_reloads; i++)
unsigned int regno = REGNO (in) + in_offset;
unsigned int nwords = HARD_REGNO_NREGS (regno, inmode);
- if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*)0)
+ if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*) 0)
&& ! hard_reg_set_here_p (regno, regno + nwords,
PATTERN (this_insn))
&& (! earlyclobber
struct decomposition xdata;
if (ydata.reg_flag)
- return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, (rtx*)0);
+ return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, (rtx*) 0);
if (ydata.safe)
return 1;
;
else if (constraints[i][0] == 'p')
{
- find_reloads_address (VOIDmode, (rtx*)0,
+ find_reloads_address (VOIDmode, (rtx*) 0,
recog_data.operand[i],
recog_data.operand_loc[i],
i, operand_type[i], ind_levels, insn);
case 'p':
/* All necessary reloads for an address_operand
were handled in find_reloads_address. */
- this_alternative[i] = (int) BASE_REG_CLASS;
+ this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
win = 1;
break;
recog_data.operand[commutative] = substed_operand[commutative + 1];
recog_data.operand[commutative + 1] = substed_operand[commutative];
+ /* Swap the duplicates too. */
+ for (i = 0; i < recog_data.n_dups; i++)
+ if (recog_data.dup_num[i] == commutative
+ || recog_data.dup_num[i] == commutative + 1)
+ *recog_data.dup_loc[i]
+ = recog_data.operand[(int) recog_data.dup_num[i]];
tclass = preferred_class[commutative];
preferred_class[commutative] = preferred_class[commutative + 1];
recog_data.operand[commutative] = substed_operand[commutative];
recog_data.operand[commutative + 1]
= substed_operand[commutative + 1];
+ /* Unswap the duplicates too. */
+ for (i = 0; i < recog_data.n_dups; i++)
+ if (recog_data.dup_num[i] == commutative
+ || recog_data.dup_num[i] == commutative + 1)
+ *recog_data.dup_loc[i]
+ = recog_data.operand[(int) recog_data.dup_num[i]];
}
}
{
/* No alternative works with reloads?? */
if (insn_code_number >= 0)
- fatal_insn ("Unable to generate reloads for:", insn);
+ fatal_insn ("unable to generate reloads for:", insn);
error_for_asm (insn, "inconsistent operand constraints in an `asm'");
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
{
operand_reloadnum[i]
= push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
- &XEXP (recog_data.operand[i], 0), (rtx*)0,
- BASE_REG_CLASS,
+ &XEXP (recog_data.operand[i], 0), (rtx*) 0,
+ MODE_BASE_REG_CLASS (VOIDmode),
GET_MODE (XEXP (recog_data.operand[i], 0)),
VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
rld[operand_reloadnum[i]].inc
rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
}
+ /* Special case a simple move with an input reload and a
+ destination of a hard reg, if the hard reg is ok, use it. */
+ for (i = 0; i < n_reloads; i++)
+ if (rld[i].when_needed == RELOAD_FOR_INPUT
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_DEST (PATTERN (insn))) == REG
+ && SET_SRC (PATTERN (insn)) == rld[i].in)
+ {
+ rtx dest = SET_DEST (PATTERN (insn));
+ unsigned int regno = REGNO (dest);
+
+ if (regno < FIRST_PSEUDO_REGISTER
+ && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
+ && HARD_REGNO_MODE_OK (regno, rld[i].mode))
+ rld[i].reg_rtx = dest;
+ }
+
return retval;
}
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
- find_reloads_address (GET_MODE (tem), (rtx*)0, XEXP (tem, 0),
+ find_reloads_address (GET_MODE (tem), (rtx*) 0, XEXP (tem, 0),
&XEXP (tem, 0), opnum, ADDR_TYPE (type),
ind_levels, insn);
}
return 0;
/* If we do not have one of the cases above, we must do the reload. */
- push_reload (ad, NULL_RTX, loc, (rtx*)0, BASE_REG_CLASS,
+ push_reload (ad, NULL_RTX, loc, (rtx*) 0, MODE_BASE_REG_CLASS (mode),
GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
return 1;
}
{
/* Must use TEM here, not AD, since it is the one that will
have any subexpressions reloaded, if needed. */
- push_reload (tem, NULL_RTX, loc, (rtx*)0,
- BASE_REG_CLASS, GET_MODE (tem),
+ push_reload (tem, NULL_RTX, loc, (rtx*) 0,
+ MODE_BASE_REG_CLASS (mode), GET_MODE (tem),
VOIDmode, 0,
0, opnum, type);
return ! removed_and;
/* If the sum of two regs is not necessarily valid,
reload the sum into a base reg.
That will at least work. */
- find_reloads_address_part (ad, loc, BASE_REG_CLASS,
+ find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
Pmode, opnum, type, ind_levels);
}
return ! removed_and;
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), BASE_REG_CLASS,
+ 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);
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), BASE_REG_CLASS,
+ 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);
loc = &XEXP (*loc, 0);
}
- find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode, opnum, type,
- ind_levels);
+ find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+ Pmode, opnum, type, ind_levels);
return ! removed_and;
}
/* Then reload the memory location into a base
register. */
reloadnum = push_reload (tem, tem, &XEXP (x, 0),
- &XEXP (op1, 0), BASE_REG_CLASS,
+ &XEXP (op1, 0),
+ MODE_BASE_REG_CLASS (mode),
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,
+ MODE_BASE_REG_CLASS (mode),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
x = XEXP (x, 0);
reloadnum
= push_reload (x, x, loc, loc,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, RELOAD_OTHER);
}
else
{
reloadnum
- = push_reload (x, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ = push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), GET_MODE (x), 0, 0,
opnum, type);
rld[reloadnum].inc
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
opnum, type, ind_levels, insn);
- reloadnum = push_reload (x, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
rld[reloadnum].inc
= find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
- push_reload (*loc, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
if (reg_equiv_constant[regno] != 0)
{
find_reloads_address_part (reg_equiv_constant[regno], loc,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), opnum, type, ind_levels);
return 1;
}
that feeds this insn. */
if (reg_equiv_mem[regno] != 0)
{
- push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
|| !(context ? REGNO_OK_FOR_INDEX_P (regno)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
{
- push_reload (x, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
from before this insn to after it. */
if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
- push_reload (x, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
{
- push_reload (x, NULL_RTX, loc, (rtx*)0,
- (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+ push_reload (x, NULL_RTX, loc, (rtx*) 0,
+ (context ? INDEX_REG_CLASS :
+ MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
else
{
enum reg_class class = (context ? INDEX_REG_CLASS
- : BASE_REG_CLASS);
+ : MODE_BASE_REG_CLASS (mode));
if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
x = find_reloads_subreg_address (x, 0, opnum, type,
ind_levels, insn);
- push_reload (x, NULL_RTX, loc, (rtx*)0, class,
+ push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
opnum, type, ind_levels, 0);
}
- push_reload (x, NULL_RTX, loc, (rtx*)0, class,
+ push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
mode, VOIDmode, 0, 0, opnum, type);
}
\f
if (reg_equiv_memory_loc[r])
return refers_to_regno_for_reload_p (regno, endregno,
reg_equiv_memory_loc[r],
- (rtx*)0);
+ (rtx*) 0);
if (reg_equiv_constant[r])
return 0;
int regno, endregno;
/* Overly conservative. */
- if (GET_CODE (x) == STRICT_LOW_PART)
+ if (GET_CODE (x) == STRICT_LOW_PART
+ || GET_RTX_CLASS (GET_CODE (x)) == 'a')
x = XEXP (x, 0);
/* If either argument is a constant, then modifying X can not affect IN. */
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|| GET_CODE (x) == CC0)
return reg_mentioned_p (x, in);
+ else if (GET_CODE (x) == PLUS)
+ return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
+ || reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
else
abort ();
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
- return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*)0);
+ return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
}
/* Return nonzero if anything in X contains a MEM. Look also for pseudo
&& refers_to_regno_for_reload_p (valueno,
(valueno
+ HARD_REGNO_NREGS (valueno, mode)),
- goal, (rtx*)0))
+ goal, (rtx*) 0))
return 0;
/* Reject registers that overlap GOAL. */