OSDN Git Service

mn10300: tidy pic address loading
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Jan 2011 18:46:30 +0000 (18:46 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Jan 2011 18:46:30 +0000 (18:46 +0000)
There's little reason to greatly complicate things by splitting
the pic_load patterns and using complex rtl to make it work out.
Instead, use the %= marker to generate unique numbers and emit
the entire load_pic sequence at once.

At the same time, collect all references to outgoing_args_size
into mn10300_frame_size, and all computations of register save
area size into mn10300_initial_offset.

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

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

index 5a85c70..dcdd569 100644 (file)
@@ -1,5 +1,24 @@
 2011-01-19  Richard Henderson  <rth@redhat.com>
 
+       * config/mn10300/mn10300.c (mn10300_unspec_int_label_counter): Remove.
+       (mn10300_asm_output_addr_const_extra): Don't handle UNSPEC_INT_LABEL.
+       (mn10300_legitimate_constant_p): Likewise.
+       (mn10300_can_use_return_insn): Use mn10300_initial_offset.
+       (mn10300_frame_size): New.
+       (mn10300_expand_prologue): Use it.
+       (mn10300_expand_epilogue): Likewise.
+       (mn10300_initial_offset): Likewise.
+       * config/mn10300/mn10300-protos.h: Update.
+       * config/mn10300/mn10300.h (mn10300_unspec_int_label_counter): Remove.
+       * config/mn10300/mn10300.md (UNSPEC_INT_LABEL): Remove.
+       (prologue, epilogue, return_internal): Tidy output code.
+       (mn10300_store_multiple_operation, return): Likewise.
+       (int_label, pop_pic_reg, GOTaddr2picreg): Remove.
+       (am33_loadPC, mn10300_loadPC, call_next_insn): Remove.
+       (add_GOT_to_pic_reg, add_GOT_to_any_reg): Remove.
+       (load_pic, am33_load_pic): New.
+       (mn10300_load_pic0, mn10300_load_pic1): New.
+
        * config/mn10300/mn10300-modes.def (CCZN, CCZNC): New modes.
        * config/mn10300/mn10300.c (CC_FLAG_Z): New.
        (CC_FLAG_N, CC_FLAG_C, CC_FLAG_V): New.
index 28a9412..c25ba9b 100644 (file)
@@ -49,6 +49,7 @@ extern int   mn10300_can_use_return_insn (void);
 extern void  mn10300_expand_prologue (void);
 extern void  mn10300_expand_epilogue (void);
 extern int   mn10300_initial_offset (int, int);
+extern int   mn10300_frame_size (void);
 
 #undef Mmode
 #undef Cstar
index 7535253..b2c2460 100644 (file)
 #include "target-def.h"
 #include "df.h"
 
-/* This is used by GOTaddr2picreg to uniquely identify
-   UNSPEC_INT_LABELs.  */
-int mn10300_unspec_int_label_counter;
-
 /* This is used in the am33_2.0-linux-gnu port, in which global symbol
    names are not prefixed by underscores, to tell whether to prefix a
    label with a plus sign or not, so that the assembler can tell
@@ -544,10 +540,6 @@ mn10300_asm_output_addr_const_extra (FILE *file, rtx x)
     {
       switch (XINT (x, 1))
        {
-       case UNSPEC_INT_LABEL:
-         asm_fprintf (file, ".%LLIL" HOST_WIDE_INT_PRINT_DEC,
-                      INTVAL (XVECEXP (x, 0, 0)));
-         break;
        case UNSPEC_PIC:
          /* GLOBAL_OFFSET_TABLE or local symbols, no suffix.  */
          output_addr_const (file, XVECEXP (x, 0, 0));
@@ -634,24 +626,7 @@ mn10300_print_reg_list (FILE *file, int mask)
 int
 mn10300_can_use_return_insn (void)
 {
-  /* size includes the fixed stack space needed for function calls.  */
-  int size = get_frame_size () + crtl->outgoing_args_size;
-
-  /* And space for the return pointer.  */
-  size += crtl->outgoing_args_size ? 4 : 0;
-
-  return (reload_completed
-         && size == 0
-         && !df_regs_ever_live_p (2)
-         && !df_regs_ever_live_p (3)
-         && !df_regs_ever_live_p (6)
-         && !df_regs_ever_live_p (7)
-         && !df_regs_ever_live_p (14)
-         && !df_regs_ever_live_p (15)
-         && !df_regs_ever_live_p (16)
-         && !df_regs_ever_live_p (17)
-         && fp_regs_to_save () == 0
-         && !frame_pointer_needed);
+  return !mn10300_initial_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM);
 }
 
 /* Returns the set of live, callee-saved registers as a bitmask.  The
@@ -760,11 +735,7 @@ mn10300_gen_multiple_store (unsigned int mask)
 void
 mn10300_expand_prologue (void)
 {
-  HOST_WIDE_INT size;
-
-  /* SIZE includes the fixed stack space needed for function calls.  */
-  size = get_frame_size () + crtl->outgoing_args_size;
-  size += (crtl->outgoing_args_size ? 4 : 0);
+  HOST_WIDE_INT size = mn10300_frame_size ();
 
   /* If we use any of the callee-saved registers, save them now.  */
   mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
