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] Hookize FRAME_POINTER_REQUIRED


Hello.

This patch turns FRAME_POINTER_REQUIRED macro into a hook.

The patch has been bootstrapped on and regression tested on:
armv5tel-unknown-linux-gnueabi
i86_64-unknown-linux-gnu
mipsel-unknown-linux-gnu
hppa2.0-unknown-linux-gnu
sparc64-unknown-linux-gnu

Regression tested on:
avr-unknown-elf
bfin-unknown-elf
cris-axis-elf
frv-unknown-elf
m32c-unknown-elf
m32r-unknown-elf
mmix-knuth-mmixware
sh-unknown-elf
xtensa

I don't have the opportunity to test this patch on arc, crx, fr30, mcore,
score and vax target.

Ok for mainline?

2008-05-14  Anatoly Sokolov  <aesok@post.ru>

        * target.h (struct gcc_target): Add frame_pointer_required field.
        * target-def.h (TARGET_FRAME_POINTER_REQUIRED): New.
        (TARGET_INITIALIZER): Use TARGET_FRAME_POINTER_REQUIRED.
        * ira.c (setup_eliminable_regset): Use frame_pointer_required target
        hook.
        * reload1.c (update_eliminables): (Ditto.).
        * gcc/system.h (FRAME_POINTER_REQUIRED): Poison.
        * doc/tm.texi (FRAME_POINTER_REQUIRED): Revise documentation.
        (INITIAL_FRAME_POINTER_OFFSET): (Ditto.).

        * config/arc/arc.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/arc/arc.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (arc_frame_pointer_required): New function.

        * config/arm/arm.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/arm/arm.c (TARGET_FRAME_POINTER_REQUIRED): Define.
        (arm_frame_pointer_required): New function.

        * config/avr/avr.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/avr/avr.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (avr_frame_pointer_required_p): Declare as static.
        * config/avr/avr-protos.h (avr_frame_pointer_required_p): Remove.

        * config/bfin/bfin.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/bfin/bfin.c (TARGET_FRAME_POINTER_REQUIRED): Define.
        (bfin_frame_pointer_required): Make as static, change return type
        to bool.
        * config/bfin/bfin-protos.h (bfin_frame_pointer_required): Remove.

        * config/cris/cris.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/cris/cris.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (cris_frame_pointer_required): New function.
        
        * config/crx/crx.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/crx/crx.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (crx_frame_pointer_required): New function.

        * config/fr30/fr30.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/fr30/fr30.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (fr30_frame_pointer_required): New function.
        
        * config/frv/frv.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/frv/frv.c (TARGET_FRAME_POINTER_REQUIRED): Define.
        (frv_frame_pointer_required): Make as static, change return type
        to bool.
        * config/bfin/bfin-protos.h (frv_frame_pointer_required): Remove.

        * config/i386/i386.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/i386/i386.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (ix86_frame_pointer_required): Make as static, change return type to
        bool.
        * config/i386/i386-protos.h (ix86_frame_pointer_required): Remove.

        * config/m32c/m32c.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/m32c/m32c.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.

        * config/m32r/m32r.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/m32r/m32r.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (m32r_frame_pointer_required): New function.

        * config/mcore/mcore.h (CAN_ELIMINATE): Redefine.
        * config/mcore/mcore.c (mcore_can_eliminate): New function.
        * config/mcore/mcore-protos.h (mcore_can_eliminate): Declare.

        * config/mips/mips.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/mips/mips.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (mips_frame_pointer_required): Make as static.
        * config/mips/mips-protos.h (mips_frame_pointer_required): Remove.
        
        * config/mmix/mmix.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/mmix/mmix.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (mmix_frame_pointer_required): Mew function.

        * config/pa/pa.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/pa/pa.c (TARGET_FRAME_POINTER_REQUIRED): Define.
        (pa_frame_pointer_required): New function.

        * config/score/score.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/score/score.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (score_frame_pointer_required): New function.   

        * config/sh/sh.h (CAN_ELIMINATE): Redefine.
        * config/sh/sh.c (sh_can_eliminate): New function.
        * config/sh/sh-protos.h (sh_can_eliminate): Declare.

        * config/sparc/sparc.h (FRAME_POINTER_REQUIRED): Remove macro.
        (CAN_ELIMINATE): Redefine.
        * config/sparc/sparc.c (TARGET_FRAME_POINTER_REQUIRED): Define macro.
        (sparc_frame_pointer_required): New function.
        (sparc_can_eliminate): New function.
        * config/sparc/sparc-protos.h (sparc_can_eliminate): Declare.

        * config/vax/vax.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/vax/vax.c (TARGET_FRAME_POINTER_REQUIRED): Define.

        * config/xtensa/xtensa.h (FRAME_POINTER_REQUIRED): Remove macro.
        * config/xtensa/xtensa.c (TARGET_FRAME_POINTER_REQUIRED): Define.
        (xtensa_frame_pointer_required): Make as static, change return type
        to bool.
        * config/xtensa/xtensa-protos.h (xtensa_frame_pointer_required):
        Remove.


Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     (revision 148460)
+++ gcc/doc/tm.texi     (working copy)
@@ -3737,12 +3737,12 @@
 @c prevent bad page break with this line
 This is about eliminating the frame pointer and arg pointer.
 
-@defmac FRAME_POINTER_REQUIRED
-A C expression which is @code{true} if a function must have and use a frame
-pointer.  This expression is evaluated  in the reload pass.  If its value is
-@code{true} the function will have a frame pointer.
+@deftypefn {Target Hook} bool TARGET_FRAME_POINTER_REQUIRED (void)
+This target hook should return @code{true} if a function must have and use
+a frame pointer.  This target hook is called in the reload pass.  If its return
+value is @code{true} the function will have a frame pointer.
 
