re PR target/28181 (ICE in reload_cse_simplify_operands, at postreload.c:393 on m68k)
gcc/ PR target/28181 * config/m68k/m68k-protos.h (m68k_secondary_reload_class): Declare. (m68k_preferred_reload_class): Likewise. * config/m68k/m68k.h (HARD_REGNO_MODE_OK): Remove duplicated comment. (SECONDARY_RELOAD_CLASS): Define. (PREFERRED_RELOAD_CLASS): Use m68k_preferred_reload_class. (LIMIT_RELOAD_CLASS): Delete. * config/m68k/m68k.c (m68k_regno_mode_ok): Don't prevent address registers from storing bytes. (m68k_secondary_reload_class): New function. (m68k_preferred_reload_class): Likewise. gcc/testsuite/ * gcc.c-torture/compile/m68k-byte-addr.c: New test. From-SVN: r122609
This commit is contained in:
parent
4f44ecc07f
commit
ffa2596e3a
|
@ -1,3 +1,17 @@
|
|||
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
PR target/28181
|
||||
* config/m68k/m68k-protos.h (m68k_secondary_reload_class): Declare.
|
||||
(m68k_preferred_reload_class): Likewise.
|
||||
* config/m68k/m68k.h (HARD_REGNO_MODE_OK): Remove duplicated comment.
|
||||
(SECONDARY_RELOAD_CLASS): Define.
|
||||
(PREFERRED_RELOAD_CLASS): Use m68k_preferred_reload_class.
|
||||
(LIMIT_RELOAD_CLASS): Delete.
|
||||
* config/m68k/m68k.c (m68k_regno_mode_ok): Don't prevent address
|
||||
registers from storing bytes.
|
||||
(m68k_secondary_reload_class): New function.
|
||||
(m68k_preferred_reload_class): Likewise.
|
||||
|
||||
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* config/m68k/m68k.c (m68k_save_reg): Remove special case for
|
||||
|
|
|
@ -69,6 +69,9 @@ extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool);
|
|||
#endif /* RTX_CODE */
|
||||
|
||||
extern bool m68k_regno_mode_ok (int, enum machine_mode);
|
||||
extern enum reg_class m68k_secondary_reload_class (enum reg_class,
|
||||
enum machine_mode, rtx);
|
||||
extern enum reg_class m68k_preferred_reload_class (rtx, enum reg_class);
|
||||
extern int flags_in_68881 (void);
|
||||
extern void m68k_expand_prologue (void);
|
||||
extern bool m68k_use_return_insn (void);
|
||||
|
|
|
@ -4153,9 +4153,10 @@ m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Value is true if hard register REGNO can hold a value of machine-mode MODE.
|
||||
On the 68000, the cpu registers can hold any mode except bytes in address
|
||||
registers, but the 68881 registers can hold only SFmode or DFmode. */
|
||||
/* Value is true if hard register REGNO can hold a value of machine-mode
|
||||
MODE. On the 68000, we let the cpu registers can hold any mode, but
|
||||
restrict the 68881 registers to floating-point modes. */
|
||||
|
||||
bool
|
||||
m68k_regno_mode_ok (int regno, enum machine_mode mode)
|
||||
{
|
||||
|
@ -4167,10 +4168,6 @@ m68k_regno_mode_ok (int regno, enum machine_mode mode)
|
|||
}
|
||||
else if (ADDRESS_REGNO_P (regno))
|
||||
{
|
||||
/* Address Registers, can't hold bytes, can hold aggregate if
|
||||
fits in. */
|
||||
if (GET_MODE_SIZE (mode) == 1)
|
||||
return false;
|
||||
if (regno + GET_MODE_SIZE (mode) / 4 <= 16)
|
||||
return true;
|
||||
}
|
||||
|
@ -4186,6 +4183,66 @@ m68k_regno_mode_ok (int regno, enum machine_mode mode)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Implement SECONDARY_RELOAD_CLASS. */
|
||||
|
||||
enum reg_class
|
||||
m68k_secondary_reload_class (enum reg_class rclass,
|
||||
enum machine_mode mode, rtx x)
|
||||
{
|
||||
int regno;
|
||||
|
||||
regno = true_regnum (x);
|
||||
|
||||
/* If one operand of a movqi is an address register, the other
|
||||
operand must be a general register or constant. Other types
|
||||
of operand must be reloaded through a data register. */
|
||||
if (GET_MODE_SIZE (mode) == 1
|
||||
&& reg_classes_intersect_p (rclass, ADDR_REGS)
|
||||
&& !(INT_REGNO_P (regno) || CONSTANT_P (x)))
|
||||
return DATA_REGS;
|
||||
|
||||
/* PC-relative addresses must be loaded into an address register first. */
|
||||
if (TARGET_PCREL
|
||||
&& !reg_class_subset_p (rclass, ADDR_REGS)
|
||||
&& symbolic_operand (x, VOIDmode))
|
||||
return ADDR_REGS;
|
||||
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement PREFERRED_RELOAD_CLASS. */
|
||||
|
||||
enum reg_class
|
||||
m68k_preferred_reload_class (rtx x, enum reg_class rclass)
|
||||
{
|
||||
enum reg_class secondary_class;
|
||||
|
||||
/* If RCLASS might need a secondary reload, try restricting it to
|
||||
a class that doesn't. */
|
||||
secondary_class = m68k_secondary_reload_class (rclass, GET_MODE (x), x);
|
||||
if (secondary_class != NO_REGS
|
||||
&& reg_class_subset_p (secondary_class, rclass))
|
||||
return secondary_class;
|
||||
|
||||
/* Prefer to use moveq for in-range constants. */
|
||||
if (GET_CODE (x) == CONST_INT
|
||||
&& reg_class_subset_p (DATA_REGS, rclass)
|
||||
&& IN_RANGE (INTVAL (x), -0x80, 0x7f))
|
||||
return DATA_REGS;
|
||||
|
||||
/* ??? Do we really need this now? */
|
||||
if (GET_CODE (x) == CONST_DOUBLE
|
||||
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && reg_class_subset_p (FP_REGS, rclass))
|
||||
return FP_REGS;
|
||||
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
return rclass;
|
||||
}
|
||||
|
||||
/* Return floating point values in a 68881 register. This makes 68881 code
|
||||
a little bit faster. It also makes -msoft-float code incompatible with
|
||||
hard-float code, so people have to be careful not to mix the two.
|
||||
|
|
|
@ -401,13 +401,12 @@ Boston, MA 02110-1301, USA. */
|
|||
#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
|
||||
m68k_hard_regno_rename_ok (OLD_REG, NEW_REG)
|
||||
|
||||
/* Value is true if hard register REGNO can hold a value of machine-mode MODE.
|
||||
On the 68000, the cpu registers can hold any mode except bytes in
|
||||
address registers, the 68881 registers can hold only SFmode or DFmode. */
|
||||
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
|
||||
m68k_regno_mode_ok ((REGNO), (MODE))
|
||||
|
||||
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
|
||||
m68k_secondary_reload_class (CLASS, MODE, X)
|
||||
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
(! TARGET_HARD_FLOAT \
|
||||
|| ((GET_MODE_CLASS (MODE1) == MODE_FLOAT \
|
||||
|
@ -544,34 +543,8 @@ extern enum reg_class regno_reg_class[];
|
|||
? const_call_operand (OP, VOIDmode) \
|
||||
: 0)
|
||||
|
||||
/* On the m68k, use a data reg if possible when the
|
||||
value is a constant in the range where moveq could be used
|
||||
and we ensure that QImodes are reloaded into data regs. */
|
||||
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
|
||||
((GET_CODE (X) == CONST_INT \
|
||||
&& (unsigned) (INTVAL (X) + 0x80) < 0x100 \
|
||||
&& (CLASS) != ADDR_REGS) \
|
||||
? DATA_REGS \
|
||||
: (GET_MODE (X) == QImode && (CLASS) != ADDR_REGS) \
|
||||
? DATA_REGS \
|
||||
: (GET_CODE (X) == CONST_DOUBLE \
|
||||
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
|
||||
? (TARGET_HARD_FLOAT && (CLASS == FP_REGS || CLASS == DATA_OR_FP_REGS) \
|
||||
? FP_REGS : NO_REGS) \
|
||||
: (TARGET_PCREL \
|
||||
&& (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST \
|
||||
|| GET_CODE (X) == LABEL_REF)) \
|
||||
? ADDR_REGS \
|
||||
: (CLASS))
|
||||
|
||||
/* Force QImode output reloads from subregs to be allocated to data regs,
|
||||
since QImode stores from address regs are not supported. We make the
|
||||
assumption that if the class is not ADDR_REGS, then it must be a superset
|
||||
of DATA_REGS. */
|
||||
#define LIMIT_RELOAD_CLASS(MODE, CLASS) \
|
||||
(((MODE) == QImode && (CLASS) != ADDR_REGS) \
|
||||
? DATA_REGS \
|
||||
: (CLASS))
|
||||
m68k_preferred_reload_class (X, CLASS)
|
||||
|
||||
/* On the m68k, this is the size of MODE in words,
|
||||
except in the FP regs, where a single reg is always enough. */
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* gcc.c-torture/compile/m68k-byte-addr.c: New test.
|
||||
|
||||
2007-03-05 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
|
||||
|
||||
* gcc.dg/torture/builtin-convert-4.c: New test.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* This testcase triggered an attempt to reload a byte value into an
|
||||
address register. */
|
||||
extern volatile unsigned char x[];
|
||||
|
||||
#define DECLARE(I) orig##I, inc##I
|
||||
#define READ(I) orig##I = x[I]
|
||||
#define INC(I) inc##I = orig##I + 1
|
||||
#define WRITE1(I) x[I] = orig##I
|
||||
#define WRITE2(I) x[I] = inc##I
|
||||
|
||||
#define REPEAT(X) X(0), X(1), X(2), X(3), X(4), X(5), X(6), X(7), X(8)
|
||||
|
||||
void foo (void)
|
||||
{
|
||||
unsigned char REPEAT (DECLARE);
|
||||
REPEAT (READ);
|
||||
REPEAT (INC);
|
||||
REPEAT (WRITE1);
|
||||
REPEAT (WRITE2);
|
||||
}
|
Loading…
Reference in New Issue