@@ -1017,17 +988,13 @@ mn10300_expand_prologue (void)
                              GEN_INT (-size))));
 
   if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
-    emit_insn (gen_GOTaddr2picreg ());
+    emit_insn (gen_load_pic ());
 }
 
 void
 mn10300_expand_epilogue (void)
 {
-  HOST_WIDE_INT size;
-
-  /* SIZE includes the fixed stack space needed for function calls.  */
-  size = get_frame_size () + crtl->outgoing_args_size;
-  size += (crtl->outgoing_args_size ? 4 : 0);
+  HOST_WIDE_INT size = mn10300_frame_size ();
   
   if (TARGET_AM33_2 && fp_regs_to_save ())
     {
@@ -1442,54 +1409,37 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
 }
 
 int
+mn10300_frame_size (void)
+{
+  /* size includes the fixed stack space needed for function calls.  */
+  int size = get_frame_size () + crtl->outgoing_args_size;
+
+  /* And space for the return pointer.  */
+  size += crtl->outgoing_args_size ? 4 : 0;
+
+  return size;
+}
+
+int
 mn10300_initial_offset (int from, int to)
 {
+  int diff = 0;
+
+  gcc_assert (from == ARG_POINTER_REGNUM || from == FRAME_POINTER_REGNUM);
+  gcc_assert (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
+
+  if (to == STACK_POINTER_REGNUM)
+    diff = mn10300_frame_size ();
+
   /* The difference between the argument pointer and the frame pointer
      is the size of the callee register save area.  */
-  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+  if (from == ARG_POINTER_REGNUM)
     {
-      if (df_regs_ever_live_p (2) || df_regs_ever_live_p (3)
-         || df_regs_ever_live_p (6) || df_regs_ever_live_p (7)
-         || df_regs_ever_live_p (14) || df_regs_ever_live_p (15)
-         || df_regs_ever_live_p (16) || df_regs_ever_live_p (17)
-         || fp_regs_to_save ()
-         || frame_pointer_needed)
-       return REG_SAVE_BYTES
-         + 4 * fp_regs_to_save ();
-      else
-       return 0;
+      diff += REG_SAVE_BYTES;
+      diff += 4 * fp_regs_to_save ();
     }
 
-  /* The difference between the argument pointer and the stack pointer is
-     the sum of the size of this function's frame, the callee register save
-     area, and the fixed stack space needed for function calls (if any).  */
-  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    {
-      if (df_regs_ever_live_p (2) || df_regs_ever_live_p (3)
-         || df_regs_ever_live_p (6) || df_regs_ever_live_p (7)
-         || df_regs_ever_live_p (14) || df_regs_ever_live_p (15)
-         || df_regs_ever_live_p (16) || df_regs_ever_live_p (17)
-         || fp_regs_to_save ()
-         || frame_pointer_needed)
-       return (get_frame_size () + REG_SAVE_BYTES
-               + 4 * fp_regs_to_save ()
-               + (crtl->outgoing_args_size
-                  ? crtl->outgoing_args_size + 4 : 0));
-      else
-       return (get_frame_size ()
-               + (crtl->outgoing_args_size
-                  ? crtl->outgoing_args_size + 4 : 0));
-    }
-
-  /* The difference between the frame pointer and stack pointer is the sum
-     of the size of this function's frame and the fixed stack space needed
-     for function calls (if any).  */
-  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
-    return (get_frame_size ()
-           + (crtl->outgoing_args_size
-              ? crtl->outgoing_args_size + 4 : 0));
-
-  gcc_unreachable ();
+  return diff;
 }
 
 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
@@ -2087,7 +2037,6 @@ mn10300_legitimate_constant_p (rtx x)
        {
          switch (XINT (x, 1))
            {
-           case UNSPEC_INT_LABEL:
            case UNSPEC_PIC:
            case UNSPEC_GOT:
            case UNSPEC_GOTOFF:
index 21d3633..b10f450 100644 (file)
@@ -53,8 +53,6 @@
     }                                          \
   while (0)
 
-extern GTY(()) int mn10300_unspec_int_label_counter;
-
 enum processor_type
 {
   PROCESSOR_MN10300,
index 152477c..2477cb3 100644 (file)
@@ -31,7 +31,6 @@
   (MDR_REG  50)
   (CC_REG   51)
 
-  (UNSPEC_INT_LABEL    0)
   (UNSPEC_PIC          1)
   (UNSPEC_GOT          2)
   (UNSPEC_GOTOFF       3)
        (match_operand:SI     1 "impossible_plus_operand" ""))
    (clobber (match_operand:SI 2 "register_operand" "=&A"))]
   ""
-  "
 {
   rtx dest, scratch, other;
 
        emit_move_insn (dest, scratch);
     }
   DONE;
-}")
-
-(define_insn "pop_pic_reg"
-  [(set (reg:SI PIC_REG)
-       (mem:SI (post_inc:SI (reg:SI SP_REG))))]
-  "reload_completed"
-  "movm (sp),[a2]"
-  [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
-                                      (const_int 44) (const_int 33)))]
-)
+})
 
 (define_expand "movsi"
   [(set (match_operand:SI 0 "nonimmediate_operand")
 (define_expand "builtin_setjmp_receiver"
   [(match_operand 0 "" "")]
   "flag_pic"
-  "
 {
-  if (flag_pic)
-    emit_insn (gen_GOTaddr2picreg ());
-
+  emit_insn (gen_load_pic ());
   DONE;
-}")
+})
 
 (define_expand "casesi"
   [(match_operand:SI 0 "register_operand")
 (define_expand "prologue"
   [(const_int 0)]
   ""
-  "mn10300_expand_prologue (); DONE;")
+  { mn10300_expand_prologue (); DONE; }
+)
 
 (define_expand "epilogue"
   [(return)]
   ""
-  "
-  {
-    mn10300_expand_epilogue ();
-    DONE;
-  }")
+  { mn10300_expand_epilogue (); DONE; }
+)
 
 (define_insn "return_internal"
   [(const_int 2)
    (match_operand:SI 0  "const_int_operand" "i")
    (return)]
   ""
-  "*
-  {
-    fputs (\"\\tret \", asm_out_file);
-    mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
-    fprintf (asm_out_file, \",%d\\n\", (int) INTVAL (operands[0]));
-    return \"\";
-  }"
+{
+  fputs ("\tret ", asm_out_file);
+  mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ());
+  fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0]));
+  return "";
+}
   ;; Assumes that there will be no more than 8 regs to pop
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 1414) (const_int 1313)))]
   [(match_parallel 0 "mn10300_store_multiple_operation"
     [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (match_operand 1 "" "")))])]
   ""