-The expression can in principle examine the current function and decide
+This target hook can in principle examine the current function and decide
 according to the facts, but on most machines the constant @code{false} or the
 constant @code{true} suffices.  Use @code{false} when the machine allows code
 to be generated with no frame pointer, and doing so saves some time or space.
@@ -3752,15 +3752,15 @@
 In certain cases, the compiler does not know how to produce valid code
 without a frame pointer.  The compiler recognizes those cases and
 automatically gives the function a frame pointer regardless of what
-@code{FRAME_POINTER_REQUIRED} says.  You don't need to worry about
+@code{TARGET_FRAME_POINTER_REQUIRED} returns.  You don't need to worry about
 them.
 
 In a function that does not require a frame pointer, the frame pointer
 register can be allocated for ordinary usage, unless you mark it as a
 fixed register.  See @code{FIXED_REGISTERS} for more information.
 
-Default value is @code{false}.
-@end defmac
+Default return value is @code{false}.
+@end deftypefn
 
 @findex get_frame_size
 @defmac INITIAL_FRAME_POINTER_OFFSET (@var{depth-var})
@@ -3772,7 +3772,7 @@
 
 If @code{ELIMINABLE_REGS} is defined, this macro will be not be used and
 need not be defined.  Otherwise, it must be defined even if
-@code{FRAME_POINTER_REQUIRED} is defined to always be true; in that
+@code{TARGET_FRAME_POINTER_REQUIRED} is always return true; in that
 case, you may set @var{depth-var} to anything.
 @end defmac
 
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h      (revision 148460)
+++ gcc/defaults.h      (working copy)
@@ -1140,8 +1140,4 @@
 #define GO_IF_MODE_DEPENDENT_ADDRESS(X, WIN)
 #endif
 
-#ifndef FRAME_POINTER_REQUIRED
-#define FRAME_POINTER_REQUIRED false
-#endif
-
 #endif  /* ! GCC_DEFAULTS_H */
Index: gcc/target.h
===================================================================
--- gcc/target.h        (revision 148460)
+++ gcc/target.h        (working copy)
@@ -960,6 +960,9 @@
   /* Return the smallest number of different values for which it is best to
      use a jump-table instead of a tree of conditional branches.  */
   unsigned int (* case_values_threshold) (void);
+  
+  /* Retutn true if a function must have and use a frame pointer.  */
+  bool (* frame_pointer_required) (void);
 
   /* Functions specific to the C family of frontends.  */
   struct c {
Index: gcc/ira.c
===================================================================
--- gcc/ira.c   (revision 148460)
+++ gcc/ira.c   (working copy)
@@ -1411,7 +1411,7 @@
        || (cfun->calls_alloca && EXIT_IGNORE_STACK)
        || crtl->accesses_prior_frames
        || crtl->stack_realign_needed
-       || FRAME_POINTER_REQUIRED);
+       || targetm.frame_pointer_required ());
 
   frame_pointer_needed = need_fp;
 
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h    (revision 148460)
+++ gcc/target-def.h    (working copy)
@@ -666,6 +666,10 @@
 #define TARGET_CASE_VALUES_THRESHOLD default_case_values_threshold
 #endif
 
+#ifndef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_false
+#endif
+
 /* C specific.  */
 #ifndef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX default_mode_for_suffix
@@ -938,6 +942,7 @@
   TARGET_INSTANTIATE_DECLS,                    \
   TARGET_HARD_REGNO_SCRATCH_OK,                        \
   TARGET_CASE_VALUES_THRESHOLD,                        \
+  TARGET_FRAME_POINTER_REQUIRED,               \
   TARGET_C,                                    \
   TARGET_CXX,                                  \
   TARGET_EMUTLS,                               \
Index: gcc/system.h
===================================================================
--- gcc/system.h        (revision 148460)
+++ gcc/system.h        (working copy)
@@ -682,7 +682,7 @@
        MUST_PASS_IN_STACK FUNCTION_ARG_PASS_BY_REFERENCE               \
         VECTOR_MODE_SUPPORTED_P TARGET_SUPPORTS_HIDDEN                         \
        FUNCTION_ARG_PARTIAL_NREGS ASM_OUTPUT_DWARF_DTPREL              \
-       ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS
+       ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS FRAME_POINTER_REQUIRED
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h        (revision 148460)
+++ gcc/config/frv/frv.h        (working copy)
@@ -1564,26 +1564,6 @@
 
 /* Eliminating the Frame Pointer and the Arg Pointer.  */
 
-/* A C expression which is nonzero if a function must have and use a frame
-   pointer.  This expression is evaluated in the reload pass.  If its value is
-   nonzero the function will have a frame pointer.
-
-   The expression can in principle examine the current function and decide
-   according to the facts, but on most machines the constant 0 or the constant
-   1 suffices.  Use 0 when the machine allows code to be generated with no
-   frame pointer, and doing so saves some time or space.  Use 1 when there is
-   no possible advantage to avoiding a frame pointer.
-
-   In certain cases, the compiler does not know how to produce valid code
-   without a frame pointer.  The compiler recognizes those cases and
-   automatically gives the function a frame pointer regardless of what
-   `FRAME_POINTER_REQUIRED' says.  You don't need to worry about them.
-
-   In a function that does not require a frame pointer, the frame pointer
-   register can be allocated for ordinary usage, unless you mark it as a fixed
-   register.  See `FIXED_REGISTERS' for more information.  */
-#define FRAME_POINTER_REQUIRED frv_frame_pointer_required ()
-
 /* If defined, this macro specifies a table of register pairs used to eliminate
    unneeded registers that point into the stack frame.  If it is not defined,
    the only elimination attempted by the compiler is to replace references to
Index: gcc/config/frv/frv-protos.h
===================================================================
--- gcc/config/frv/frv-protos.h	(revision 148460)
+++ gcc/config/frv/frv-protos.h	(working copy)
@@ -43,7 +43,6 @@
 extern void frv_conditional_register_usage     (void);
 extern frv_stack_t *frv_stack_info             (void);
 extern void frv_debug_stack                    (frv_stack_t *);
-extern int frv_frame_pointer_required          (void);
 extern int frv_initial_elimination_offset      (int, int);
 
 #ifdef RTX_CODE
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c        (revision 148460)
+++ gcc/config/frv/frv.c        (working copy)
@@ -381,6 +381,7 @@
 static bool frv_secondary_reload                (bool, rtx, enum reg_class,
                                                 enum machine_mode,
                                                 secondary_reload_info *);
+static bool frv_frame_pointer_required         (void);
 
 /* Allow us to easily change the default for -malloc-cc.  */
 #ifndef DEFAULT_NO_ALLOC_CC
