aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68k
diff options
context:
space:
mode:
authorRichard Sandiford <richard@codesourcery.com>2007-03-06 09:01:07 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2007-03-06 09:01:07 +0000
commitffa2596e3aae16e6bc2254c954b52ea504a612b6 (patch)
treee7694879133c0b1bb72192801c9bf1826003b890 /gcc/config/m68k
parent4f44ecc07f40ad8210c703300224b7e6bed86a86 (diff)
downloadgcc-ffa2596e3aae16e6bc2254c954b52ea504a612b6.zip
gcc-ffa2596e3aae16e6bc2254c954b52ea504a612b6.tar.gz
gcc-ffa2596e3aae16e6bc2254c954b52ea504a612b6.tar.bz2
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
Diffstat (limited to 'gcc/config/m68k')
-rw-r--r--gcc/config/m68k/m68k-protos.h3
-rw-r--r--gcc/config/m68k/m68k.c71
-rw-r--r--gcc/config/m68k/m68k.h37
3 files changed, 72 insertions, 39 deletions
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index 185e7bc..b3b78a1 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -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);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index e491beb..b702f85 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -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.
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index c4b1e14..9d7843d 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -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))
+#define PREFERRED_RELOAD_CLASS(X,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. */