Patchwork [19/28] mn10300: tidy pic address loading

login
register
mail settings
Submitter Richard Henderson
Date Jan. 10, 2011, 8:31 p.m.
Message ID <1294691517-19580-20-git-send-email-rth@redhat.com>
Download mbox | patch
Permalink /patch/78218/
State New
Headers show

Comments

Richard Henderson - Jan. 10, 2011, 8:31 p.m.
From: Richard Henderson <rth@twiddle.net>

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.
---
 gcc/config/mn10300/mn10300-protos.h |    1 +
 gcc/config/mn10300/mn10300.c        |  107 +++++-------------
 gcc/config/mn10300/mn10300.h        |    2 -
 gcc/config/mn10300/mn10300.md       |  207 ++++++++++++-----------------------
 4 files changed, 99 insertions(+), 218 deletions(-)
Jeff Law - Jan. 19, 2011, 4:33 p.m.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 01/10/11 13:31, Richard Henderson wrote:
> From: Richard Henderson <rth@twiddle.net>
> 
> 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.
OK.
Jeff
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJNNxJRAAoJEBRtltQi2kC7f7kIAJk/omUcSXn7RPp0cewz5Pzu
IiLn+WHkfuGz//WWz9TCk/Wl6xW6mIrf9mWtfwl75SpA6Hqnixm0504rEv2LNPvW
BjtIVk+Db/59uRfS2+0BcZsCeFAbwlRKCM9+GgSO58pio578uc3vk19ASRfPwte0
wDtyami7YZ8n73kdjjh2fBUQBrYrLnI6pBxqTslP3YqHfUTzGMTUrX+miRHLcOkM
S8BDg/XkpDEKwlkoLKvnlAPVZZUOEHi21mDT8W42ByUYj3Snooc3Lrlk2W7JmWPp
oFIYJLe4cK+JsV1Vpnc8XRChKOfE1b0JlZBJCalDa/enxLqGdbIQaNQVMaDfOL4=
=lVpl
-----END PGP SIGNATURE-----

Patch

diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h
index 28a9412..c25ba9b 100644
--- a/gcc/config/mn10300/mn10300-protos.h
+++ b/gcc/config/mn10300/mn10300-protos.h
@@ -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
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 8e62a0c..38a1c53 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -44,10 +44,6 @@ 
 #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:
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index 34ff2ae..fe6f754 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -53,8 +53,6 @@ 
     }						\
   while (0)
 
-extern GTY(()) int mn10300_unspec_int_label_counter;
-
 enum processor_type
 {
   PROCESSOR_MN10300,
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 965c6558..24c8d11 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -31,7 +31,6 @@ 
   (MDR_REG  50)
   (CC_REG   51)
 
-  (UNSPEC_INT_LABEL	0)
   (UNSPEC_PIC		1)
   (UNSPEC_GOT		2)
   (UNSPEC_GOTOFF	3)
@@ -284,7 +283,6 @@ 
 	(match_operand:SI     1 "impossible_plus_operand" ""))
    (clobber (match_operand:SI 2 "register_operand" "=&A"))]
   ""
-  "
 {
   rtx dest, scratch, other;
 
@@ -326,16 +324,7 @@ 
 	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")
@@ -1106,13 +1095,10 @@ 
 (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")
@@ -1555,16 +1541,14 @@ 
 (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)
@@ -1581,13 +1565,12 @@ 
    (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)))]
@@ -1598,15 +1581,14 @@ 
   [(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)))]
@@ -1615,116 +1597,67 @@ 
 (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")]
 )