@@ -471,6 +472,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P frv_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED frv_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #define FRV_SYMBOL_REF_TLS_P(RTX) \
@@ -2105,28 +2109,10 @@
 }
 
 
-/* A C expression which is nonzero if a function must have and use a frame
-   pointer.  This expression is evaluated in the reload pass.  If its value is
-   nonzero the function will have a frame pointer.
 
-   The expression can in principle examine the current function and decide
-   according to the facts, but on most machines the constant 0 or the constant
-   1 suffices.  Use 0 when the machine allows code to be generated with no
-   frame pointer, and doing so saves some time or space.  Use 1 when there is
-   no possible advantage to avoiding a frame pointer.
-
-   In certain cases, the compiler does not know how to produce valid code
-   without a frame pointer.  The compiler recognizes those cases and
-   automatically gives the function a frame pointer regardless of what
-   `FRAME_POINTER_REQUIRED' says.  You don't need to worry about them.
-
-   In a function that does not require a frame pointer, the frame pointer
-   register can be allocated for ordinary usage, unless you mark it as a fixed
-   register.  See `FIXED_REGISTERS' for more information.  */
-
 /* On frv, create a frame whenever we need to create stack.  */
 
-int
+static bool
 frv_frame_pointer_required (void)
 {
   /* If we forgoing the usual linkage requirements, we only need
@@ -2135,27 +2121,27 @@
     return !current_function_sp_is_unchanging;
 
   if (! current_function_is_leaf)
-    return TRUE;
+    return true;
 
   if (get_frame_size () != 0)
-    return TRUE;
+    return true;
 
   if (cfun->stdarg)
-    return TRUE;
+    return true;
 
   if (!current_function_sp_is_unchanging)
-    return TRUE;
+    return true;
 
   if (!TARGET_FDPIC && flag_pic && crtl->uses_pic_offset_table)
-    return TRUE;
+    return true;
 
   if (profile_flag)
-    return TRUE;
+    return true;
 
   if (cfun->machine->frame_needed)
-    return TRUE;
+    return true;
 
-  return FALSE;
+  return false;
 }
 
 
Index: gcc/config/m32c/m32c.c
===================================================================
--- gcc/config/m32c/m32c.c      (revision 148460)
+++ gcc/config/m32c/m32c.c      (working copy)
@@ -4259,6 +4259,13 @@
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
 
+/* If the frame pointer isn't used, we detect it manually.  But the
+   stack pointer doesn't have as flexible addressing as the frame
+   pointer, so we always assume we have it.  */
+
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true
+
 /* The Global `targetm' Variable. */
 
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/m32c/m32c.h
===================================================================
--- gcc/config/m32c/m32c.h      (revision 148460)
+++ gcc/config/m32c/m32c.h      (working copy)
@@ -488,11 +488,6 @@
 
 /* Eliminating Frame Pointer and Arg Pointer */
 
-/* If the frame pointer isn't used, we detect it manually.  But the
-   stack pointer doesn't have as flexible addressing as the frame
-   pointer, so we always assume we have it.  */
-#define FRAME_POINTER_REQUIRED 1
-
 #define ELIMINABLE_REGS \
   {{AP_REGNO, SP_REGNO}, \
    {AP_REGNO, FB_REGNO}, \
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h     (revision 148460)
+++ gcc/config/sparc/sparc-protos.h     (working copy)
@@ -50,6 +50,7 @@
 extern void sparc_profile_hook (int);
 extern void sparc_override_options (void);
 extern void sparc_output_scratch_registers (FILE *);
+extern bool sparc_can_eliminate (int, int);
 
 #ifdef RTX_CODE
 extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx);
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c    (revision 148460)
+++ gcc/config/sparc/sparc.c    (working copy)
@@ -417,6 +417,7 @@
 static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
 static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static void sparc_file_end (void);
+static bool sparc_frame_pointer_required (void);
 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
 static const char *sparc_mangle_type (const_tree);
 #endif
@@ -584,6 +585,9 @@
 #undef TARGET_ASM_FILE_END
 #define TARGET_ASM_FILE_END sparc_file_end
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED sparc_frame_pointer_required
+
 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE sparc_mangle_type
@@ -9140,4 +9144,24 @@
   emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+sparc_frame_pointer_required (void)
+{
+  return !(leaf_function_p () && only_leaf_regs_used ());
+}
+
+/* The way this is structured, we can't eliminate SFP in favor of SP
+   if the frame pointer is required: we want to use the SFP->HFP elimination
+   in that case.  But the test in update_eliminables doesn't know we are
+   assuming below that we only do the former elimination.  */
+
+bool
+sparc_can_eliminate (int from ATTRIBUTE_UNUSED, int to)
+{
+  return (to == HARD_FRAME_POINTER_REGNUM 
+          || !targetm.frame_pointer_required ());
+}
+
 #include "gt-sparc.h"
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h    (revision 148460)
+++ gcc/config/sparc/sparc.h    (working copy)
@@ -967,13 +967,6 @@
       }                                                                         \
   } while (0)
 
