public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch RFC] M32R: Use RTL epilogues
@ 2007-01-16 23:36 Kaz Kojima
  2007-01-18 17:05 ` Nick Clifton
  0 siblings, 1 reply; 2+ messages in thread
From: Kaz Kojima @ 2007-01-16 23:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: nickc, inaoka.kazuhiro

Hi,

A recent thread for ColdFire reminds me a patch for m32r.
The appended patch makes m32r use rtl epilogues instead
of textual epilogues.  It's tested on x86-linux cross
m32r-unknown-linux-gnu with c/c++ build and the top level
"make -k check" with no new failures.

Regards,
	kaz
--
	* config/m32r/m32r-protos.h (m32r_expand_epilogue): Declare it.
	* config/m32r/m32r.c (m32r_setup_incoming_varargs): Use gen_frame_mem.
	(m32r_compute_frame_size): Use unsigned for regno.
	(m32r_reload_lr): Use gen_frame_mem.
	(pop): New.
	(m32r_output_function_epilogue): Don't output the function epilogue
	textually here.
	(m32r_expand_epilogue): New.
	(direct_return): Return false if the function has the interrupt
	attribute.
	(m32r_hard_regno_rename_ok): Remove code for the textual epilogue.
	* config/m32r/m32r.md (epilogue): New expander.
	(return_lr, return_rte): New insns.
	(return): Make it expander.
	(return_normal): New expander.

diff -uprN ORIG/trunk/gcc/config/m32r/m32r-protos.h LOCAL/trunk/gcc/config/m32r/m32r-protos.h
--- ORIG/trunk/gcc/config/m32r/m32r-protos.h	2005-12-09 08:21:08.000000000 +0900
+++ LOCAL/trunk/gcc/config/m32r/m32r-protos.h	2007-01-14 09:35:08.000000000 +0900
@@ -1,5 +1,5 @@
 /* Prototypes for m32r.c functions used in the md file & elsewhere.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
    Free Software Foundation, Inc.
 
    This file is part of GCC.
@@ -27,6 +27,7 @@ extern void   m32r_init (void);
 extern void   m32r_init_expanders (void);
 extern unsigned m32r_compute_frame_size (int);
 extern void   m32r_expand_prologue (void);
+extern void   m32r_expand_epilogue (void);
 extern int    direct_return (void);
 extern void   m32r_load_pic_register (void);
 
diff -uprN ORIG/trunk/gcc/config/m32r/m32r.c LOCAL/trunk/gcc/config/m32r/m32r.c
--- ORIG/trunk/gcc/config/m32r/m32r.c	2007-01-03 10:41:01.000000000 +0900
+++ LOCAL/trunk/gcc/config/m32r/m32r.c	2007-01-14 09:35:25.000000000 +0900
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on the Renesas M32R cpu.
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005 Free Software Foundation, Inc.
+   2005, 2007 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -1045,9 +1045,9 @@ m32r_setup_incoming_varargs (CUMULATIVE_
       int size = M32R_MAX_PARM_REGS - first_reg_offset;
       rtx regblock;
 
-      regblock = gen_rtx_MEM (BLKmode,
-			      plus_constant (arg_pointer_rtx,
-					     FIRST_PARM_OFFSET (0)));
+      regblock = gen_frame_mem (BLKmode,
+				plus_constant (arg_pointer_rtx,
+					       FIRST_PARM_OFFSET (0)));
       set_mem_alias_set (regblock, get_varargs_alias_set ());
       move_block_from_reg (first_reg_offset, regblock, size);
 
@@ -1270,7 +1270,7 @@ static struct m32r_frame_info zero_frame
 unsigned int
 m32r_compute_frame_size (int size)	/* # of var. bytes allocated.  */
 {
-  int regno;
+  unsigned int regno;
   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
   unsigned int reg_size, frame_size;
   unsigned int gmask;
@@ -1339,18 +1339,18 @@ m32r_reload_lr (rtx sp, int size)
   rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
 
   if (size == 0)
-    emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, sp)));
+    emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, sp)));
   else if (size < 32768)
-    emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode,
-					   gen_rtx_PLUS (Pmode, sp,
-							 GEN_INT (size)))));
+    emit_insn (gen_movsi (lr, gen_frame_mem (Pmode,
+					     gen_rtx_PLUS (Pmode, sp,
+							   GEN_INT (size)))));
   else
     {   
       rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
 
       emit_insn (gen_movsi (tmp, GEN_INT (size)));
       emit_insn (gen_addsi3 (tmp, tmp, sp));
-      emit_insn (gen_movsi (lr, gen_rtx_MEM (Pmode, tmp)));
+      emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, tmp)));
     }
 
   emit_insn (gen_rtx_USE (VOIDmode, lr));
@@ -1481,19 +1481,27 @@ m32r_output_function_prologue (FILE * fi
 	   current_frame_info.extra_size);
 }
 \f
-/* Do any necessary cleanup after a function to restore stack, frame,
-   and regs.  */
+/* Output RTL to pop register REGNO from the stack.  */
 
 static void
-m32r_output_function_epilogue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+pop (int regno)
+{
+  rtx x;
+
+  x = emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno),
+				stack_pointer_rtx));
+  REG_NOTES (x)
+    = gen_rtx_EXPR_LIST (REG_INC, stack_pointer_rtx, 0);
+}
+
+/* Expand the m32r epilogue as a series of insns.  */
+
+void
+m32r_expand_epilogue (void)
 {
   int regno;
   int noepilogue = FALSE;
   int total_size;
-  enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
-
-  /* This is only for the human reader.  */
-  fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);
 
   gcc_assert (current_frame_info.initialized);
   total_size = current_frame_info.total_size;
@@ -1504,7 +1512,7 @@ m32r_output_function_epilogue (FILE * fi
 
       /* If the last insn was a BARRIER, we don't have to write any code
 	 because a jump (aka return) was put there.  */
-      if (GET_CODE (insn) == NOTE)
+      if (insn && GET_CODE (insn) == NOTE)
 	insn = prev_nonnote_insn (insn);
       if (insn && GET_CODE (insn) == BARRIER)
 	noepilogue = TRUE;
@@ -1516,88 +1524,82 @@ m32r_output_function_epilogue (FILE * fi
       unsigned int args_size = current_frame_info.args_size;
       unsigned int gmask = current_frame_info.gmask;
       int can_trust_sp_p = !current_function_calls_alloca;
-      const char * sp_str = reg_names[STACK_POINTER_REGNUM];
-      const char * fp_str = reg_names[FRAME_POINTER_REGNUM];
+
+      if (flag_exceptions)
+        emit_insn (gen_blockage ());
 
       /* The first thing to do is point the sp at the bottom of the register
 	 save area.  */
       if (can_trust_sp_p)
 	{
 	  unsigned int reg_offset = var_size + args_size;
+
 	  if (reg_offset == 0)
 	    ; /* Nothing to do.  */
-	  else if (reg_offset < 128)
-	    fprintf (file, "\taddi %s,%s%d\n",
-		     sp_str, IMMEDIATE_PREFIX, reg_offset);
 	  else if (reg_offset < 32768)
-	    fprintf (file, "\tadd3 %s,%s,%s%d\n",
-		     sp_str, sp_str, IMMEDIATE_PREFIX, reg_offset);
-	  else if (reg_offset < (1 << 24))
-	    fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset,
-		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
+	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+			   GEN_INT (reg_offset)));
 	  else
-	    fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n",
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset >> 16,
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset & 0xffff,
-		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
+	    {
+	      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
+
+	      emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
+	      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				     tmp));
+	    }
 	}
       else if (frame_pointer_needed)
 	{
 	  unsigned int reg_offset = var_size + args_size;
 
 	  if (reg_offset == 0)
-	    fprintf (file, "\tmv %s,%s\n", sp_str, fp_str);
+	    emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
 	  else if (reg_offset < 32768)
-	    fprintf (file, "\tadd3 %s,%s,%s%d\n",
-		     sp_str, fp_str, IMMEDIATE_PREFIX, reg_offset);
-	  else if (reg_offset < (1 << 24))
-	    fprintf (file, "\tld24 %s,%s%d\n\tadd %s,%s\n",
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset,
-		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
+	    emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
+			   GEN_INT (reg_offset)));
 	  else
-	    fprintf (file, "\tseth %s,%s%d\n\tor3 %s,%s,%s%d\n\tadd %s,%s\n",
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset >> 16,
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     reg_names[PROLOGUE_TMP_REGNUM],
-		     IMMEDIATE_PREFIX, reg_offset & 0xffff,
-		     sp_str, reg_names[PROLOGUE_TMP_REGNUM]);
+	    {
+	      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
+
+	      emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
+	      emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
+	      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+				     tmp));
+	    }
 	}
       else
 	gcc_unreachable ();
 
       if (current_frame_info.save_lr)
-	fprintf (file, "\tpop %s\n", reg_names[RETURN_ADDR_REGNUM]);
+	pop (RETURN_ADDR_REGNUM);
 
       /* Restore any saved registers, in reverse order of course.  */
       gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
       for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno)
 	{
 	  if ((gmask & (1L << regno)) != 0)
-	    fprintf (file, "\tpop %s\n", reg_names[regno]);
+	    pop (regno);
 	}
 
       if (current_frame_info.save_fp)
-	fprintf (file, "\tpop %s\n", fp_str);
+	pop (FRAME_POINTER_REGNUM);
 
       /* Remove varargs area if present.  */
       if (current_frame_info.pretend_size != 0)
-	fprintf (file, "\taddi %s,%s%d\n",
-		 sp_str, IMMEDIATE_PREFIX, current_frame_info.pretend_size);
-	
-      /* Emit the return instruction.  */
-      if (M32R_INTERRUPT_P (fn_type))
-	fprintf (file, "\trte\n");
-      else
-	fprintf (file, "\tjmp %s\n", reg_names[RETURN_ADDR_REGNUM]);
+	emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+			       GEN_INT (current_frame_info.pretend_size)));
+
+      emit_insn (gen_blockage ());
     }
+}
+\f
+/* Do any necessary cleanup after a function to restore stack, frame,
+   and regs.  */
 
+static void
+m32r_output_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
+			       HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
   /* Reset state info for each function.  */
   current_frame_info = zero_frame_info;
   m32r_compute_function_type (NULL_TREE);
@@ -1612,10 +1614,13 @@ direct_return (void)
   if (!reload_completed)
     return FALSE;
 
+  if (M32R_INTERRUPT_P (m32r_compute_function_type (current_function_decl)))
+    return FALSE;
+
   if (! current_frame_info.initialized)
     m32r_compute_frame_size (get_frame_size ());
 
-   return current_frame_info.total_size == 0;
+  return current_frame_info.total_size == 0;
 }
 
 \f
@@ -2447,11 +2452,6 @@ m32r_hard_regno_rename_ok (unsigned int 
       && !regs_ever_live[new_reg])
     return 0;
 
-  /* We currently emit epilogues as text, not rtl, so the liveness
-     of the return address register isn't visible.  */
-  if (current_function_is_leaf && new_reg == RETURN_ADDR_REGNUM)
-    return 0;
-
   return 1;
 }
 
diff -uprN ORIG/trunk/gcc/config/m32r/m32r.md LOCAL/trunk/gcc/config/m32r/m32r.md
--- ORIG/trunk/gcc/config/m32r/m32r.md	2006-07-29 16:59:32.000000000 +0900
+++ LOCAL/trunk/gcc/config/m32r/m32r.md	2007-01-14 09:35:47.000000000 +0900
@@ -1,6 +1,6 @@
 ;; Machine description of the Renesas M32R cpu for GNU C compiler
-;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005
-;  Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2001, 2003, 2004, 2005,
+;  2007 Free Software Foundation, Inc.
 
 ;; This file is part of GCC.
 
@@ -211,6 +211,17 @@
   DONE;
 }")
 
+;; Expand epilogue as RTL
+(define_expand "epilogue"
+  [(return)]
+  ""
+  "
+{
+  m32r_expand_epilogue ();
+  emit_jump_insn (gen_return_normal ());
+  DONE;
+}")
+
 \f
 ;; Move instructions.
 ;;
@@ -2270,13 +2281,47 @@
   [(set_attr "type" "uncond_branch")
    (set_attr "length" "2")])
 
-(define_insn "return"
-  [(return)]
-  "direct_return ()"
+(define_insn "return_lr"
+  [(parallel [(return) (use (reg:SI 14))])]
+  ""
   "jmp lr"
   [(set_attr "type" "uncond_branch")
    (set_attr "length" "2")])
  
+(define_insn "return_rte"
+  [(return)]
+  ""
+  "rte"
+  [(set_attr "type" "uncond_branch")
+   (set_attr "length" "2")])
+ 
+(define_expand "return"
+  [(return)]
+  "direct_return ()"
+  "
+{
+  emit_jump_insn (gen_return_lr ());
+  DONE;
+}")
+
+(define_expand "return_normal"
+  [(return)]
+  "!direct_return ()"
+  "
+{
+  enum m32r_function_type fn_type;
+
+  fn_type = m32r_compute_function_type (current_function_decl);
+  if (M32R_INTERRUPT_P (fn_type))
+    {
+      emit_jump_insn (gen_return_rte ());
+      DONE;
+    }
+
+  emit_jump_insn (gen_return_lr ());
+  DONE;
+}")
+
 (define_expand "tablejump"
   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
               (use (label_ref (match_operand 1 "" "")))])]

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [patch RFC] M32R: Use RTL epilogues
  2007-01-16 23:36 [patch RFC] M32R: Use RTL epilogues Kaz Kojima
@ 2007-01-18 17:05 ` Nick Clifton
  0 siblings, 0 replies; 2+ messages in thread
From: Nick Clifton @ 2007-01-18 17:05 UTC (permalink / raw)
  To: Kaz Kojima; +Cc: gcc-patches, inaoka.kazuhiro

Hi Kaz,

> 	* config/m32r/m32r-protos.h (m32r_expand_epilogue): Declare it.
> 	* config/m32r/m32r.c (m32r_setup_incoming_varargs): Use gen_frame_mem.
> 	(m32r_compute_frame_size): Use unsigned for regno.
> 	(m32r_reload_lr): Use gen_frame_mem.
> 	(pop): New.
> 	(m32r_output_function_epilogue): Don't output the function epilogue
> 	textually here.
> 	(m32r_expand_epilogue): New.
> 	(direct_return): Return false if the function has the interrupt
> 	attribute.
> 	(m32r_hard_regno_rename_ok): Remove code for the textual epilogue.
> 	* config/m32r/m32r.md (epilogue): New expander.
> 	(return_lr, return_rte): New insns.
> 	(return): Make it expander.
> 	(return_normal): New expander.

Approved and applied - thanks!

Cheers
   Nick

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-01-18 17:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-16 23:36 [patch RFC] M32R: Use RTL epilogues Kaz Kojima
2007-01-18 17:05 ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).