This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch RFC] SH: Use FRAME_GROWS_DOWNWARD
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: gcc-patches at gcc dot gnu dot org
- Cc: joern dot rennecke at st dot com, aoliva at redhat dot com
- Date: Thu, 07 Jul 2005 05:46:43 +0900 (JST)
- Subject: [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; \