-/* 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.
-   Used in flow.c, global.c, ra.c and reload1.c.  */
-#define FRAME_POINTER_REQUIRED	\
-  (! (leaf_function_p () && only_leaf_regs_used ()))
-
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
 
@@ -1390,8 +1383,7 @@
    if the frame pointer is required: we want to use the SFP->HFP elimination
    in that case.  But the test in update_eliminables doesn't know we are
    assuming below that we only do the former elimination.  */
-#define CAN_ELIMINATE(FROM, TO) \
-  ((TO) == HARD_FRAME_POINTER_REGNUM || !FRAME_POINTER_REQUIRED)
+#define CAN_ELIMINATE(FROM, TO) sparc_can_eliminate((FROM), (TO))
 
 /* We always pretend that this is a leaf function because if it's not,
    there's no point in trying to eliminate the frame pointer.  If it
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c      (revision 148460)
+++ gcc/config/m32r/m32r.c      (working copy)
@@ -87,6 +87,7 @@
                                    const_tree, bool);
 static int m32r_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                   tree, bool);
+static bool m32r_frame_pointer_required (void);
 
 /* Initialize the GCC target structure.  */
 #undef  TARGET_ATTRIBUTE_TABLE
@@ -140,6 +141,8 @@
 #define TARGET_PASS_BY_REFERENCE m32r_pass_by_reference
 #undef  TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES m32r_arg_partial_bytes
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED m32r_frame_pointer_required
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -2615,3 +2618,11 @@
 
   return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
 }
+
+/* Worker function for TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+m32r_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca);
+}
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h      (revision 148460)
+++ gcc/config/m32r/m32r.h      (working copy)
@@ -770,11 +770,6 @@
 
 /* Eliminating the frame and arg pointers.  */
 
-/* A C expression which is nonzero if a function must have and use a
-   frame pointer.  This expression is evaluated in the reload pass.
-   If its value is nonzero the function will have a frame pointer.  */
-#define FRAME_POINTER_REQUIRED cfun->calls_alloca
-
 #if 0
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h      (revision 148460)
+++ gcc/config/i386/i386.h      (working copy)
@@ -1152,12 +1152,6 @@
 #define FIRST_REX_SSE_REG  (LAST_REX_INT_REG + 1)
 #define LAST_REX_SSE_REG   (FIRST_REX_SSE_REG + 7)
 
-/* 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  ix86_frame_pointer_required ()
-
 /* Override this in other tm.h files to cope with various OS lossage
    requiring a frame pointer.  */
 #ifndef SUBTARGET_FRAME_POINTER_REQUIRED
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h       (revision 148460)
+++ gcc/config/i386/i386-protos.h       (working copy)
@@ -24,7 +24,6 @@
 extern void optimization_options (int, int);
 
 extern int ix86_can_use_return_insn_p (void);
-extern int ix86_frame_pointer_required (void);
 extern void ix86_setup_frame_addresses (void);
 
 extern void ix86_file_end (void);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 148460)
+++ gcc/config/i386/i386.c      (working copy)
@@ -7422,18 +7422,18 @@
    Zero means the frame pointer need not be set up (and parms may
    be accessed via the stack pointer) in functions that seem suitable.  */
 
