rtl.h (simplify_subreg_regno): Declare.

gcc/
	* rtl.h (simplify_subreg_regno): Declare.
	* rtlanal.c (simplify_subreg_regno): New function, split out from...
	* simplify-rtx.c (simplify_subreg): ...here.
	* reload.c (find_reloads): Use simplify_subreg_regno instead of
	subreg_offset_representable_p.

From-SVN: r139736
This commit is contained in:
Richard Sandiford 2008-08-28 20:02:54 +00:00 committed by Richard Sandiford
parent 9b3f31f2ed
commit eef302d277
5 changed files with 78 additions and 33 deletions

View File

@ -1,3 +1,11 @@
2008-08-28 Richard Sandiford <rdsandiford@googlemail.com>
* rtl.h (simplify_subreg_regno): Declare.
* rtlanal.c (simplify_subreg_regno): New function, split out from...
* simplify-rtx.c (simplify_subreg): ...here.
* reload.c (find_reloads): Use simplify_subreg_regno instead of
subreg_offset_representable_p.
2008-08-28 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/30949

View File

@ -2999,12 +2999,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
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),

View File

@ -1084,6 +1084,8 @@ extern unsigned int subreg_regno_offset (unsigned int, enum machine_mode,
extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
unsigned int, enum machine_mode);
extern unsigned int subreg_regno (const_rtx);
extern int simplify_subreg_regno (unsigned int, enum machine_mode,
unsigned int, enum machine_mode);
extern unsigned int subreg_nregs (const_rtx);
extern unsigned int subreg_nregs_with_regno (unsigned int, const_rtx);
extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, enum machine_mode);

View File

@ -3244,6 +3244,64 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
return info.representable_p;
}
/* Return the number of a YMODE register to which
(subreg:YMODE (reg:XMODE XREGNO) OFFSET)
can be simplified. Return -1 if the subreg can't be simplified.
XREGNO is a hard register number. */
int
simplify_subreg_regno (unsigned int xregno, enum machine_mode xmode,
unsigned int offset, enum machine_mode ymode)
{
struct subreg_info info;
unsigned int yregno;
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Give the backend a chance to disallow the mode change. */
if (GET_MODE_CLASS (xmode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (xmode) != MODE_COMPLEX_FLOAT
&& REG_CANNOT_CHANGE_MODE_P (xregno, xmode, ymode))
return -1;
#endif
/* We shouldn't simplify stack-related registers. */
if ((!reload_completed || frame_pointer_needed)
&& (xregno == FRAME_POINTER_REGNUM
|| xregno == HARD_FRAME_POINTER_REGNUM))
return -1;
if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& xregno == ARG_POINTER_REGNUM)
return -1;
if (xregno == STACK_POINTER_REGNUM)
return -1;
/* Try to get the register offset. */
subreg_get_info (xregno, xmode, offset, ymode, &info);
if (!info.representable_p)
return -1;
/* Make sure that the offsetted register value is in range. */
yregno = xregno + info.offset;
if (!HARD_REGISTER_NUM_P (yregno))
return -1;
/* See whether (reg:YMODE YREGNO) is valid.
??? We allow invalid registers if (reg:XMODE XREGNO) is also invalid.
This is a kludge to work around how float/complex arguments are passed
on 32-bit SPARC and should be fixed. */
if (!HARD_REGNO_MODE_OK (yregno, ymode)
&& HARD_REGNO_MODE_OK (xregno, xmode))
return -1;
return (int) yregno;
}
/* Return the final regno that a subreg expression refers to. */
unsigned int
subreg_regno (const_rtx x)

View File

@ -5069,35 +5069,13 @@ simplify_subreg (enum machine_mode outermode, rtx op,
suppress this simplification. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */
if (REG_P (op)
&& REGNO (op) < FIRST_PSEUDO_REGISTER
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
#endif
&& ((reload_completed && !frame_pointer_needed)
|| (REGNO (op) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
&& REGNO (op) != HARD_FRAME_POINTER_REGNUM
#endif
))
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& REGNO (op) != ARG_POINTER_REGNUM
#endif
&& REGNO (op) != STACK_POINTER_REGNUM
&& subreg_offset_representable_p (REGNO (op), innermode,
byte, outermode))
if (REG_P (op) && HARD_REGISTER_P (op))
{
unsigned int regno = REGNO (op);
unsigned int final_regno
= regno + subreg_regno_offset (regno, innermode, byte, outermode);
unsigned int regno, final_regno;
/* ??? We do allow it if the current REG is not valid for
its mode. This is a kludge to work around how float/complex
arguments are passed on 32-bit SPARC and should be fixed. */
if (HARD_REGNO_MODE_OK (final_regno, outermode)
|| ! HARD_REGNO_MODE_OK (regno, innermode))
regno = REGNO (op);
final_regno = simplify_subreg_regno (regno, innermode, byte, outermode);
if (HARD_REGISTER_NUM_P (final_regno))
{
rtx x;
int final_offset = byte;