This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[MIPS 8/30] Fix handling of large MIPS16 frames
- From: Richard Sandiford <rsandifo at nildram dot co dot uk>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 18 Oct 2007 20:38:10 +0100
- Subject: [MIPS 8/30] Fix handling of large MIPS16 frames
- References: <87przc9wms.fsf@firetop.home>
This one's a bug fix. We were forcing large MIPS16 frames to use
a frame pointer by refusing to eliminate to the stack pointer.
However, we should really handle this in FRAME_POINTER_REQUIRED;
that way, you get a warning if you try to use the frame pointer
in an asm statement.
Richard
gcc/
* config/mips/mips-protos.h (mips_frame_pointer_required): Declare.
* config/mips/mips.h (FRAME_POINTER_REQUIRED): Use
mips_hard_frame_pointer_required.
(CAN_ELIMINATE): Rely on FRAME_POINTER_REQUIRED to check for
large MIPS16 frames.
* config/mips/mips.c (mips_frame_pointer_required): New function.
gcc/testsuite/
* gcc.target/mips/save-restore-3.c: Don't clobber $17.
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h 2007-10-18 11:06:46.000000000 +0100
+++ gcc/config/mips/mips-protos.h 2007-10-18 11:07:06.000000000 +0100
@@ -255,6 +255,7 @@ extern void mips_finish_declare_object (
extern bool mips_small_data_pattern_p (rtx);
extern rtx mips_rewrite_small_data (rtx);
+extern bool mips_frame_pointer_required (void);
extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT);
extern HOST_WIDE_INT mips_initial_elimination_offset (int, int);
extern rtx mips_return_addr (int, rtx);
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h 2007-10-18 11:07:05.000000000 +0100
+++ gcc/config/mips/mips.h 2007-10-18 11:07:06.000000000 +0100
@@ -1585,11 +1585,7 @@ #define FRAME_POINTER_REGNUM 78
#define HARD_FRAME_POINTER_REGNUM \
(TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30)
-/* Value should be nonzero if functions must have frame pointers.
- Zero means the frame pointer need not be set up (and parms
- may be accessed via the stack pointer) in functions that seem suitable.
- This is computed in `reload', in reload1.c. */
-#define FRAME_POINTER_REQUIRED (current_function_calls_alloca)
+#define FRAME_POINTER_REQUIRED (mips_frame_pointer_required ())
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2)
@@ -1916,18 +1912,10 @@ #define ELIMINABLE_REGS \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
-/* We can always eliminate to the hard frame pointer. We can eliminate
- to the stack pointer unless a frame pointer is needed.
-
- In mips16 mode, we need a frame pointer for a large frame; otherwise,
- reload may be unable to compute the address of a local variable,
- since there is no way to add a large constant to the stack pointer
- without using a temporary register. */
-#define CAN_ELIMINATE(FROM, TO) \
- ((TO) == HARD_FRAME_POINTER_REGNUM \
- || ((TO) == STACK_POINTER_REGNUM && !frame_pointer_needed \
- && (!TARGET_MIPS16 \
- || compute_frame_size (get_frame_size ()) < 32768)))
+/* Make sure that we're not trying to eliminate to the wrong hard frame
+ pointer. */
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == HARD_FRAME_POINTER_REGNUM || (TO) == STACK_POINTER_REGNUM)
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
(OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c 2007-10-18 11:07:06.000000000 +0100
+++ gcc/config/mips/mips.c 2007-10-18 11:07:06.000000000 +0100
@@ -8068,6 +8068,30 @@ mips_current_loadgp_style (void)
return TARGET_NEWABI ? LOADGP_NEWABI : LOADGP_OLDABI;
}
+/* Implement FRAME_POINTER_REQUIRED. */
+
+bool
+mips_frame_pointer_required (void)
+{
+ /* If the function contains dynamic stack allocations, we need to
+ use the frame pointer to access the static parts of the frame. */
+ if (current_function_calls_alloca)
+ return true;
+
+ /* In MIPS16 mode, we need a frame pointer for a large frame; otherwise,
+ reload may be unable to compute the address of a local variable,
+ since there is no way to add a large constant to the stack pointer
+ without using a second temporary register. */
+ if (TARGET_MIPS16)
+ {
+ compute_frame_size (get_frame_size ());
+ if (!SMALL_OPERAND (cfun->machine->frame.total_size))
+ return true;
+ }
+
+ return false;
+}
+
/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
pointer or argument pointer. TO is either the stack pointer or
hard frame pointer. */
Index: gcc/testsuite/gcc.target/mips/save-restore-3.c
===================================================================
--- gcc/testsuite/gcc.target/mips/save-restore-3.c 2007-10-18 11:06:46.000000000 +0100
+++ gcc/testsuite/gcc.target/mips/save-restore-3.c 2007-10-18 11:07:06.000000000 +0100
@@ -12,7 +12,7 @@ foo (int *a, int b, int c)
int x[0x4000];
asm volatile ("" ::: "$2", "$3", "$4", "$5", "$6", "$7", "$8",
"$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16",
- "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24",
+ "$18", "$19", "$20", "$21", "$22", "$23", "$24",
"$25", "$30", "memory");
bar (x);
a[b] = 1;