-int
+static bool
 ix86_frame_pointer_required (void)
 {
   /* If we accessed previous frames, then the generated code expects
      to be able to access the saved ebp value in our frame.  */
   if (cfun->machine->accesses_prev_frame)
-    return 1;
+    return true;
 
   /* Several x86 os'es need a frame pointer for other reasons,
      usually pertaining to setjmp.  */
   if (SUBTARGET_FRAME_POINTER_REQUIRED)
-    return 1;
+    return true;
 
   /* In override_options, TARGET_OMIT_LEAF_FRAME_POINTER turns off
      the frame pointer by default.  Turn it back on now if we've not
@@ -7441,12 +7441,12 @@
   if (TARGET_OMIT_LEAF_FRAME_POINTER
       && (!current_function_is_leaf
          || ix86_current_function_calls_tls_descriptor))
-    return 1;
+    return true;
 
   if (crtl->profile)
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
 /* Record that the current function accesses previous call frames.  */
@@ -30719,6 +30719,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-i386.h"
Index: gcc/config/sh/sh-protos.h
===================================================================
--- gcc/config/sh/sh-protos.h   (revision 148460)
+++ gcc/config/sh/sh-protos.h   (working copy)
@@ -149,6 +149,7 @@
 extern int sh_register_move_cost
   (enum machine_mode mode, enum reg_class, enum reg_class);
 extern int check_use_sfunc_addr (rtx, rtx);
+extern bool sh_can_eliminate (int, int);
 
 #ifdef HARD_CONST
 extern void fpscr_set_from_mem (int, HARD_REG_SET);
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c  (revision 148460)
+++ gcc/config/sh/sh.c  (working copy)
@@ -11930,4 +11930,13 @@
 
 enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
 
+/* Implement CAN_ELIMINATE.  */
+
+bool
+sh_can_eliminate (int from, int to ATTRIBUTE_UNUSED)
+{
+  return !(from == HARD_FRAME_POINTER_REGNUM
+           && targetm.frame_pointer_required ());
+}
+
 #include "gt-sh.h"
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h  (revision 148460)
+++ gcc/config/sh/sh.h  (working copy)
@@ -1033,8 +1033,7 @@
 
 /* Given FROM and TO register numbers, say whether this elimination
    is allowed.  */
-#define CAN_ELIMINATE(FROM, TO) \
-  (!((FROM) == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
+#define CAN_ELIMINATE(FROM, TO) sh_can_eliminate((FROM), (TO))
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
Index: gcc/config/avr/avr-protos.h
===================================================================
--- gcc/config/avr/avr-protos.h	(revision 148460)
+++ gcc/config/avr/avr-protos.h	(working copy)
@@ -30,7 +30,6 @@
 extern enum reg_class class_likely_spilled_p (int c);
 extern enum reg_class avr_regno_reg_class (int r);
 extern enum reg_class avr_reg_class_from_letter (int c);
-extern bool avr_frame_pointer_required_p (void);
 extern void asm_globalize_label (FILE *file, const char *name);
 extern void avr_asm_declare_function_name (FILE *, const char *, tree);
 extern void order_regs_for_local_alloc (void);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c        (revision 148460)
+++ gcc/config/avr/avr.c        (working copy)
@@ -90,6 +90,7 @@
 static rtx avr_builtin_setjmp_frame_value (void);
 static bool avr_hard_regno_scratch_ok (unsigned int);
 static unsigned int avr_case_values_threshold (void);
+static bool avr_frame_pointer_required_p (void);
 
 /* Allocate registers from r25 to r8 for parameters for function calls.  */
 #define FIRST_CUM_REG 26
@@ -371,6 +372,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P avr_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 void
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h        (revision 148460)
+++ gcc/config/avr/avr.h        (working copy)
@@ -350,8 +350,6 @@
 
 #define STATIC_CHAIN_REGNUM 2
 
-#define FRAME_POINTER_REQUIRED avr_frame_pointer_required_p()
-
 /* Offset from the frame pointer register value to the top of the stack.  */
 #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
 
Index: gcc/config/crx/crx.h
===================================================================
--- gcc/config/crx/crx.h        (revision 148460)
+++ gcc/config/crx/crx.h        (working copy)
@@ -291,8 +291,6 @@
 
 #define FIRST_PARM_OFFSET(FNDECL)  0
 
-#define FRAME_POINTER_REQUIRED (cfun->calls_alloca)
-
 #define ELIMINABLE_REGS \
   { \
     { ARG_POINTER_REGNUM,   STACK_POINTER_REGNUM}, \
Index: gcc/config/crx/crx.c
===================================================================
--- gcc/config/crx/crx.c        (revision 148460)
+++ gcc/config/crx/crx.c        (working copy)
@@ -135,6 +135,7 @@
 static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
 static int crx_address_cost (rtx, bool);
 static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool crx_frame_pointer_required (void);
 
 /*****************************************************************************/
 /* RTL VALIDITY                                                                     */
@@ -156,6 +157,9 @@
 #undef	TARGET_RETURN_IN_MEMORY
 #define        TARGET_RETURN_IN_MEMORY         crx_return_in_memory
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED   crx_frame_pointer_required
+
 /*****************************************************************************/
 /* RELATIVE COSTS OF OPERATIONS                                                     */
 /*****************************************************************************/
@@ -1436,3 +1440,11 @@
   else
     emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
 }
+
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+crx_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca);
+}
Index: gcc/config/xtensa/xtensa.c
===================================================================
--- gcc/config/xtensa/xtensa.c  (revision 148460)
+++ gcc/config/xtensa/xtensa.c  (working copy)
@@ -145,6 +145,7 @@
 static tree xtensa_fold_builtin (tree, tree, bool);
 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 static void xtensa_va_start (tree, rtx);
+static bool xtensa_frame_pointer_required (void);
 
 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
   REG_ALLOC_ORDER;
@@ -227,6 +228,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    xtensa_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED xtensa_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 
@@ -1534,7 +1538,7 @@
 void
 xtensa_setup_frame_addresses (void)
 {
-  /* Set flag to cause FRAME_POINTER_REQUIRED to be set.  */
+  /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true.  */
   cfun->machine->accesses_prev_frame = 1;
 
   emit_library_call
@@ -2495,7 +2499,7 @@
 }
 
 
-int
+bool
 xtensa_frame_pointer_required (void)
 {
   /* The code to expand builtin_frame_addr and builtin_return_addr
@@ -2504,9 +2508,9 @@
      This function is derived from the i386 code.  */
 
   if (cfun->machine->accesses_prev_frame)
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
 
Index: gcc/config/xtensa/xtensa.h
===================================================================
--- gcc/config/xtensa/xtensa.h  (revision 148460)
+++ gcc/config/xtensa/xtensa.h  (working copy)
@@ -380,12 +380,6 @@
    either the stack pointer or the hard frame pointer.  */
 #define FRAME_POINTER_REGNUM (GP_REG_FIRST + 16)
 
-/* 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 xtensa_frame_pointer_required ()
-
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM (GP_REG_FIRST + 17)
 
Index: gcc/config/xtensa/xtensa-protos.h
===================================================================
--- gcc/config/xtensa/xtensa-protos.h   (revision 148460)
+++ gcc/config/xtensa/xtensa-protos.h   (working copy)
@@ -84,7 +84,6 @@
 extern int xtensa_dbx_register_number (int);
 extern void override_options (void);
 extern long compute_frame_size (int);
-extern int xtensa_frame_pointer_required (void);
 extern void xtensa_expand_prologue (void);
 extern void order_regs_for_local_alloc (void);
 extern void xtensa_trampoline_template (FILE *);
Index: gcc/config/fr30/fr30.h
===================================================================
--- gcc/config/fr30/fr30.h      (revision 148460)
+++ gcc/config/fr30/fr30.h      (working copy)
@@ -519,28 +519,6 @@
 /*}}}*/ 
 /*{{{  Eliminating the Frame Pointer and the Arg Pointer.  */ 
 
-/* A C expression which is nonzero if a function must have and use a frame
-   pointer.  This expression is evaluated in the reload pass.  If its value is
-   nonzero the function will have a frame pointer.
-
-   The expression can in principle examine the current function and decide
-   according to the facts, but on most machines the constant 0 or the constant
-   1 suffices.  Use 0 when the machine allows code to be generated with no
-   frame pointer, and doing so saves some time or space.  Use 1 when there is
-   no possible advantage to avoiding a frame pointer.
-
-   In certain cases, the compiler does not know how to produce valid code
-   without a frame pointer.  The compiler recognizes those cases and
-   automatically gives the function a frame pointer regardless of what
-   `FRAME_POINTER_REQUIRED' says.  You don't need to worry about them.
-
-   In a function that does not require a frame pointer, the frame pointer
-   register can be allocated for ordinary usage, unless you mark it as a fixed
-   register.  See `FIXED_REGISTERS' for more information.  */
-/* #define FRAME_POINTER_REQUIRED 0 */
-#define FRAME_POINTER_REQUIRED \
-     (flag_omit_frame_pointer == 0 || crtl->args.pretend_args_size > 0)
-
 /* If defined, this macro specifies a table of register pairs used to eliminate
    unneeded registers that point into the stack frame.  If it is not defined,
    the only elimination attempted by the compiler is to replace references to
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c      (revision 148460)
+++ gcc/config/fr30/fr30.c      (working copy)
@@ -119,8 +119,8 @@
 static bool fr30_must_pass_in_stack (enum machine_mode, const_tree);
 static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                   tree, bool);
+static bool fr30_frame_pointer_required (void);
 
-
 #define FRAME_POINTER_MASK     (1 << (FRAME_POINTER_REGNUM))
 #define RETURN_POINTER_MASK    (1 << (RETURN_POINTER_REGNUM))
 
@@ -158,6 +158,9 @@
 #undef  TARGET_MUST_PASS_IN_STACK
 #define TARGET_MUST_PASS_IN_STACK fr30_must_pass_in_stack
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED fr30_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Returns the number of bytes offset between FROM_REG and TO_REG
@@ -899,6 +902,14 @@
   return val;
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+fr30_frame_pointer_required (void)
+{
+  return (flag_omit_frame_pointer == 0 || crtl->args.pretend_args_size > 0);
+}
+
 /*}}}*/
 /* Local Variables: */
 /* folded-file: t   */
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c      (revision 148460)
+++ gcc/config/cris/cris.c      (working copy)
@@ -122,6 +122,8 @@
 
 static bool cris_handle_option (size_t, const char *, int);
 
+static bool cris_frame_pointer_required (void);
+
 /* This is the parsed result of the "-max-stack-stackframe=" option.  If
    it (still) is zero, then there was no such option given.  */
 int cris_max_stackframe = 0;
@@ -180,6 +182,8 @@
 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | CRIS_SUBTARGET_DEFAULT)
 #undef TARGET_HANDLE_OPTION
 #define TARGET_HANDLE_OPTION cris_handle_option
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -3814,6 +3818,18 @@
                    clobbers);
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.
+
+   Really only needed if the stack frame has variable length (alloca
+   or variable sized local arguments (GNU C extension).  See PR39499 and
+   PR38609 for the reason this isn't just 0.  */
+
+bool
+cris_frame_pointer_required (void)
+{
+  return !current_function_sp_is_unchanging;
+}
+
 #if 0
 /* Various small functions to replace macros.  Only called from a
    debugger.  They might collide with gcc functions or system functions,
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h      (revision 148460)
+++ gcc/config/cris/cris.h      (working copy)
@@ -850,11 +850,6 @@
 
 /* Node: Elimination */
 
-/* Really only needed if the stack frame has variable length (alloca
-   or variable sized local arguments (GNU C extension).  See PR39499 and
-   PR38609 for the reason this isn't just 0.  */
-#define FRAME_POINTER_REQUIRED (!current_function_sp_is_unchanging)
-
 #define ELIMINABLE_REGS                                \
  {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},  \
   {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},  \
Index: gcc/config/arc/arc.c
===================================================================
--- gcc/config/arc/arc.c        (revision 148460)
+++ gcc/config/arc/arc.c        (working copy)
@@ -94,6 +94,7 @@
 static bool arc_return_in_memory (const_tree, const_tree);
 static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
                                   const_tree, bool);