-  "*
-  {
-    fputs (\"\\tmovm \", asm_out_file);
-    mn10300_print_reg_list (asm_out_file,
-                            mn10300_store_multiple_operation (operands[0],
-                                                             VOIDmode));
-    fprintf (asm_out_file, \",(sp)\\n\");
-    return \"\";
-  }"
+{
+  fputs ("\tmovm ", asm_out_file);
+  mn10300_print_reg_list (asm_out_file,
+                          mn10300_store_multiple_operation (operands[0],
+                                                           VOIDmode));
+  fprintf (asm_out_file, ",(sp)\n");
+  return "";
+}
   ;; Assume that no more than 8 registers will be pushed.
   [(set (attr "timings") (if_then_else (eq_attr "cpu" "am34")
                                       (const_int 99) (const_int 88)))]
 (define_insn "return"
   [(return)]
   "mn10300_can_use_return_insn ()"
-  "*
-{
-  rtx next = next_active_insn (insn);
-
-  if (next
-      && JUMP_P (next)
-      && GET_CODE (PATTERN (next)) == RETURN)
-    return \"\";
-  else
-    return \"rets\";
-}"
+  "rets"
   [(set_attr "timings" "66")]
 )
 
-(define_expand "int_label"
-  [(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)]
-  "" "")
-
-(define_expand "GOTaddr2picreg"
-  [(match_dup 0)]
-  "" "
+(define_expand "load_pic"
+  [(const_int 0)]
+  "flag_pic"
 {
-  /* It would be nice to be able to have int_label keep track of the
-     counter and all, but if we add C code to it, we'll get an insn
-     back, and we just want the pattern.  */
-  operands[0] = gen_int_label (GEN_INT (mn10300_unspec_int_label_counter++));
   if (TARGET_AM33)
-    emit_insn (gen_am33_loadPC (operands[0]));
+    emit_insn (gen_am33_load_pic (pic_offset_table_rtx));
+  else if (mn10300_frame_size () == 0)
+    emit_insn (gen_mn10300_load_pic0 (pic_offset_table_rtx));
   else
-    emit_insn (gen_mn10300_loadPC (operands[0]));
-  emit_insn (gen_add_GOT_to_pic_reg (copy_rtx (operands[0])));
+    emit_insn (gen_mn10300_load_pic1 (pic_offset_table_rtx));
   DONE;
-}
-")
+})
 
-(define_insn "am33_loadPC"
-  [(parallel
-    [(set (reg:SI PIC_REG) (pc))
-     (use (match_operand 0 "" ""))])]
+(define_insn "am33_load_pic"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(const_int 0)] UNSPEC_GOT))
+   (clobber (reg:CC CC_REG))]
   "TARGET_AM33"
