This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch RFC] SH: Use FRAME_GROWS_DOWNWARD


Hi,

The attached patch is to use the soft frame pointer on SH backend.
It's tested with bootstrap and the toplevel "make -k check" with
no new failures on sh4-unknown-linux-gnu and sh64-unknown-linux-gnu,
except one libffi test failure on sh4-unknown-linux-gnu.  It turned
out that that libffi failure is a latent bug in the SH port of libffi
and I'm preparing a fix for it.

Regards,
	kaz
--
2005-07-06  Kaz Kojima  <kkojima@gcc.gnu.org>

	* config/sh/sh.c (regno_reg_class): Add GENERAL_REGS for
	soft frame pointer.
	(sh_expand_prologue): Use hard_frame_pointer_rtx instead
	of frame_pointer_rtx.
	(sh_expand_epilogue): Likewise.
	(sh_set_return_address): Likewise.
	(initial_elimination_offset): Use HARD_FRAME_POINTER_REGNUM
	instead of FRAME_POINTER_REGNUM if needed.  Add elimination
	offsets from FRAME_POINTER_REGNUM.
	* config/sh/sh.h (SH_REGISTER_NAMES_INITIALIZER): Add sfp.
	(sh_register_names): Add initializer for sfp.
	(GENERAL_OR_AP_REGISTER_P): Permit FRAME_POINTER_REGNUM.
	(VALID_REGISTER_P): Likewise.
	(FIRST_PSEUDO_REGISTER): Update.
	(DWARF_FRAME_REGISTERS): Define.
	(FIXED_REGISTERS, CALL_USED_REGISTERS): Add sfp.
	(HARD_FRAME_POINTER_REGNUM): Define.
	(FRAME_POINTER_REGNUM): Redefine.
	(ELIMINABLE_REGS): Never eliminate to FRAME_POINTER_REGNUM,
	but HARD_FRAME_POINTER_REGNUM instead.  Add eliminations
	from FRAME_POINTER_REGNUM.
	(CAN_ELIMINATE): Use HARD_FRAME_POINTER_REGNUM 	instead of
	FRAME_POINTER_REGNUM.
	(REG_CLASS_CONTENTS): Add sfp.
	(REG_ALLOC_ORDER): Likewise.
	(FRAME_GROWS_DOWNWARD): Set to 1.  Update comment.
	(GO_IF_LEGITIMATE_ADDRESS): Use hard_frame_pointer_rtx instead
	of frame_pointer_rtx.
	(LEGITIMIZE_RELOAD_ADDRESS): Likewise.

diff -uprN ORIG/gcc/gcc/config/sh/sh.c LOCAL/gcc/gcc/config/sh/sh.c
--- ORIG/gcc/gcc/config/sh/sh.c	2005-07-05 06:32:59.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.c	2005-07-05 11:25:50.000000000 +0900
@@ -169,7 +169,7 @@ enum reg_class regno_reg_class[FIRST_PSE
   DF_REGS, DF_REGS, DF_REGS, DF_REGS,
   NO_REGS, GENERAL_REGS, PR_REGS, T_REGS,
   MAC_REGS, MAC_REGS, FPUL_REGS, FPSCR_REGS,
-  GENERAL_REGS,
+  GENERAL_REGS, GENERAL_REGS,
 };
 
 char sh_register_names[FIRST_PSEUDO_REGISTER] \
@@ -6006,7 +6006,7 @@ sh_expand_prologue (void)
 		       stack_pointer_rtx, 0, NULL);
 
   if (frame_pointer_needed)
