mn10300: Cleanup legitimate addresses
authorRichard Henderson <rth@redhat.com>
Wed, 19 Jan 2011 17:14:31 +0000 (09:14 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 19 Jan 2011 17:14:31 +0000 (09:14 -0800)
Allow REG+REG and POST_MODIFY addressing for AM33.  Fix AM33 base and
index register classes.  Remove a bunch of register class combinations
that aren't really useful after this cleanup.

From-SVN: r169006

gcc/ChangeLog
gcc/config/mn10300/mn10300-protos.h
gcc/config/mn10300/mn10300.c
gcc/config/mn10300/mn10300.h

index 06b439e..7ef09cc 100644 (file)
@@ -1,5 +1,33 @@
 2011-01-19  Richard Henderson  <rth@redhat.com>
 
+       * config/mn10300/mn10300.c (mn10300_print_operand_address): Handle
+       POST_MODIFY.
+       (mn10300_secondary_reload): Tidy combination reload classes.
+       (mn10300_legitimate_address_p): Allow post-modify and reg+reg
+       addresses for AM33.  Allow symbolic offsets for reg+imm.
+       (mn10300_regno_in_class_p): New.
+       (mn10300_legitimize_reload_address): New.
+       * config/mn10300/mn10300.h (enum reg_class): Remove
+       DATA_OR_ADDRESS_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
+       SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS.  Add
+       SP_OR_GENERAL_REGS.
+       (REG_CLASS_NAMES): Update to match.
+       (REG_CLASS_CONTENTS): Likewise.
+       (INDEX_REG_CLASS): Use GENERAL_REGS for AM33.
+       (BASE_REG_CLASS): Use SP_OR_GENERAL_REGS for AM33.
+       (REGNO_IN_RANGE_P): Remove.
+       (REGNO_DATA_P): Use mn10300_regno_in_class_p.
+       (REGNO_ADDRESS_P, REGNO_EXTENDED_P): Likewise.
+       (REGNO_STRICT_OK_FOR_BASE_P): Likewise.
+       (REGNO_STRICT_OK_FOR_BIT_BASE_P): Likewise.
+       (REGNO_STRICT_OK_FOR_INDEX_P): Likewise.
+       (REGNO_SP_P, REGNO_AM33_P, REGNO_FP_P): Remove.
+       (REGNO_GENERAL_P): New.
+       (HAVE_POST_MODIFY_DISP): New.
+       (USE_LOAD_POST_INCREMENT, USE_STORE_POST_INCREMENT): New.
+       (LEGITIMIZE_RELOAD_ADDRESS): New.
+       * config/mn10300/mn10300-protos.h: Update.
+
        * config/mn10300/mn10300.c (mn10300_preferred_reload_class): Allow
        DATA_REGS for AM33 stack-pointer destination.
        (mn10300_preferred_output_reload_class): Likewise.
index 37968ff..d0ce1b3 100644 (file)
@@ -26,6 +26,7 @@
 #ifdef RTX_CODE
 extern rtx   mn10300_legitimize_pic_address (rtx, rtx);
 extern int   mn10300_legitimate_pic_operand_p (rtx);
+extern rtx   mn10300_legitimize_reload_address (rtx, Mmode, int, int, int);
 extern bool  mn10300_function_value_regno_p (const unsigned int);
 extern int   mn10300_get_live_callee_saved_regs (void);
 extern bool  mn10300_hard_regno_mode_ok (unsigned int, Mmode);
@@ -40,6 +41,7 @@ extern int   mn10300_store_multiple_operation (rtx, Mmode);
 extern int   mn10300_symbolic_operand (rtx, Mmode);
 #endif /* RTX_CODE */
 
+extern bool  mn10300_regno_in_class_p (unsigned, int, bool);
 extern int   mn10300_can_use_return_insn (void);
 extern void  mn10300_expand_prologue (void);
 extern void  mn10300_expand_epilogue (void);
index 29cf337..197ff85 100644 (file)
@@ -495,26 +495,38 @@ mn10300_print_operand_address (FILE *file, rtx addr)
   switch (GET_CODE (addr))
     {
     case POST_INC:
-      mn10300_print_operand_address (file, XEXP (addr, 0));
+      mn10300_print_operand (file, XEXP (addr, 0), 0);
       fputc ('+', file);
       break;
+
+    case POST_MODIFY:
+      mn10300_print_operand (file, XEXP (addr, 0), 0);
+      fputc ('+', file);
+      fputc (',', file);
+      mn10300_print_operand (file, XEXP (addr, 1), 0);
+      break;
+
     case REG:
       mn10300_print_operand (file, addr, 0);
       break;
     case PLUS:
       {
-       rtx base, index;
-       if (REG_P (XEXP (addr, 0))
-           && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
-         base = XEXP (addr, 0), index = XEXP (addr, 1);
-       else if (REG_P (XEXP (addr, 1))
-           && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
-         base = XEXP (addr, 1), index = XEXP (addr, 0);
-       else
-         gcc_unreachable ();
+       rtx base = XEXP (addr, 0);
+       rtx index = XEXP (addr, 1);
+       
+       if (REG_P (index) && !REG_OK_FOR_INDEX_P (index))
+         {
+           rtx x = base;
+           base = index;
+           index = x;
+
+           gcc_assert (REG_P (index) && REG_OK_FOR_INDEX_P (index));
+         }
+       gcc_assert (REG_OK_FOR_BASE_P (base));
+
        mn10300_print_operand (file, index, 0);
        fputc (',', file);
-       mn10300_print_operand (file, base, 0);;
+       mn10300_print_operand (file, base, 0);
        break;
       }
     case SYMBOL_REF:
@@ -1395,8 +1407,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   if (in_p
       && rclass != SP_REGS
       && rclass != SP_OR_ADDRESS_REGS
-      && rclass != SP_OR_EXTENDED_REGS
-      && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS
+      && rclass != SP_OR_GENERAL_REGS
       && GET_CODE (x) == PLUS
       && (XEXP (x, 0) == stack_pointer_rtx
          || XEXP (x, 1) == stack_pointer_rtx))
@@ -1422,7 +1433,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
        addr = XEXP (x, 0);
 
       if (addr && CONSTANT_ADDRESS_P (addr))
-       return DATA_OR_EXTENDED_REGS;
+       return GENERAL_REGS;
     }
 
   /* Otherwise assume no secondary reloads are needed.  */
@@ -1954,51 +1965,99 @@ mn10300_legitimate_pic_operand_p (rtx x)
 static bool
 mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
 {
-  if (CONSTANT_ADDRESS_P (x)
-      && (! flag_pic || mn10300_legitimate_pic_operand_p (x)))
-    return TRUE;
+  rtx base, index;
+
+  if (CONSTANT_ADDRESS_P (x))
+    return !flag_pic || mn10300_legitimate_pic_operand_p (x);
 
   if (RTX_OK_FOR_BASE_P (x, strict))
-    return TRUE;
+    return true;
 
-  if (TARGET_AM33
-      && GET_CODE (x) == POST_INC
-      && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
-      && (mode == SImode || mode == SFmode || mode == HImode))
-    return TRUE;
+  if (TARGET_AM33 && (mode == SImode || mode == SFmode || mode == HImode))
+    {
+      if (GET_CODE (x) == POST_INC)
+       return RTX_OK_FOR_BASE_P (XEXP (x, 0), strict);
+      if (GET_CODE (x) == POST_MODIFY)
+       return (RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
+               && CONSTANT_ADDRESS_P (XEXP (x, 1)));
+    }
 
-  if (GET_CODE (x) == PLUS)
+  if (GET_CODE (x) != PLUS)
+    return false;
+
+  base = XEXP (x, 0);
+  index = XEXP (x, 1);
+
+  if (!REG_P (base))
+    return false;
+  if (REG_P (index))
     {
-      rtx base = 0, index = 0;
+      /* ??? Without AM33 generalized (Ri,Rn) addressing, reg+reg
+        addressing is hard to satisfy.  */
+      if (!TARGET_AM33)
+       return false;
 
-      if (REG_P (XEXP (x, 0))
-         && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict))
-       {
-         base = XEXP (x, 0);
-         index = XEXP (x, 1);
-       }
+      return (REGNO_GENERAL_P (REGNO (base), strict)
+             && REGNO_GENERAL_P (REGNO (index), strict));
+    }
 
-      if (REG_P (XEXP (x, 1))
-         && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict))
-       {
-         base = XEXP (x, 1);
-         index = XEXP (x, 0);
-       }
+  if (!REGNO_STRICT_OK_FOR_BASE_P (REGNO (base), strict))
+    return false;
 
-      if (base != 0 && index != 0)
-       {
-         if (CONST_INT_P (index))
-           return TRUE;
-         if (GET_CODE (index) == CONST
-             && GET_CODE (XEXP (index, 0)) != PLUS
-             && (! flag_pic
-                 || (mn10300_legitimate_pic_operand_p (index)
-                     && GET_MODE_SIZE (mode) == 4)))
-           return TRUE;
-       }
+  if (CONST_INT_P (index))
+    return IN_RANGE (INTVAL (index), -1 - 0x7fffffff, 0x7fffffff);
+
+  if (CONSTANT_ADDRESS_P (index))
+    return !flag_pic || mn10300_legitimate_pic_operand_p (index);
+
+  return false;
+}
+
+bool
+mn10300_regno_in_class_p (unsigned regno, int rclass, bool strict)
+{
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    {
+      if (!strict)
+       return true;
+      if (!reg_renumber)
+       return false;
+      regno = reg_renumber[regno];
+    }
+  return TEST_HARD_REG_BIT (reg_class_contents[rclass], regno);
+}
+
+rtx
+mn10300_legitimize_reload_address (rtx x,
+                                  enum machine_mode mode ATTRIBUTE_UNUSED,
+                                  int opnum, int type,
+                                  int ind_levels ATTRIBUTE_UNUSED)
+{
+  bool any_change = false;
+
+  /* See above re disabling reg+reg addressing for MN103.  */
+  if (!TARGET_AM33)
+    return NULL_RTX;
+
+  if (GET_CODE (x) != PLUS)
+    return NULL_RTX;
+
+  if (XEXP (x, 0) == stack_pointer_rtx)
+    {
+      push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+                  GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0,
+                  opnum, (enum reload_type) type);
+      any_change = true;
+    }
+  if (XEXP (x, 1) == stack_pointer_rtx)
+    {
+      push_reload (XEXP (x, 1), NULL_RTX, &XEXP (x, 1), NULL,
+                  GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0,
+                  opnum, (enum reload_type) type);
+      any_change = true;
     }
 
-  return FALSE;
+  return any_change ? x : NULL_RTX;
 }
 
 /* Used by LEGITIMATE_CONSTANT_P().  Returns TRUE if X is a valid
index 1ed13b9..587ba17 100644 (file)
@@ -261,12 +261,9 @@ extern enum processor_type mn10300_tune_cpu;
 
 enum reg_class
 {
-  NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS,
-  DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS,
-  EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
-  SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS,
-  FP_REGS, FP_ACC_REGS, CC_REGS,
-  GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
+  NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, SP_OR_ADDRESS_REGS,
+  EXTENDED_REGS, FP_REGS, FP_ACC_REGS, CC_REGS,
+  GENERAL_REGS, SP_OR_GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
 };
 
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
@@ -274,13 +271,9 @@ enum reg_class
 /* Give names of register classes as strings for dump file.  */
 
 #define REG_CLASS_NAMES                                                \
-{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS",                      \
-  "SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS",     \
-  "EXTENDED_REGS",                                             \
-  "DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS",         \
-  "SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS",     \
-  "FP_REGS", "FP_ACC_REGS", "CC_REGS",                         \
-  "GENERAL_REGS", "ALL_REGS", "LIM_REGS"                       \
+{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", "SP_REGS", "SP_OR_ADDRESS_REGS", \
+  "EXTENDED_REGS", "FP_REGS", "FP_ACC_REGS", "CC_REGS",                \
+  "GENERAL_REGS", "SP_OR_GENERAL_REGS", "ALL_REGS", "LIM_REGS" \
 }
 
 /* Define which registers fit in which classes.
@@ -292,17 +285,13 @@ enum reg_class
   { 0x0000000f, 0 },     /* DATA_REGS */                       \
   { 0x000001f0, 0 },     /* ADDRESS_REGS */                    \
   { 0x00000200, 0 },     /* SP_REGS */                         \
-  { 0x000001ff, 0 },     /* DATA_OR_ADDRESS_REGS */            \
   { 0x000003f0, 0 },     /* SP_OR_ADDRESS_REGS */              \
   { 0x0003fc00, 0 },     /* EXTENDED_REGS */                   \
-  { 0x0003fc0f, 0 },     /* DATA_OR_EXTENDED_REGS */           \
-  { 0x0003fdf0, 0 },     /* ADDRESS_OR_EXTENDED_REGS */        \
-  { 0x0003fe00, 0 },     /* SP_OR_EXTENDED_REGS */             \
-  { 0x0003fff0, 0 },     /* SP_OR_ADDRESS_OR_EXTENDED_REGS */  \
   { 0xfffc0000, 0x3ffff },/* FP_REGS */                                \
   { 0x03fc0000, 0 },     /* FP_ACC_REGS */                     \
   { 0x00000000, 0x80000 },/* CC_REGS */                                \
   { 0x0003fdff, 0 },     /* GENERAL_REGS */                    \
+  { 0x0003ffff, 0 },      /* SP_OR_GENERAL_REGS */             \
   { 0xffffffff, 0xfffff } /* ALL_REGS */                       \
 }
 
@@ -334,8 +323,10 @@ enum reg_class
    NO_REGS)
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS
-#define BASE_REG_CLASS  SP_OR_ADDRESS_REGS
+#define INDEX_REG_CLASS \
+  (TARGET_AM33 ? GENERAL_REGS : DATA_REGS)
+#define BASE_REG_CLASS \
+  (TARGET_AM33 ? SP_OR_GENERAL_REGS : SP_OR_ADDRESS_REGS)
 
 /* Macros to check register numbers against specific register classes.  */
 
@@ -364,50 +355,31 @@ enum reg_class
 # define REG_STRICT 1
 #endif
 
-# define REGNO_IN_RANGE_P(regno,min,max,strict) \
-  (IN_RANGE ((regno), (min), (max))            \
-   || ((strict)                                        \
-       ? (reg_renumber                         \
-         && reg_renumber[(regno)] >= (min)     \
-         && reg_renumber[(regno)] <= (max))    \
-       : (regno) >= FIRST_PSEUDO_REGISTER))
-
 #define REGNO_DATA_P(regno, strict) \
-  (REGNO_IN_RANGE_P ((regno), FIRST_DATA_REGNUM, LAST_DATA_REGNUM, \
-                    (strict)))
+  mn10300_regno_in_class_p (regno, DATA_REGS, strict)
 #define REGNO_ADDRESS_P(regno, strict) \