+static bool arc_frame_pointer_required (void);
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
@@ -144,6 +145,9 @@
 #undef TARGET_EXPAND_BUILTIN_VA_START
 #define TARGET_EXPAND_BUILTIN_VA_START arc_va_start
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -2342,3 +2346,11 @@
 
   return size > 8;
 }
+
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+arc_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca);
+}
Index: gcc/config/arc/arc.h
===================================================================
--- gcc/config/arc/arc.h        (revision 148460)
+++ gcc/config/arc/arc.h        (working copy)
@@ -516,12 +516,6 @@
    not be a register used by the prologue.  */
 #define STATIC_CHAIN_REGNUM 24
 
-/* A C expression which is nonzero if a function must have and use a
-   frame pointer.  This expression is evaluated in the reload pass.
-   If its value is nonzero the function will have a frame pointer.  */
-#define FRAME_POINTER_REQUIRED \
-(cfun->calls_alloca)
-
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.  */
 #define INITIAL_FRAME_POINTER_OFFSET(VAR) \
Index: gcc/config/mcore/mcore-protos.h
===================================================================
--- gcc/config/mcore/mcore-protos.h     (revision 148460)
+++ gcc/config/mcore/mcore-protos.h     (working copy)
@@ -33,6 +33,7 @@
 extern int          mcore_dllexport_name_p             (const char *);
 extern int          mcore_dllimport_name_p             (const char *);
 extern int          mcore_naked_function_p             (void);
