Commit eef302d2 by Richard Sandiford Committed by Richard Sandiford

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
parent 9b3f31f2
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> 2008-08-28 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/30949 PR c/30949
......
...@@ -2999,12 +2999,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, ...@@ -2999,12 +2999,11 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
if (REG_P (SUBREG_REG (operand)) if (REG_P (SUBREG_REG (operand))
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER) && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{ {
if (!subreg_offset_representable_p if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
(REGNO (SUBREG_REG (operand)), GET_MODE (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)), SUBREG_BYTE (operand),
SUBREG_BYTE (operand), GET_MODE (operand)) < 0)
GET_MODE (operand))) force_reload = 1;
force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)), offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)), GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand), SUBREG_BYTE (operand),
......
...@@ -1084,6 +1084,8 @@ extern unsigned int subreg_regno_offset (unsigned int, enum machine_mode, ...@@ -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, extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
unsigned int, enum machine_mode); unsigned int, enum machine_mode);
extern unsigned int subreg_regno (const_rtx); 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 (const_rtx);
extern unsigned int subreg_nregs_with_regno (unsigned int, 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); extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, enum machine_mode);
......
...@@ -3244,6 +3244,64 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode, ...@@ -3244,6 +3244,64 @@ subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
return info.representable_p; 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. */ /* Return the final regno that a subreg expression refers to. */
unsigned int unsigned int
subreg_regno (const_rtx x) subreg_regno (const_rtx x)
......
...@@ -5069,35 +5069,13 @@ simplify_subreg (enum machine_mode outermode, rtx op, ...@@ -5069,35 +5069,13 @@ simplify_subreg (enum machine_mode outermode, rtx op,
suppress this simplification. If the hard register is the stack, suppress this simplification. If the hard register is the stack,
frame, or argument pointer, leave this as a SUBREG. */ frame, or argument pointer, leave this as a SUBREG. */
if (REG_P (op) if (REG_P (op) && HARD_REGISTER_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))
{ {
unsigned int regno = REGNO (op); unsigned int regno, final_regno;
unsigned int final_regno
= regno + subreg_regno_offset (regno, innermode, byte, outermode); regno = REGNO (op);
final_regno = simplify_subreg_regno (regno, innermode, byte, outermode);
/* ??? We do allow it if the current REG is not valid for if (HARD_REGISTER_NUM_P (final_regno))
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))
{ {
rtx x; rtx x;
int final_offset = byte; int final_offset = byte;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment