mn10300: Cleanup secondary reloads
authorRichard Henderson <rth@redhat.com>
Wed, 19 Jan 2011 17:02:57 +0000 (09:02 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 19 Jan 2011 17:02:57 +0000 (09:02 -0800)
Handles output reloads for QI/HImode properly; previously we were
only handing input reloads properly.

Handles reloads involving the stack pointer better; note that the
AM33 allows copying SP to DATA_REGS as well as ADDRESS and EXTENDED.

From-SVN: r169005

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

index 46ebaee53f213040aa9680bf13248f5326152128..06b439efcdb30ba93d50411ea2bcf4d2d9de08cc 100644 (file)
@@ -1,5 +1,17 @@
 2011-01-19  Richard Henderson  <rth@redhat.com>
 
+       * config/mn10300/mn10300.c (mn10300_preferred_reload_class): Allow
+       DATA_REGS for AM33 stack-pointer destination.
+       (mn10300_preferred_output_reload_class): Likewise.
+       (mn10300_secondary_reload): Rearrange mn10300_secondary_reload_class
+       into a form appropriate for ...
+       (TARGET_SECONDARY_RELOAD): New.
+       * config/mn10300/mn10300.h (SECONDARY_RELOAD_CLASS): Remove.
+       * config/mn10300/mn10300-protos.h: Update.
+       * config/mn10300/mn10300.md (reload_plus_sp_const): Rename from
+       reload_insi; use the "A" constraint for the scratch; handle AM33
+       moves of sp to non-address registers.
+
        * config/mn10300/mn10300.md (*am33_movqi, *mn10300_movqi): Merge into
        (*movqi_internal): ... here.
        (*am33_movhi, *mn10300_movhi): Merge into...
index d6cf850a52ce982b7793767fc39dddded327ad74..37968ff5cc9dd370ecb14063f74487709e960cee 100644 (file)
@@ -35,7 +35,6 @@ extern Cstar mn10300_output_cmp (rtx, rtx);
 extern void  mn10300_print_operand (FILE *, rtx, int);
 extern void  mn10300_print_operand_address (FILE *, rtx);
 extern void  mn10300_print_reg_list (FILE *, int);
-extern Rclas mn10300_secondary_reload_class (Rclas, Mmode, rtx);
 extern Mmode mn10300_select_cc_mode (rtx);
 extern int   mn10300_store_multiple_operation (rtx, Mmode);
 extern int   mn10300_symbolic_operand (rtx, Mmode);
index f9be6ea6c5857171dba242818d8e3487daf2d04b..29cf3373a60a856b507bd027a2827587e41da32f 100644 (file)
@@ -1327,7 +1327,7 @@ static reg_class_t
 mn10300_preferred_reload_class (rtx x, reg_class_t rclass)
 {
   if (x == stack_pointer_rtx && rclass != SP_REGS)
-     return ADDRESS_OR_EXTENDED_REGS;
+    return (TARGET_AM33 ? GENERAL_REGS : ADDRESS_REGS);
   else if (MEM_P (x)
           || (REG_P (x) 
               && !HARD_REGISTER_P (x))
@@ -1345,72 +1345,83 @@ static reg_class_t
 mn10300_preferred_output_reload_class (rtx x, reg_class_t rclass)
 {
   if (x == stack_pointer_rtx && rclass != SP_REGS)
-    return ADDRESS_OR_EXTENDED_REGS;
-
+    return (TARGET_AM33 ? GENERAL_REGS : ADDRESS_REGS);
   return rclass;
 }
 
-/* What (if any) secondary registers are needed to move IN with mode
-   MODE into a register in register class RCLASS.
-
-   We might be able to simplify this.  */
+/* Implement TARGET_SECONDARY_RELOAD.  */
 
-enum reg_class
-mn10300_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
-                               rtx in)
+static reg_class_t
+mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
+                         enum machine_mode mode, secondary_reload_info *sri)
 {
-  rtx inner = in;
-
-  /* Strip off any SUBREG expressions from IN.  Basically we want
-     to know if IN is a pseudo or (subreg (pseudo)) as those can
-     turn into MEMs during reload.  */
-  while (GET_CODE (inner) == SUBREG)
-    inner = SUBREG_REG (inner);
-
-  /* Memory loads less than a full word wide can't have an
-     address or stack pointer destination.  They must use
-     a data register as an intermediate register.  */
-  if ((MEM_P (in)
-       || (REG_P (inner)
-          && REGNO (inner) >= FIRST_PSEUDO_REGISTER))
-      && (mode == QImode || mode == HImode)
-      && (rclass == ADDRESS_REGS || rclass == SP_REGS
-         || rclass == SP_OR_ADDRESS_REGS))
+  enum reg_class rclass = (enum reg_class) rclass_i;
+  enum reg_class xclass = NO_REGS;
+  unsigned int xregno = INVALID_REGNUM;
+
+  if (REG_P (x))
     {
-      if (TARGET_AM33)
-       return DATA_OR_EXTENDED_REGS;
-      return DATA_REGS;
+      xregno = REGNO (x);
+      if (xregno >= FIRST_PSEUDO_REGISTER)
+       xregno = true_regnum (x);
+      if (xregno != INVALID_REGNUM)
+       xclass = REGNO_REG_CLASS (xregno);
+    }
+
+  if (!TARGET_AM33)
+    {
+      /* Memory load/stores less than a full word wide can't have an
+         address or stack pointer destination.  They must use a data
+         register as an intermediate register.  */
+      if (rclass != DATA_REGS
+         && (mode == QImode || mode == HImode)
+         && xclass == NO_REGS)
+       return DATA_REGS;
+
+      /* We can only move SP to/from an address register.  */
+      if (in_p
+         && rclass == SP_REGS
+         && xclass != ADDRESS_REGS)
+       return ADDRESS_REGS;
+      if (!in_p
+         && xclass == SP_REGS
+         && rclass != ADDRESS_REGS
+         && rclass != SP_OR_ADDRESS_REGS)
+       return ADDRESS_REGS;
     }
 
-  /* We can't directly load sp + const_int into a data register;
-     we must use an address register as an intermediate.  */
-  if (rclass != SP_REGS
-      && rclass != ADDRESS_REGS
+  /* We can't directly load sp + const_int into a register;
+     we must use an address register as an scratch.  */
+  if (in_p
+      && rclass != SP_REGS
       && rclass != SP_OR_ADDRESS_REGS
       && rclass != SP_OR_EXTENDED_REGS
-      && rclass != ADDRESS_OR_EXTENDED_REGS
       && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS
-      && (in == stack_pointer_rtx
-         || (GET_CODE (in) == PLUS
-             && (XEXP (in, 0) == stack_pointer_rtx
-                 || XEXP (in, 1) == stack_pointer_rtx))))
-    return ADDRESS_REGS;
+      && GET_CODE (x) == PLUS
+      && (XEXP (x, 0) == stack_pointer_rtx
+         || XEXP (x, 1) == stack_pointer_rtx))
+    {
+      sri->icode = CODE_FOR_reload_plus_sp_const;
+      return NO_REGS;
+    }
 
+  /* We can't load/store an FP register from a constant address.  */
   if (TARGET_AM33_2
-      && rclass == FP_REGS)
+      && (rclass == FP_REGS || xclass == FP_REGS)
+      && (xclass == NO_REGS || rclass == NO_REGS))
     {
-      /* We can't load directly into an FP register from a     
-        constant address.  */
-      if (MEM_P (in)
-         && CONSTANT_ADDRESS_P (XEXP (in, 0)))
-       return DATA_OR_EXTENDED_REGS;
+      rtx addr = NULL;
+
+      if (xregno >= FIRST_PSEUDO_REGISTER && xregno != INVALID_REGNUM)
+       {
+         addr = reg_equiv_mem [xregno];
+         if (addr)
+           addr = XEXP (addr, 0);
+       }
+      else if (MEM_P (x))
+       addr = XEXP (x, 0);
 
-      /* Handle case were a pseudo may not get a hard register
-        but has an equivalent memory location defined.  */
-      if (REG_P (inner)
-         && REGNO (inner) >= FIRST_PSEUDO_REGISTER
-         && reg_equiv_mem [REGNO (inner)]
-         && CONSTANT_ADDRESS_P (XEXP (reg_equiv_mem [REGNO (inner)], 0)))
+      if (addr && CONSTANT_ADDRESS_P (addr))
        return DATA_OR_EXTENDED_REGS;
     }
 
@@ -2802,7 +2813,10 @@ mn10300_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
 #undef  TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS mn10300_preferred_reload_class
 #undef  TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
-#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS mn10300_preferred_output_reload_class
+#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS \
+  mn10300_preferred_output_reload_class
+#undef  TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD  mn10300_secondary_reload
 
 #undef  TARGET_TRAMPOLINE_INIT
 #define TARGET_TRAMPOLINE_INIT mn10300_trampoline_init
index 3f63498d0864b39ffc54f737aa9fa4cc0bed19d7..1ed13b9b181b1d2c46900e7ef5cfdc696b96da23 100644 (file)
@@ -416,9 +416,6 @@ enum reg_class
 #define LIMIT_RELOAD_CLASS(MODE, CLASS) \
   (!TARGET_AM33 && (MODE == QImode || MODE == HImode) ? DATA_REGS : CLASS)
 
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
-  mn10300_secondary_reload_class(CLASS,MODE,IN)
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 
index 9cddebf3e79d17a701dddc9fefba2db0b1987016..7dd33676cf0f8fcf235e3934657f341414ac6b70 100644 (file)
 ;; We use this to handle addition of two values when one operand is the
 ;; stack pointer and the other is a memory reference of some kind.  Reload
 ;; does not handle them correctly without this expander.
-(define_expand "reload_insi"
-  [(set (match_operand:SI     0 "register_operand" "=a")
+(define_expand "reload_plus_sp_const"
+  [(set (match_operand:SI     0 "register_operand" "=r")
        (match_operand:SI     1 "impossible_plus_operand" ""))
-   (clobber (match_operand:SI 2 "register_operand" "=&r"))]
+   (clobber (match_operand:SI 2 "register_operand" "=&A"))]
   ""
   "
 {
-  gcc_assert (REGNO (operands[0]) != REGNO (operands[2]));
+  rtx dest, scratch, other;
 
-  if (XEXP (operands[1], 0) == stack_pointer_rtx)
+  dest = operands[0];
+  scratch = operands[2];
+
+  other = XEXP (operands[1], 1);
+  if (other == stack_pointer_rtx)
+    other = XEXP (operands[1], 0);
+
+  if (true_regnum (other) == true_regnum (dest))
     {
-      if (GET_CODE (XEXP (operands[1], 1)) == SUBREG
-         && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 1)))
-             > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 1))))))
-       emit_move_insn (operands[2],
-                       gen_rtx_ZERO_EXTEND
-                       (GET_MODE (XEXP (operands[1], 1)),
-                        SUBREG_REG (XEXP (operands[1], 1))));
-      else
-       emit_move_insn (operands[2], XEXP (operands[1], 1));
-      emit_move_insn (operands[0], XEXP (operands[1], 0));
+      gcc_assert (true_regnum (scratch) != true_regnum (dest));
+      emit_move_insn (scratch, stack_pointer_rtx);
+      emit_insn (gen_addsi3 (dest, dest, scratch));
+    }
+  else if (TARGET_AM33 || REGNO_REG_CLASS (true_regnum (dest)) == ADDRESS_REGS)
+    {
+      emit_move_insn (dest, stack_pointer_rtx);
+      if (other == stack_pointer_rtx)
+        emit_insn (gen_addsi3 (dest, dest, dest));
+      else if (other != const0_rtx)
+        emit_insn (gen_addsi3 (dest, dest, other));
     }
   else
     {
-      if (GET_CODE (XEXP (operands[1], 0)) == SUBREG
-         && (GET_MODE_SIZE (GET_MODE (XEXP (operands[1], 0)))
-             > GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (operands[1], 0))))))
-       emit_move_insn (operands[2],
-                       gen_rtx_ZERO_EXTEND
-                       (GET_MODE (XEXP (operands[1], 0)),
-                        SUBREG_REG (XEXP (operands[1], 0))));
+      emit_move_insn (scratch, stack_pointer_rtx);
+      if (other == stack_pointer_rtx)
+       {
+         emit_move_insn (dest, scratch);
+          emit_insn (gen_addsi3 (dest, dest, dest));
+       }
+      else if (other != const0_rtx)
+       {
+         emit_move_insn (dest, other);
+          emit_insn (gen_addsi3 (dest, dest, scratch));
+       }
       else
-       emit_move_insn (operands[2], XEXP (operands[1], 0));
-      emit_move_insn (operands[0], XEXP (operands[1], 1));
+       emit_move_insn (dest, scratch);
     }
-  emit_insn (gen_addsi3 (operands[0], operands[0], operands[2]));
   DONE;
 }")