-  (REGNO_IN_RANGE_P ((regno), FIRST_ADDRESS_REGNUM, LAST_ADDRESS_REGNUM, \
-                    (strict)))
-#define REGNO_SP_P(regno, strict) \
-  (REGNO_IN_RANGE_P ((regno), STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, \
-                    (strict)))
+  mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict)
 #define REGNO_EXTENDED_P(regno, strict) \
-  (REGNO_IN_RANGE_P ((regno), FIRST_EXTENDED_REGNUM, LAST_EXTENDED_REGNUM, \
-                    (strict)))
-#define REGNO_AM33_P(regno, strict) \
-  (REGNO_DATA_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)) \
-   || REGNO_EXTENDED_P ((regno), (strict)))
-#define REGNO_FP_P(regno, strict) \
-  (REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM, (strict)))
+  mn10300_regno_in_class_p (regno, EXTENDED_REGS, strict)
+#define REGNO_GENERAL_P(regno, strict) \
+  mn10300_regno_in_class_p (regno, GENERAL_REGS, strict)
 
 #define REGNO_STRICT_OK_FOR_BASE_P(regno, strict) \
-  (REGNO_SP_P ((regno), (strict)) \
-   || REGNO_ADDRESS_P ((regno), (strict)) \
-   || REGNO_EXTENDED_P ((regno), (strict)))
+  mn10300_regno_in_class_p (regno, BASE_REG_CLASS, strict)
 #define REGNO_OK_FOR_BASE_P(regno) \
   (REGNO_STRICT_OK_FOR_BASE_P ((regno), REG_STRICT))
 #define REG_OK_FOR_BASE_P(X) \
   (REGNO_OK_FOR_BASE_P (REGNO (X)))
 
 #define REGNO_STRICT_OK_FOR_BIT_BASE_P(regno, strict) \
-  (REGNO_SP_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)))
+  mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict)
 #define REGNO_OK_FOR_BIT_BASE_P(regno) \
   (REGNO_STRICT_OK_FOR_BIT_BASE_P ((regno), REG_STRICT))
 #define REG_OK_FOR_BIT_BASE_P(X) \
   (REGNO_OK_FOR_BIT_BASE_P (REGNO (X)))
 
 #define REGNO_STRICT_OK_FOR_INDEX_P(regno, strict) \
-  (REGNO_DATA_P ((regno), (strict)) || REGNO_EXTENDED_P ((regno), (strict)))
+  mn10300_regno_in_class_p (regno, INDEX_REG_CLASS, strict)
 #define REGNO_OK_FOR_INDEX_P(regno) \
   (REGNO_STRICT_OK_FOR_INDEX_P ((regno), REG_STRICT))
 #define REG_OK_FOR_INDEX_P(X) \
@@ -557,7 +529,15 @@ struct cum_arg
 #define MAX_REGS_PER_ADDRESS 2
 
 \f
-#define HAVE_POST_INCREMENT (TARGET_AM33)
+/* We have post-increments.  */
+#define HAVE_POST_INCREMENT    TARGET_AM33
+#define HAVE_POST_MODIFY_DISP  TARGET_AM33
+
+/* ... But we don't want to use them for block moves.  Small offsets are
+   just as effective, at least for inline block move sizes, and appears
+   to produce cleaner code.  */
+#define USE_LOAD_POST_INCREMENT(M)     0
+#define USE_STORE_POST_INCREMENT(M)    0
 
 /* Accept either REG or SUBREG where a register is valid.  */
 
@@ -568,6 +548,15 @@ struct cum_arg
        && REGNO_STRICT_OK_FOR_BASE_P (REGNO (SUBREG_REG (X)),  \
                                      (strict))))
 
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN)              \
+do {                                                                        \
+  rtx new_x = mn10300_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \
+  if (new_x)                                                                \
+    {                                                                       \
+      X = new_x;                                                            \
+      goto WIN;                                                                     \
+    }                                                                       \
+} while (0)
 \f
 
 /* Nonzero if the constant value X is a legitimate general operand.