-    frame_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
+    frame_insn (GEN_MOV (hard_frame_pointer_rtx, stack_pointer_rtx));
 
   if (TARGET_SHCOMPACT
       && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
@@ -6068,14 +6068,15 @@ sh_expand_epilogue (bool sibcall_p)
 	 when exception handling is enabled.  See PR/18032.  */
       if (flag_exceptions)
 	emit_insn (gen_blockage ());
-      output_stack_adjust (frame_size, frame_pointer_rtx, e, &live_regs_mask);
+      output_stack_adjust (frame_size, hard_frame_pointer_rtx, e,
+			   &live_regs_mask);
 
       /* We must avoid moving the stack pointer adjustment past code
 	 which reads from the local frame, else an interrupt could
 	 occur after the SP adjustment and clobber data in the local
 	 frame.  */
       emit_insn (gen_blockage ());
-      emit_insn (GEN_MOV (stack_pointer_rtx, frame_pointer_rtx));
+      emit_insn (GEN_MOV (stack_pointer_rtx, hard_frame_pointer_rtx));
     }
   else if (frame_size)
     {
@@ -6352,7 +6353,7 @@ sh_set_return_address (rtx ra, rtx tmp)
     pr_offset = rounded_frame_size (d);
 
   emit_insn (GEN_MOV (tmp, GEN_INT (pr_offset)));
-  emit_insn (GEN_ADD3 (tmp, tmp, frame_pointer_rtx));
+  emit_insn (GEN_ADD3 (tmp, tmp, hard_frame_pointer_rtx));
 
   tmp = gen_rtx_MEM (Pmode, tmp);
   emit_insn (GEN_MOV (tmp, ra));
@@ -7271,7 +7272,7 @@ initial_elimination_offset (int from, in
 
   total_saved_regs_space = regs_saved + regs_saved_rounding;
 
-  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
     return total_saved_regs_space + total_auto_space
       + current_function_args_info.byref_regs * 8;
 
@@ -7280,11 +7281,18 @@ initial_elimination_offset (int from, in
       + current_function_args_info.byref_regs * 8;
 
   /* Initial gap between fp and sp is 0.  */
-  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+  if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
     return 0;
 
+  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+    return rounded_frame_size (0);
+
+  if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+    return rounded_frame_size (0);
+
   gcc_assert (from == RETURN_ADDRESS_POINTER_REGNUM
-	      && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM));
+	      && (to == HARD_FRAME_POINTER_REGNUM
+		  || to == STACK_POINTER_REGNUM));
   if (TARGET_SH5)
     {
       int n = total_saved_regs_space;
diff -uprN ORIG/gcc/gcc/config/sh/sh.h LOCAL/gcc/gcc/config/sh/sh.h
--- ORIG/gcc/gcc/config/sh/sh.h	2005-07-05 06:33:00.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.h	2005-07-05 11:25:50.000000000 +0900
@@ -882,7 +882,7 @@ extern char sh_register_names[][MAX_REGI
   "tr0",  "tr1",  "tr2",  "tr3",  "tr4",  "tr5",  "tr6",  "tr7", 	\
   "xd0",  "xd2",  "xd4",  "xd6",  "xd8",  "xd10", "xd12", "xd14",	\
   "gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr",	\
-  "rap"									\
+  "rap",  "sfp"								\
 }
 
 #define REGNAMES_ARR_INDEX_1(index) \
@@ -907,7 +907,7 @@ extern char sh_register_names[][MAX_REGI
   REGNAMES_ARR_INDEX_8 (128), \
   REGNAMES_ARR_INDEX_8 (136), \
   REGNAMES_ARR_INDEX_8 (144), \
-  REGNAMES_ARR_INDEX_1 (152) \
+  REGNAMES_ARR_INDEX_2 (152) \
 }
 
 #define ADDREGNAMES_SIZE 32
@@ -969,7 +969,8 @@ extern char sh_additional_register_names
 	    (unsigned HOST_WIDE_INT) LAST_GENERAL_REG)
 
 #define GENERAL_OR_AP_REGISTER_P(REGNO) \
-  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG))
+  (GENERAL_REGISTER_P (REGNO) || ((REGNO) == AP_REG)	\
+   || ((REGNO) == FRAME_POINTER_REGNUM))
 
 #define FP_REGISTER_P(REGNO) \
   ((int) (REGNO) >= FIRST_FP_REG && (int) (REGNO) <= LAST_FP_REG)
@@ -999,6 +1000,7 @@ extern char sh_additional_register_names
 #define VALID_REGISTER_P(REGNO) \
   (SHMEDIA_REGISTER_P (REGNO) || XD_REGISTER_P (REGNO) \
    || (REGNO) == AP_REG || (REGNO) == RAP_REG \
+   || (REGNO) == FRAME_POINTER_REGNUM \
    || (TARGET_SH1 && (SPECIAL_REGISTER_P (REGNO) || (REGNO) == PR_REG)) \
    || (TARGET_SH2E && (REGNO) == FPUL_REG))
 
@@ -1011,7 +1013,10 @@ extern char sh_additional_register_names
    ? DImode \
    : SImode)
 
-#define FIRST_PSEUDO_REGISTER 153
+#define FIRST_PSEUDO_REGISTER 154
+
+/* Don't count soft frame pointer.  */
+#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.
@@ -1048,8 +1053,8 @@ extern char sh_additional_register_names
   0,      0,      0,      0,      0,      0,      0,      0,		\
 /*"gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr", */	\
   1,      1,      1,      1,      1,      1,      0,      1,		\
