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]

[MIPS 8/30] Fix handling of large MIPS16 frames


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;


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