-  "%0:\;mov pc,a2"
+{
+  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+  return ".LPIC%=:\;mov pc,%0\;add %1-(.LPIC%=-.),%0";
+}
+  [(set_attr "timings" "33")]
 )
 
-(define_insn_and_split "mn10300_loadPC"
-  [(parallel
-    [(set (reg:SI PIC_REG) (pc))
-     (use (match_operand 0 "" ""))])]
-  "! TARGET_AM33"
-  "#"
-  "&& reload_completed"
-  [(match_operand 0 "" "")]
-  {
-    rtx sp_reg = gen_rtx_REG (SImode, SP_REG);
-    int need_stack_space = (get_frame_size () == 0
-                           && crtl->outgoing_args_size == 0);
-
-    if (need_stack_space)
-      emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-4)));
-
-    emit_insn (gen_call_next_insn (operands[0]));
-
-    if (need_stack_space)
-      emit_insn (gen_pop_pic_reg ());
-    else
-      emit_move_insn (pic_offset_table_rtx, gen_rtx_MEM (SImode, sp_reg));
-    DONE;
-  }
+;; Load pic register with push/pop of stack.
+(define_insn "mn10300_load_pic0"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(const_int 0)] UNSPEC_GOT))
+   (clobber (reg:SI MDR_REG))
+   (clobber (reg:CC CC_REG))]
+  ""
+{
+  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+  return ("add -4,sp\;"
+         "calls .LPIC%=\n"
+          ".LPIC%=:\;"
+         "movm (sp),[%0]\;"
+         "add %1-(.LPIC%=-.),%0");
+}
+  [(set_attr "timings" "88")]
 )
 
-(define_insn "call_next_insn"
-  [(parallel
-    [(set (mem:SI (reg:SI SP_REG)) (pc))
-     (use (match_operand 0 "" ""))])]
-  "reload_completed"
-  "calls %0\;%0:"
-  [(set_attr "timings" "44")]
-)
-
-(define_expand "add_GOT_to_pic_reg"
-  [(parallel [(set (reg:SI PIC_REG)
-                  (plus:SI
-                   (reg:SI PIC_REG)
-                   (const:SI
-                    (unspec:SI [(minus:SI
-                              (match_dup 1)
-                              (const (minus:SI
-                                      (const (match_operand:SI 0 "" ""))
-                                      (pc))))
-                             ] UNSPEC_PIC))))
-             (clobber (reg:CC CC_REG))
-             ])
-  ]
-  ""
-  "operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);"
-)
-
-(define_expand "add_GOT_to_any_reg"
-  [(parallel [(set (match_operand:SI 0 "" "")
-                  (plus:SI
-                   (match_operand:SI 1 "" "")
-                   (const
-                    (unspec [(minus:SI
-                              (match_dup 3)
-                              (const (minus:SI
-                                      (const (match_operand:SI 2 "" ""))
-                                      (pc))))
-                             ] UNSPEC_PIC))))
-             (clobber (reg:CC CC_REG))
-            ])
-  ]
+;; Load pic register re-using existing stack space.
+(define_insn "mn10300_load_pic1"
+  [(set (match_operand:SI 0 "register_operand" "=a")
+       (unspec:SI [(const_int 0)] UNSPEC_GOT))
+   (clobber (mem:SI (reg:SI SP_REG)))
+   (clobber (reg:SI MDR_REG))
+   (clobber (reg:CC CC_REG))]
   ""
-  "operands[3] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);"
+{
+  operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
+  return ("calls .LPIC%=\n"
+         ".LPIC%=:\;"
+          "mov (sp),%0\;"
+          "add %1-(.LPIC%=-.),%0");
+}
+  [(set_attr "timings" "66")]
 )