+extern bool         mcore_can_eliminate                 (int, int);
 
 #ifdef TREE_CODE
 #ifdef HAVE_MACHINE_MODES
Index: gcc/config/mcore/mcore.c
===================================================================
--- gcc/config/mcore/mcore.c    (revision 148460)
+++ gcc/config/mcore/mcore.c    (working copy)
@@ -3105,3 +3105,12 @@
   const HOST_WIDE_INT size = int_size_in_bytes (type);
   return (size == -1 || size > 2 * UNITS_PER_WORD);
 }
+
+/* Worker function for CAN_ELIMINATE.  */
+
+bool
+mcore_can_eliminate (int from, int to ATTRIBUTE_UNUSED)
+{
+  return !(from == FRAME_POINTER_REGNUM 
+           && targetm.frame_pointer_required ()));
+}
\ No newline at end of file
Index: gcc/config/mcore/mcore.h
===================================================================
--- gcc/config/mcore/mcore.h    (revision 148460)
+++ gcc/config/mcore/mcore.h    (working copy)
@@ -327,8 +327,10 @@
 
 /* Given FROM and TO register numbers, say whether this elimination
    is allowed.  */
+#define CAN_ELIMINATE(FROM, TO) mcore_can_eliminate((FROM), (TO))
 #define CAN_ELIMINATE(FROM, TO) \
-  (!((FROM) == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
+  (!((FROM) == FRAME_POINTER_REGNUM 
+     && targetm.frame_pointer_required ()))
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c    (revision 148460)
+++ gcc/config/score/score.c    (working copy)
@@ -119,6 +119,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    score_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED  score_frame_pointer_required
+
 struct extern_list *extern_head = 0;
 
 /* default 0 = NO_REGS  */
@@ -1186,4 +1189,12 @@
   return false;
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+static bool
+score_frame_pointer_required (void)
+{
+  return (cfun->calls_alloca);
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/score/score.h
===================================================================
--- gcc/config/score/score.h    (revision 148460)
+++ gcc/config/score/score.h    (working copy)
@@ -557,11 +557,6 @@
 #define STATIC_CHAIN_REGNUM             23
 
 /* Elimination Frame Pointer and Arg Pointer  */
-/* 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          cfun->calls_alloca
 
 #define ELIMINABLE_REGS                                \
   {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},        \
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c        (revision 148460)
+++ gcc/config/arm/arm.c        (working copy)
@@ -200,6 +200,7 @@
 static int arm_issue_rate (void);
 static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static bool arm_allocate_stack_slots_for_args (void);
+static bool arm_frame_pointer_required (void);
 
 
 /* Initialize the GCC target structure.  */
@@ -407,6 +408,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    arm_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED arm_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -19782,4 +19786,14 @@
     flag_section_anchors = 2;
 }
 
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
+
+bool
+arm_frame_pointer_required (void)
+{
+  return (cfun->has_nonlocal_label
+          || SUBTARGET_FRAME_POINTER_REQUIRED
+          || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()));
+}
+
 #include "gt-arm.h"
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h        (revision 148460)
+++ gcc/config/arm/arm.h        (working copy)
@@ -1022,11 +1022,6 @@
 #define SUBTARGET_FRAME_POINTER_REQUIRED 0
 #endif
 
-#define FRAME_POINTER_REQUIRED                                 \
-  (cfun->has_nonlocal_label                            \
-   || SUBTARGET_FRAME_POINTER_REQUIRED                         \
-   || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
-
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
Index: gcc/config/pa/pa.c
===================================================================
--- gcc/config/pa/pa.c  (revision 148460)
+++ gcc/config/pa/pa.c  (working copy)
@@ -159,6 +159,7 @@
                                           enum machine_mode,
                                           secondary_reload_info *);
 static void pa_extra_live_on_entry (bitmap);
+static bool pa_frame_pointer_required (void);
 
 /* The following extra sections are only used for SOM.  */
 static GTY(()) section *som_readonly_data_section;
@@ -322,6 +323,9 @@
 #undef TARGET_EXTRA_LIVE_ON_ENTRY
 #define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED pa_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Parse the -mfixed-range= option string.  */
@@ -9708,4 +9712,12 @@
   return true;
 }
 
+/* Return true if functions must have frame pointers.  */
+
+bool
+pa_frame_pointer_required (void)
+{
+  return cfun->calls_alloca;
+}
+
 #include "gt-pa.h"
Index: gcc/config/pa/pa.h
===================================================================
--- gcc/config/pa/pa.h  (revision 148460)
+++ gcc/config/pa/pa.h  (working copy)
@@ -356,10 +356,6 @@
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM 3
 
-/* Value should be nonzero if functions must have frame pointers.  */
-#define FRAME_POINTER_REQUIRED \
-  (cfun->calls_alloca)
-
 /* Don't allow hard registers to be renamed into r2 unless r2
    is already live or already being saved (due to eh).  */
 
