gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2007 09:01:07 +0000 (09:01 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2007 09:01:07 +0000 (09:01 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122609 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/m68k-byte-addr.c [new file with mode: 0644]

index 9707639..69978a3 100644 (file)
@@ -1,5 +1,19 @@
 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
        leaf functions.
        (m68k_expand_prologue): Likewise.
index 185e7bc..b3b78a1 100644 (file)
@@ -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);
index e491beb..b702f85 100644 (file)
@@ -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.
index c4b1e14..9d7843d 100644 (file)
@@ -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.  */
index 7753a04..849ec24 100644 (file)
@@ -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.
diff --git a/gcc/testsuite/gcc.c-torture/compile/m68k-byte-addr.c b/gcc/testsuite/gcc.c-torture/compile/m68k-byte-addr.c
new file mode 100644 (file)
index 0000000..88667a4
--- /dev/null
@@ -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);
+}