-/*"rap" */								\
-  1,									\
+/*"rap",  "sfp" */							\
+  1,	  1,								\
 }
 
 /* 1 for registers not available across function calls.
@@ -1088,8 +1093,8 @@ extern char sh_additional_register_names
   1,      1,      1,      1,      1,      1,      0,      0,		\
 /*"gbr",  "ap",	  "pr",   "t",    "mach", "macl", "fpul", "fpscr", */	\
   1,      1,      1,      1,      1,      1,      1,      1,		\
-/*"rap" */								\
-  1,									\
+/*"rap",  "sfp" */							\
+  1,	  1,								\
 }
 
 /* CONDITIONAL_REGISTER_USAGE might want to make a register call-used, yet
@@ -1204,7 +1209,10 @@ extern char sh_additional_register_names
 #define STACK_POINTER_REGNUM	SP_REG
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM	FP_REG
+#define HARD_FRAME_POINTER_REGNUM	FP_REG
+
+/* Base register for access to local variables of the function.  */
+#define FRAME_POINTER_REGNUM	153
 
 /* Fake register that holds the address on the stack of the
    current function's return address.  */
@@ -1246,16 +1254,18 @@ extern char sh_additional_register_names
    of elimination fail.  */
 
 #define ELIMINABLE_REGS						\
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},			\
+{{ HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},		\
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},			\
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},		\
  { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},	\
- { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM},	\
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},	\
  { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},			\
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},}
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},}
 
 /* Given FROM and TO register numbers, say whether this elimination
    is allowed.  */
 #define CAN_ELIMINATE(FROM, TO) \
-  (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
+  (!((FROM) == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
@@ -1380,7 +1390,7 @@ enum reg_class
 /* SIBCALL_REGS: Initialized in CONDITIONAL_REGISTER_USAGE.  */	\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	\
 /* GENERAL_REGS:  */							\
-  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x01020000 },	\
+  { 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x03020000 },	\
 /* FP0_REGS:  */							\
   { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000 },	\
 /* FP_REGS:  */								\
@@ -1396,7 +1406,7 @@ enum reg_class
 /* TARGET_REGS:  */							\
   { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff },	\
 /* ALL_REGS:  */							\
-  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff },	\
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff },	\
 }
 
 /* The same information, inverted:
@@ -1446,7 +1456,7 @@ extern enum reg_class regno_reg_class[FI
    128,129,130,131,132,133,134,135, \
    /* Fixed registers */ \
     15, 16, 24, 25, 26, 27, 63,144, \
-   145,146,147,148,149,152 }
+   145,146,147,148,149,152,153 }
 
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS \
@@ -1695,10 +1705,8 @@ extern enum reg_class reg_class_from_let
 #define STACK_GROWS_DOWNWARD
 
 /*  Define this macro to non-zero if the addresses of local variable slots
-    are at negative offsets from the frame pointer.
-
-    The SH only has positive indexes, so grow the frame up.  */
-#define FRAME_GROWS_DOWNWARD 0
+    are at negative offsets from the frame pointer.  */
+#define FRAME_GROWS_DOWNWARD 1
 
 /* Offset from the frame pointer to the first local variable slot to
    be allocated.  */
@@ -2528,9 +2536,11 @@ struct sh_args {
       if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0))	\
 	GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL);			\
       if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode		\
-	   || ((xop0 == stack_pointer_rtx || xop0 == frame_pointer_rtx)	\
+	   || ((xop0 == stack_pointer_rtx				\
+		|| xop0 == hard_frame_pointer_rtx)			\
 	       && REG_P (xop1) && REGNO (xop1) == R0_REG)		\
-	   || ((xop1 == stack_pointer_rtx || xop1 == frame_pointer_rtx)	\
+	   || ((xop1 == stack_pointer_rtx				\
+		|| xop1 == hard_frame_pointer_rtx)			\
 	       && REG_P (xop0) && REGNO (xop0) == R0_REG))		\
 	  && ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4)		\
 	      || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8)		\
@@ -2625,7 +2635,7 @@ struct sh_args {
       && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS)	\
       && (ALLOW_INDEXED_ADDRESS						\
 	  || XEXP ((X), 0) == stack_pointer_rtx				\
-	  || XEXP ((X), 0) == frame_pointer_rtx))			\
+	  || XEXP ((X), 0) == hard_frame_pointer_rtx))			\
     {									\
       rtx index_rtx = XEXP (X, 1);					\
       HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;		\


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]