Index: gcc/config/mips/mips-protos.h
===================================================================
--- gcc/config/mips/mips-protos.h       (revision 148460)
+++ gcc/config/mips/mips-protos.h       (working copy)
@@ -272,7 +272,6 @@
 
 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 mips_initial_elimination_offset (int, int);
 extern rtx mips_return_addr (int, rtx);
 extern enum mips_loadgp_style mips_current_loadgp_style (void);
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      (revision 148460)
+++ gcc/config/mips/mips.c      (working copy)
@@ -8918,9 +8918,9 @@
   return TARGET_NEWABI ? LOADGP_NEWABI : LOADGP_OLDABI;
 }
 
-/* Implement FRAME_POINTER_REQUIRED.  */
+/* Implement TARGET_FRAME_POINTER_REQUIRED.  */
 
-bool
+static bool
 mips_frame_pointer_required (void)
 {
   /* If the function contains dynamic stack allocations, we need to
@@ -14931,6 +14931,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    mips_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED mips_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-mips.h"
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h      (revision 148460)
+++ gcc/config/mips/mips.h      (working copy)
@@ -1767,8 +1767,6 @@
 #define HARD_FRAME_POINTER_REGNUM \
   (TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30)
 
-#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 + 15)
 
Index: gcc/config/vax/vax.c
===================================================================
--- gcc/config/vax/vax.c        (revision 148460)
+++ gcc/config/vax/vax.c        (working copy)
@@ -98,6 +98,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P vax_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Set global variables as needed for the options enabled.  */
Index: gcc/config/vax/vax.h
===================================================================
--- gcc/config/vax/vax.h        (revision 148460)
+++ gcc/config/vax/vax.h        (working copy)
@@ -175,12 +175,6 @@
 /* Base register for access to local variables of the function.  */
 #define FRAME_POINTER_REGNUM VAX_FP_REGNUM
 
-/* 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 1
-
 /* Offset from the frame pointer register value to the top of stack.  */
 #define FRAME_POINTER_CFA_OFFSET(FNDECL) 0
 
Index: gcc/config/mmix/mmix.h
===================================================================
--- gcc/config/mmix/mmix.h      (revision 148460)
+++ gcc/config/mmix/mmix.h      (working copy)
@@ -585,9 +585,6 @@
 
 
 /* Node: Elimination */
-/* FIXME: Is this requirement built-in?  Anyway, we should try to get rid
-   of it; we can deduce the value.  */
-#define FRAME_POINTER_REQUIRED  cfun->has_nonlocal_label
 
 /* The frame-pointer is stored in a location that either counts to the
    offset of incoming parameters, or that counts to the offset of the
Index: gcc/config/mmix/mmix.c
===================================================================
--- gcc/config/mmix/mmix.c      (revision 148460)
+++ gcc/config/mmix/mmix.c      (working copy)
@@ -137,6 +137,7 @@
 static rtx mmix_struct_value_rtx (tree, int);
 static bool mmix_pass_by_reference (CUMULATIVE_ARGS *,
                                    enum machine_mode, const_tree, bool);
+static bool mmix_frame_pointer_required (void);
 
 /* Target structure macros.  Listed by node.  See `Using and Porting GCC'
    for a general description.  */
@@ -210,6 +211,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    mmix_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED mmix_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Functions that are expansions for target macros.
@@ -2697,6 +2701,17 @@
   return gen_rtx_REG (Pmode, MMIX_STRUCT_VALUE_REGNUM);
 }
 
+/* Worker function for TARGET_FRAME_POINTER_REQUIRED.
+
+   FIXME: Is this requirement built-in?  Anyway, we should try to get rid
+   of it; we can deduce the value.  */
+
+bool
+mmix_frame_pointer_required (void)
+{
+  return (cfun->has_nonlocal_label);
+}
+
 /*
  * Local variables:
  * eval: (c-set-style "gnu")
Index: gcc/config/bfin/bfin-protos.h
===================================================================
--- gcc/config/bfin/bfin-protos.h       (revision 148460)
+++ gcc/config/bfin/bfin-protos.h       (working copy)
@@ -112,7 +112,6 @@
 extern bool bfin_legitimate_constant_p (rtx);
 extern int hard_regno_mode_ok (int, Mmode);
 extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);         
-extern int bfin_frame_pointer_required (void);
 extern HOST_WIDE_INT bfin_initial_elimination_offset (int, int);
 
 extern int effective_address_32bit_p (rtx, Mmode);
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c      (revision 148460)
+++ gcc/config/bfin/bfin.c      (working copy)
@@ -812,20 +812,20 @@
    Zero means the frame pointer need not be set up (and parms may
    be accessed via the stack pointer) in functions that seem suitable.  */
 
-int
+static bool
 bfin_frame_pointer_required (void) 
 {
   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
 
   if (fkind != SUBROUTINE)
-    return 1;
+    return true;
 
   /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
      so we have to override it for non-leaf functions.  */
   if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
-    return 1;
+    return true;
 
-  return 0;
+  return false;
 }
 
 /* Return the number of registers pushed during the prologue.  */
@@ -6339,4 +6339,7 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    bfin_legitimate_address_p
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h      (revision 148460)
+++ gcc/config/bfin/bfin.h      (working copy)
@@ -313,13 +313,6 @@
    found in the variable crtl->outgoing_args_size. */ 
 #define ACCUMULATE_OUTGOING_ARGS 1
 
-/* 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 (bfin_frame_pointer_required ())
-
 /*#define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) for arrays.. */
 
 /* If defined, a C expression to compute the alignment for a local
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c       (revision 148460)
+++ gcc/reload1.c       (working copy)
@@ -3702,7 +3702,8 @@
   struct elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
+    if ((ep->from == HARD_FRAME_POINTER_REGNUM 
+         && targetm.frame_pointer_required ())
 #ifdef ELIMINABLE_REGS
        || ! CAN_ELIMINATE (ep->from, ep->to)
 #endif


Anatoly.


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