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 CAN_ELIMINATE


Hello.

This patch turns CAN_ELIMINATE macro into a hook.

The patch has been bootstrapped on and regression tested on:
x86_64-unknown-linux-gnu
ia64-unknown-linux-gnu
mipsel-unknown-linux-gnu
powerpc-unknown-linux-gnu
sparc64-unknown-linux-gnu

Regression tested on:
fr30-unknown-elf
frv-unknown-elf
m32r-unknown-elf
v850-unknown-elf

I don't have the opportunity to test this patch on alpha-vms, arm,
bfin, crx, h8300, iq2000, m68hc11, m68k, mep, s390, score and
stormy16 targets.

Ok for mainline?

        * hooks.h (hook_bool_const_int_const_int_true): Declare.
        * hooks.c (hook_bool_const_int_const_int_true): New function.
        * target.h (struct gcc_target): Add can_eliminate field.
        * target-def.h (TARGET_CAN_ELIMINATE): Define.
        (TARGET_INITIALIZER): Use TARGET_CAN_ELIMINATE.
        * ira.c (setup_eliminable_regset): Use can_eliminate target hook.
        * reload1.c (update_eliminables, init_elim_table): (Ditto.).
        (elim_table): Revise comment.
        * system.h (CAN_ELIMINATE): Poison.
        * defaults.h (CAN_ELIMINATE): Remove.
        * doc/tm.texi (CAN_ELIMINATE): Revise documentation.
        
        * config/alpha/vms.h (CAN_ELIMINATE): Remove macro.
        * config/alpha/alpha.c (TARGET_CAN_ELIMINATE) [TARGET_ABI_OPEN_VMS]:
        Define macro.
        (alpha_vms_can_eliminate): Declare as static, change return type to
        bool.
        * config/alpha/alpha-protos.h (alpha_vms_can_eliminate): Remove.

        * config/arm/arm.h (CAN_ELIMINATE): Remove macro.
        * config/arm/arm.c (TARGET_CAN_ELIMINATE): Define macro.
        (arm_can_eliminate): New function.

        * config/avr/avr.h (CAN_ELIMINATE): Remove macro.
        * config/avr/avr.c (TARGET_CAN_ELIMINATE): Define macro.
        (avr_can_eliminate): Declare as static.
        * config/avr/avr-protos.h (avr_can_eliminate): Remove.

        * config/bfin/bfin.h (CAN_ELIMINATE): Remove macro.
        * config/bfin/bfin.c (TARGET_CAN_ELIMINATE): Define macro.
        (bfin_can_eliminate): New function.

        * config/crx/crx.h (CAN_ELIMINATE): Remove macro.
        * config/crx/crx.c (TARGET_CAN_ELIMINATE): Define macro.
        (crx_can_eliminate): New function.
        
        * config/fr30/fr30.h (CAN_ELIMINATE): Remove macro.
        * config/fr30/fr30.c (TARGET_CAN_ELIMINATE): Define macro.
        (fr30_can_eliminate): New function.

        * config/frv/frv.h (CAN_ELIMINATE): Remove macro.
        * config/frv/frv.c (TARGET_CAN_ELIMINATE): Define macro.
        (frv_can_eliminate): New function.

        * config/h8300/h8300.h (CAN_ELIMINATE): Remove macro.
        * config/h8300/h8300.c (TARGET_CAN_ELIMINATE): Define macro.
        (h8300_can_eliminate): New function.

        * config/i386/i386.h (CAN_ELIMINATE): Remove macro.
        * config/i386/i386.c (TARGET_CAN_ELIMINATE): Define macro.
        (i386_can_eliminate): Declare as static, change return type to bool.
        * config/i386/i386-protos.h (i386_can_eliminate): Remove.

        * config/ia64/ia64.h (CAN_ELIMINATE): Remove macro.
        * config/ia64/ia64.c (TARGET_CAN_ELIMINATE): Define macro.
        (ia64_can_eliminate): New function.

        * config/iq2000/iq2000.h (CAN_ELIMINATE): Remove macro.
        * config/iq2000/iq2000.c (TARGET_CAN_ELIMINATE): Define macro.
        (iq2000_can_eliminate): New function.

        * config/m32r/m32r.h (CAN_ELIMINATE): Remove macro.
        * config/m32r/m32r.c (TARGET_CAN_ELIMINATE): Define macro.
        (m32r_can_eliminate): New function.

        * config/m68hc11/m68hc11.h (CAN_ELIMINATE): Remove macro.
        * config/m68hc11/m68hc11.c (TARGET_CAN_ELIMINATE): Define macro.
        (m68hc11_can_eliminate): New function.

        * config/m68k/m68k.h (CAN_ELIMINATE): Remove macro.
        * config/m68k/m68k.c (TARGET_CAN_ELIMINATE): Define macro.
        (m68k_can_eliminate): New function.

        * config/mep/mep.h (CAN_ELIMINATE): Remove macro.
        * config/mep/mep.c (TARGET_CAN_ELIMINATE): Define macro.
        (mep_can_eliminate): New function.

        * config/mips/mips.h (CAN_ELIMINATE): Remove macro.
        * config/mips/mips.c (TARGET_CAN_ELIMINATE): Define macro.
        (mips_can_eliminate): New function.

        * config/rs6000/rs6000.h (CAN_ELIMINATE): Remove macro.
        * config/rs6000/rs6000.c (TARGET_CAN_ELIMINATE): Define macro.
        (rs6000_can_eliminate): New function.

        * config/s390/s390.h (CAN_ELIMINATE): Remove macro.
        * config/s390/s390.c (TARGET_CAN_ELIMINATE): Define macro.
        (s390_can_eliminate): Declare as static.
        * config/s390/s390-protos.h (sparc_can_eliminate): Remove.

        * config/score/score.h (CAN_ELIMINATE): Remove macro.
        * config/score/score.c (TARGET_CAN_ELIMINATE): Define macro.
        (score_can_eliminate): New function.

        * config/sparc/sparc.h (CAN_ELIMINATE): Remove macro.
        * config/sparc/sparc.c (TARGET_CAN_ELIMINATE): Define macro.
        (sparc_can_eliminate): Declare as static.
        * config/sparc/sparc-protos.h (sparc_can_eliminate): Remove.

        * config/stormy16/stormy16.h (CAN_ELIMINATE): Remove macro.
        * config/stormy16/stormy16.c (TARGET_CAN_ELIMINATE): Define macro.
        (xstormy16_can_eliminate): New function.

        * config/v850/v850.h (CAN_ELIMINATE): Remove macro.
        * config/v850/v850.c (TARGET_CAN_ELIMINATE): Define macro.
        (v850_can_eliminate): New function.


Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     (revision 151057)
+++ gcc/doc/tm.texi     (working copy)
@@ -3812,16 +3812,16 @@
 specified first since that is the preferred elimination.
 @end defmac
 
-@defmac CAN_ELIMINATE (@var{from-reg}, @var{to-reg})
-A C expression that returns @code{true} if the compiler is allowed to try
-to replace register number @var{from-reg} with register number
-@var{to-reg}.  This macro need only be defined if @code{ELIMINABLE_REGS}
+@deftypefn {Target Hook} bool TARGET_CAN_ELIMINATE (const int @var{from-reg}, const int @var{to-reg})
+This target hook should returns @code{true} if the compiler is allowed to
+try to replace register number @var{from-reg} with register number
+@var{to-reg}.  This target hook need only be defined if @code{ELIMINABLE_REGS}
 is defined, and will usually be @code{true}, since most of the cases
 preventing register elimination are things that the compiler already
 knows about.
 
-Default value is @code{true}.
-@end defmac
+Default return value is @code{true}.
+@end deftypefn
 
 @defmac INITIAL_ELIMINATION_OFFSET (@var{from-reg}, @var{to-reg}, @var{offset-var})
 This macro is similar to @code{INITIAL_FRAME_POINTER_OFFSET}.  It
Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	(revision 151057)
+++ gcc/hooks.c	(working copy)
@@ -56,6 +56,13 @@
   return false;
 }
 
+/* Generic hook that takes const int, const int) and returns true.  */
+bool hook_bool_const_int_const_int_true (const int a ATTRIBUTE_UNUSED,
+                                         const int b ATTRIBUTE_UNUSED)
+{
+  return true;
+}
+
 /* Generic hook that takes (enum machine_mode) and returns false.  */
 bool
 hook_bool_mode_false (enum machine_mode mode ATTRIBUTE_UNUSED)
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	(revision 151057)
+++ gcc/hooks.h	(working copy)
@@ -28,6 +28,7 @@
 extern bool hook_bool_void_false (void);
 extern bool hook_bool_void_true (void);
 extern bool hook_bool_bool_false (bool);
+extern bool hook_bool_const_int_const_int_true (const int, const int);
 extern bool hook_bool_mode_false (enum machine_mode);
 extern bool hook_bool_mode_const_rtx_false (enum machine_mode, const_rtx);
 extern bool hook_bool_mode_const_rtx_true (enum machine_mode, const_rtx);
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h      (revision 151057)
+++ gcc/defaults.h      (working copy)
@@ -1147,10 +1147,6 @@
 #define ATTRIBUTE_ALIGNED_VALUE BIGGEST_ALIGNMENT
 #endif
 
-#ifndef CAN_ELIMINATE
-#define CAN_ELIMINATE(FROM, TO) true
-#endif
-
 /* Many ports have no mode-dependent addresses (except possibly autoincrement
    and autodecrement addresses, which are handled by target-independent code
    in recog.c).  */
Index: gcc/target.h
===================================================================
--- gcc/target.h        (revision 151057)
+++ gcc/target.h        (working copy)
@@ -971,6 +971,10 @@
   /* Retutn true if a function must have and use a frame pointer.  */
   bool (* frame_pointer_required) (void);
 
+  /* Returns true if the compiler is allowed to try to replace register number
+     from-reg with register number to-reg.  */
+  bool (* can_eliminate) (const int, const int);
+
   /* Functions specific to the C family of frontends.  */
   struct c {
     /* Return machine mode for non-standard suffix
Index: gcc/ira.c
===================================================================
--- gcc/ira.c   (revision 151057)
+++ gcc/ira.c   (working copy)
@@ -1458,7 +1458,7 @@
   for (i = 0; i < (int) ARRAY_SIZE (eliminables); i++)
     {
       bool cannot_elim
-       = (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
+       = (! targetm.can_eliminate (eliminables[i].from, eliminables[i].to)
           || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
 
       if (! regs_asm_clobbered[eliminables[i].from])
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h    (revision 151057)
+++ gcc/target-def.h    (working copy)
@@ -666,6 +666,10 @@
 #define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_false
 #endif
 
+#ifndef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE hook_bool_const_int_const_int_true
+#endif
+
 /* C specific.  */
 #ifndef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX default_mode_for_suffix
@@ -939,6 +943,7 @@
   TARGET_HARD_REGNO_SCRATCH_OK,                        \
   TARGET_CASE_VALUES_THRESHOLD,                        \
   TARGET_FRAME_POINTER_REQUIRED,               \
+  TARGET_CAN_ELIMINATE,                                \
   TARGET_C,                                    \
   TARGET_CXX,                                  \
   TARGET_EMUTLS,                               \
Index: gcc/system.h
===================================================================
--- gcc/system.h        (revision 151057)
+++ gcc/system.h        (working copy)
@@ -693,7 +693,8 @@
        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 FRAME_POINTER_REQUIRED
+       ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS FRAME_POINTER_REQUIRED \
+       CAN_ELIMINATE
 
 /* 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/alpha/vms.h
===================================================================
--- gcc/config/alpha/vms.h      (revision 151057)
+++ gcc/config/alpha/vms.h      (working copy)
@@ -142,10 +142,6 @@
 #undef EPILOGUE_USES
 #define EPILOGUE_USES(REGNO)    ((REGNO) == 26 || (REGNO) == 29)
 
-#undef CAN_ELIMINATE
-#define CAN_ELIMINATE(FROM, TO)  \
-  (alpha_vms_can_eliminate ((FROM), (TO)))
-
 #undef INITIAL_ELIMINATION_OFFSET
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   ((OFFSET) = alpha_vms_initial_elimination_offset(FROM, TO))
Index: gcc/config/alpha/alpha.c
===================================================================
--- gcc/config/alpha/alpha.c    (revision 151057)
+++ gcc/config/alpha/alpha.c    (working copy)
@@ -7483,8 +7483,10 @@
 
 #if TARGET_ABI_OPEN_VMS
 
-int
-alpha_vms_can_eliminate (unsigned int from ATTRIBUTE_UNUSED, unsigned int to)
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+static bool
+alpha_vms_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
 {
   /* We need the alpha_procedure_type to decide. Evaluate it now.  */
   alpha_sa_size ();
@@ -10983,6 +10985,8 @@
 #if TARGET_ABI_OPEN_VMS
 # undef TARGET_ATTRIBUTE_TABLE
 # define TARGET_ATTRIBUTE_TABLE vms_attribute_table
+# undef TARGET_CAN_ELIMINATE
+# define TARGET_CAN_ELIMINATE alpha_vms_can_eliminate
 #endif
 
 #undef TARGET_IN_SMALL_DATA_P
Index: gcc/config/alpha/alpha-protos.h
===================================================================
--- gcc/config/alpha/alpha-protos.h     (revision 151057)
+++ gcc/config/alpha/alpha-protos.h     (working copy)
@@ -114,7 +114,6 @@
 extern void vms_output_aligned_decl_common (FILE *, tree, const char *,
                                            unsigned HOST_WIDE_INT,
                                            unsigned int);
-extern int alpha_vms_can_eliminate (unsigned int, unsigned int);
 extern HOST_WIDE_INT alpha_vms_initial_elimination_offset (unsigned int,
                                                           unsigned int);
 #endif
Index: gcc/config/frv/frv.h
===================================================================
--- gcc/config/frv/frv.h        (revision 151057)
+++ gcc/config/frv/frv.h        (working copy)
@@ -1594,17 +1594,6 @@
   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}                         \
 }
 
-/* A C expression that returns nonzero if the compiler is allowed to try to
-   replace register number FROM with register number TO.  This macro need only
-   be defined if `ELIMINABLE_REGS' is defined, and will usually be the constant
-   1, since most of the cases preventing register elimination are things that
-   the compiler already knows about.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                                \
-  ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM                \
-   ? ! frame_pointer_needed                                            \
-   : 1)
-
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
    initial difference between the specified pair of registers.  This macro must
    be defined if `ELIMINABLE_REGS' is defined.  */
Index: gcc/config/frv/frv.c
===================================================================
--- gcc/config/frv/frv.c        (revision 151057)
+++ gcc/config/frv/frv.c        (working copy)
@@ -382,6 +382,7 @@
                                                 enum machine_mode,
                                                 secondary_reload_info *);
 static bool frv_frame_pointer_required         (void);
+static bool frv_can_eliminate                  (const int, const int);
 
 /* Allow us to easily change the default for -malloc-cc.  */
 #ifndef DEFAULT_NO_ALLOC_CC
@@ -475,6 +476,9 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED frv_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE frv_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #define FRV_SYMBOL_REF_TLS_P(RTX) \
@@ -2145,6 +2149,16 @@
 }
 
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+frv_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
    initial difference between the specified pair of registers.  This macro must
    be defined if `ELIMINABLE_REGS' is defined.  */
Index: gcc/config/s390/s390.c
===================================================================
--- gcc/config/s390/s390.c      (revision 151057)
+++ gcc/config/s390/s390.c      (working copy)
@@ -7335,8 +7335,8 @@
 
 /* Return true if register FROM can be eliminated via register TO.  */
 
-bool
-s390_can_eliminate (int from, int to)
+static bool
+s390_can_eliminate (const int from, const int to)
 {
   /* On zSeries machines, we have not marked the base register as fixed.
      Instead, we have an elimination rule BASE_REGNUM -> BASE_REGNUM.
@@ -10146,6 +10146,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P s390_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE s390_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-s390.h"
Index: gcc/config/s390/s390.h
===================================================================
--- gcc/config/s390/s390.h      (revision 151057)
+++ gcc/config/s390/s390.h      (working copy)
@@ -646,9 +646,6 @@
  { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM },	\
  { BASE_REGNUM, BASE_REGNUM }}
 
-#define CAN_ELIMINATE(FROM, TO) \
-  s390_can_eliminate ((FROM), (TO))
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
   (OFFSET) = s390_initial_elimination_offset ((FROM), (TO))
 
Index: gcc/config/s390/s390-protos.h
===================================================================
--- gcc/config/s390/s390-protos.h       (revision 151057)
+++ gcc/config/s390/s390-protos.h       (working copy)
@@ -36,7 +36,6 @@
 
 extern void optimization_options (int, int);
 extern void override_options (void);
-extern bool s390_can_eliminate (int, int);
 extern HOST_WIDE_INT s390_initial_elimination_offset (int, int);
 extern void s390_emit_prologue (void);
 extern void s390_emit_epilogue (bool);
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h     (revision 151057)
+++ gcc/config/sparc/sparc-protos.h     (working copy)
@@ -50,7 +50,6 @@
 extern void sparc_profile_hook (int);
 extern void sparc_override_options (void);
 extern void sparc_output_scratch_registers (FILE *);
-extern bool sparc_can_eliminate (const int, const 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 151057)
+++ gcc/config/sparc/sparc.c    (working copy)
@@ -420,6 +420,7 @@
 static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static void sparc_file_end (void);
 static bool sparc_frame_pointer_required (void);
+static bool sparc_can_eliminate (const int, const int);
 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
 static const char *sparc_mangle_type (const_tree);
 #endif
@@ -588,6 +589,9 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED sparc_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE sparc_can_eliminate
+
 #ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE sparc_mangle_type
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h    (revision 151057)
+++ gcc/config/sparc/sparc.h    (working copy)
@@ -1369,12 +1369,6 @@
   {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
    { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM} }
 
-/* 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.  */
-#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
    is a leaf function, we guessed right!  */
Index: gcc/config/mep/mep.c
===================================================================
--- gcc/config/mep/mep.c        (revision 151057)
+++ gcc/config/mep/mep.c        (working copy)
@@ -227,6 +227,7 @@
 static tree mep_build_builtin_va_list (void);
 static void mep_expand_va_start (tree, rtx);
 static tree mep_gimplify_va_arg_expr (tree, tree, tree *, tree *);
+static bool mep_can_eliminate (const int, const int);
 
 /* Initialize the GCC target structure.  */
 
@@ -298,6 +299,8 @@
 #define TARGET_EXPAND_BUILTIN_VA_START	mep_expand_va_start
 #undef	TARGET_GIMPLIFY_VA_ARG_EXPR
 #define        TARGET_GIMPLIFY_VA_ARG_EXPR     mep_gimplify_va_arg_expr
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE            mep_can_eliminate
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -2609,6 +2612,16 @@
   return 4;
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+mep_can_eliminate (const int from, const int to)
+{
+  return  (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+           ? ! frame_pointer_needed                                    \
+           : true);
+}
+
 int
 mep_elimination_offset (int from, int to)
 {
Index: gcc/config/mep/mep.h
===================================================================
--- gcc/config/mep/mep.h        (revision 151057)
+++ gcc/config/mep/mep.h        (working copy)
@@ -498,11 +498,6 @@
   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}                 \
 }
 
-#define CAN_ELIMINATE(FROM, TO)                                        \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM	\
-  ? ! frame_pointer_needed                                     \
-  : 1)
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
        (OFFSET) = mep_elimination_offset (FROM, TO)
 
Index: gcc/config/m32r/m32r.c
===================================================================
--- gcc/config/m32r/m32r.c      (revision 151057)
+++ 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_can_eliminate (const int, const int);
 
 /* M32R specific attributes.  */
 
@@ -151,6 +152,9 @@
 #undef  TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES m32r_arg_partial_bytes
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE m32r_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Implement TARGET_HANDLE_OPTION.  */
@@ -1472,6 +1476,17 @@
   /* Ok, we're done.  */
   return total_size;
 }
+
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+m32r_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
 
 /* The table we use to reference PIC data.  */
 static rtx global_offset_table;
Index: gcc/config/m32r/m32r.h
===================================================================
--- gcc/config/m32r/m32r.h      (revision 151057)
+++ gcc/config/m32r/m32r.h      (working copy)
@@ -793,18 +793,6 @@
  { ARG_POINTER_REGNUM,  STACK_POINTER_REGNUM },        \
  { ARG_POINTER_REGNUM,   FRAME_POINTER_REGNUM }}
 
-/* A C expression that returns nonzero if the compiler is allowed to
-   try to replace register number FROM-REG with register number
-   TO-REG.  This macro need only be defined if `ELIMINABLE_REGS' is
-   defined, and will usually be the constant 1, since most of the
-   cases preventing register elimination are things that the compiler
-   already knows about.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                                \
-  ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM                \
-   ? ! frame_pointer_needed                                            \
-   : 1)
-
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It
    specifies the initial difference between the specified pair of
    registers.  This macro must be defined if `ELIMINABLE_REGS' is
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h      (revision 151057)
+++ gcc/config/i386/i386.h      (working copy)
@@ -1684,11 +1684,6 @@
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                \
  { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}   \
 
-/* Given FROM and TO register numbers, say whether this elimination is
-   allowed.   */
-
-#define CAN_ELIMINATE(FROM, TO) ix86_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/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h       (revision 151057)
+++ gcc/config/i386/i386-protos.h       (working copy)
@@ -28,7 +28,6 @@
 extern void ix86_setup_frame_addresses (void);
 
 extern void ix86_file_end (void);
-extern int ix86_can_eliminate (int, int);
 extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int);
 extern void ix86_expand_prologue (void);
 extern void ix86_expand_epilogue (int);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c      (revision 151057)
+++ gcc/config/i386/i386.c      (working copy)
@@ -7794,8 +7794,8 @@
    pointer.  Otherwise, frame pointer elimination is automatically
    handled and all other eliminations are valid.  */
 
-int
-ix86_can_eliminate (int from, int to)
+static bool
+ix86_can_eliminate (const int from, const int to)
 {
   if (stack_realign_fp)
     return ((from == ARG_POINTER_REGNUM
@@ -7803,7 +7803,7 @@
            || (from == FRAME_POINTER_REGNUM
                && to == STACK_POINTER_REGNUM));
   else
-    return to == STACK_POINTER_REGNUM ? !frame_pointer_needed : 1;
+    return to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true;
 }
 
 /* Return the offset between two registers, one to be eliminated, and the other
@@ -30664,6 +30664,9 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE ix86_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-i386.h"
Index: gcc/config/avr/avr-protos.h
===================================================================
--- gcc/config/avr/avr-protos.h	(revision 151057)
+++ gcc/config/avr/avr-protos.h	(working copy)
@@ -34,7 +34,6 @@
 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);
-extern bool avr_can_eliminate (int, int);
 extern int avr_initial_elimination_offset (int from, int to);
 extern int avr_simple_epilogue (void);
 extern void gas_output_limited_string (FILE *file, const char *str);
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c        (revision 151057)
+++ gcc/config/avr/avr.c        (working copy)
@@ -90,6 +90,7 @@
 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);
+static bool avr_can_eliminate (const int, const int);
 
 /* Allocate registers from r25 to r8 for parameters for function calls.  */
 #define FIRST_CUM_REG 26
@@ -191,6 +192,8 @@
 
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE avr_can_eliminate
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
@@ -428,7 +431,7 @@
 /* Return true if register FROM can be eliminated via register TO.  */
 
 bool
-avr_can_eliminate (int from, int to)
+avr_can_eliminate (const int from, const int to)
 {
   return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
          || ((from == FRAME_POINTER_REGNUM 
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h        (revision 151057)
+++ gcc/config/avr/avr.h        (working copy)
@@ -364,8 +364,6 @@
        {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}            \
        ,{FRAME_POINTER_REGNUM+1,STACK_POINTER_REGNUM+1}}
 
-#define CAN_ELIMINATE(FROM, TO)        avr_can_eliminate (FROM, TO)
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   OFFSET = avr_initial_elimination_offset (FROM, TO)
 
Index: gcc/config/crx/crx.h
===================================================================
--- gcc/config/crx/crx.h        (revision 151057)
+++ gcc/config/crx/crx.h        (working copy)
@@ -298,9 +298,6 @@
     { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}  \
   }
 
-#define CAN_ELIMINATE(FROM, TO) \
- ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   do {                                                                 \
     (OFFSET) = crx_initial_elimination_offset ((FROM), (TO));          \
Index: gcc/config/crx/crx.c
===================================================================
--- gcc/config/crx/crx.c        (revision 151057)
+++ gcc/config/crx/crx.c        (working copy)
@@ -129,6 +129,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_can_eliminate (const int, const int);
 
 /*****************************************************************************/
 /* RTL VALIDITY                                                                     */
@@ -137,6 +138,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    crx_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE           crx_can_eliminate
+
 /*****************************************************************************/
 /* STACK LAYOUT AND CALLING CONVENTIONS                                             */
 /*****************************************************************************/
@@ -320,6 +324,14 @@
                                     crtl->outgoing_args_size : 0);
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+crx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
 
 int
Index: gcc/config/stormy16/stormy16.c
===================================================================
--- gcc/config/stormy16/stormy16.c      (revision 151057)
+++ gcc/config/stormy16/stormy16.c      (working copy)
@@ -1016,6 +1016,16 @@
   return layout;
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+static bool
+xstormy16_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
 /* Determine how all the special registers get eliminated.  */
 
 int
@@ -2654,6 +2664,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    xstormy16_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE xstormy16_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-stormy16.h"
Index: gcc/config/stormy16/stormy16.h
===================================================================
--- gcc/config/stormy16/stormy16.h      (revision 151057)
+++ gcc/config/stormy16/stormy16.h      (working copy)
@@ -375,11 +375,6 @@
   {ARG_POINTER_REGNUM,  HARD_FRAME_POINTER_REGNUM},    \
 }
 
-#define CAN_ELIMINATE(FROM, TO)                                                \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM         \
-  ? ! frame_pointer_needed                                             \
-  : 1)
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
   (OFFSET) = xstormy16_initial_elimination_offset (FROM, TO)
 
Index: gcc/config/fr30/fr30.h
===================================================================
--- gcc/config/fr30/fr30.h      (revision 151057)
+++ gcc/config/fr30/fr30.h      (working copy)
@@ -549,15 +549,6 @@
   {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}	\
 }
 
-/* A C expression that returns nonzero if the compiler is allowed to try to
-   replace register number FROM with register number TO.  This macro
-   need only be defined if `ELIMINABLE_REGS' is defined, and will usually be
-   the constant 1, since most of the cases preventing register elimination are
-   things that the compiler already knows about.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                                \
- ((TO) == FRAME_POINTER_REGNUM || ! frame_pointer_needed)
-
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
    initial difference between the specified pair of registers.  This macro must
    be defined if `ELIMINABLE_REGS' is defined.  */
Index: gcc/config/fr30/fr30.c
===================================================================
--- gcc/config/fr30/fr30.c      (revision 151057)
+++ gcc/config/fr30/fr30.c      (working copy)
@@ -120,6 +120,7 @@
 static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                   tree, bool);
 static bool fr30_frame_pointer_required (void);
+static bool fr30_can_eliminate (const int, const int);
 
 #define FRAME_POINTER_MASK     (1 << (FRAME_POINTER_REGNUM))
 #define RETURN_POINTER_MASK    (1 << (RETURN_POINTER_REGNUM))
@@ -161,8 +162,20 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED fr30_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE fr30_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
+
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+fr30_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == FRAME_POINTER_REGNUM || ! frame_pointer_needed);
+}
+
 /* Returns the number of bytes offset between FROM_REG and TO_REG
    for the current function.  As a side effect it fills in the 
    current_frame_info structure, if the data is available.  */
Index: gcc/config/m68hc11/m68hc11.c
===================================================================
--- gcc/config/m68hc11/m68hc11.c        (revision 151057)
+++ gcc/config/m68hc11/m68hc11.c        (working copy)
@@ -91,6 +91,7 @@
 static void m68hc11_init_libfuncs (void);
 static rtx m68hc11_struct_value_rtx (tree, int);
 static bool m68hc11_return_in_memory (const_tree, const_tree);
+static bool m68hc11_can_eliminate (const int, const int);
 
 /* Must be set to 1 to produce debug messages.  */
 int debug_m6811 = 0;
@@ -278,6 +279,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    m68hc11_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE m68hc11_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 int
@@ -1280,6 +1284,19 @@
 
 /* Argument support functions.  */
 
+/* Given FROM and TO register numbers, say whether this elimination is
+   allowed. Frame pointer elimination is automatically handled.
+
+   All other eliminations are valid.  */
+
+bool
+m68hc11_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : true);
+}
+
 /* Define the offset between two registers, one to be eliminated, and the
    other its replacement, at the start of a routine.  */
 int
Index: gcc/config/m68hc11/m68hc11.h
===================================================================
--- gcc/config/m68hc11/m68hc11.h        (revision 151057)
+++ gcc/config/m68hc11/m68hc11.h        (working copy)
@@ -883,17 +883,6 @@
  {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},         \
  {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
 
-/* Given FROM and TO register numbers, say whether this elimination is allowed.
-   Frame pointer elimination is automatically handled.
-
-   All other eliminations are valid.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                        \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM	\
-  ? ! frame_pointer_needed                                     \
-  : 1)
-
-
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
 
Index: gcc/config/iq2000/iq2000.h
===================================================================
--- gcc/config/iq2000/iq2000.h  (revision 151057)
+++ gcc/config/iq2000/iq2000.h  (working copy)
@@ -354,17 +354,6 @@
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                                \
  { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
 
-
-/* We can always eliminate to the frame pointer.  We can eliminate to the 
-   stack pointer unless a frame pointer is needed.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                                \
-  (((FROM) == RETURN_ADDRESS_POINTER_REGNUM && (! leaf_function_p ()   \
-   || (TO == GP_REG_FIRST + 31 && leaf_function_p)))                           \
-  || ((FROM) != RETURN_ADDRESS_POINTER_REGNUM                          \
-   && ((TO) == HARD_FRAME_POINTER_REGNUM                               \
-   || ((TO) == STACK_POINTER_REGNUM && ! frame_pointer_needed))))
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                    \
         (OFFSET) = iq2000_initial_elimination_offset ((FROM), (TO))
 
Index: gcc/config/iq2000/iq2000.c
===================================================================
--- gcc/config/iq2000/iq2000.c  (revision 151057)
+++ gcc/config/iq2000/iq2000.c  (working copy)
@@ -165,6 +165,7 @@
                                       tree, bool);
 static void iq2000_va_start          (tree, rtx);
 static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
+static bool iq2000_can_eliminate      (const int, const int);
 
 #undef  TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS           iq2000_init_builtins
@@ -214,6 +215,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    iq2000_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE            iq2000_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return nonzero if we split the address into high and low parts.  */
@@ -1678,6 +1682,22 @@
   return total_size;
 }
 
+
+/* We can always eliminate to the frame pointer.  We can eliminate to the
+   stack pointer unless a frame pointer is needed.  */
+
+bool
+iq2000_can_eliminate (const int from, const int to)
+{
+  return (from == RETURN_ADDRESS_POINTER_REGNUM 
+          && (! leaf_function_p () 
+              || (to == GP_REG_FIRST + 31 && leaf_function_p)))
+          || (from != RETURN_ADDRESS_POINTER_REGNUM
+              && (to == HARD_FRAME_POINTER_REGNUM
+                  || (to == STACK_POINTER_REGNUM 
+                      && ! frame_pointer_needed)));
+}
+
 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame
    pointer, argument pointer, or return address pointer.  TO is either
    the stack pointer or hard frame pointer.  */
Index: gcc/config/ia64/ia64.c
===================================================================
--- gcc/config/ia64/ia64.c      (revision 151057)
+++ gcc/config/ia64/ia64.c      (working copy)
@@ -199,6 +199,7 @@
 static rtx gen_fr_spill_x (rtx, rtx, rtx);
 static rtx gen_fr_restore_x (rtx, rtx, rtx);
 
+static bool ia64_can_eliminate (const int, const int);
 static enum machine_mode hfa_element_mode (const_tree, bool);
 static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
                                         tree, int *, int);
@@ -522,6 +523,9 @@
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX ia64_c_mode_for_suffix
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE ia64_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 typedef enum
@@ -2639,6 +2643,14 @@
   current_frame_info.initialized = reload_completed;
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+ia64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == BR_REG (0) ? current_function_is_leaf : true);
+}
+
 /* Compute the initial difference between the specified pair of registers.  */
 
 HOST_WIDE_INT
Index: gcc/config/ia64/ia64.h
===================================================================
--- gcc/config/ia64/ia64.h      (revision 151057)
+++ gcc/config/ia64/ia64.h      (working copy)
@@ -1027,13 +1027,6 @@
   {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},                   \
 }
 
-/* A C expression that returns nonzero if the compiler is allowed to try to
-   replace register number FROM with register number TO.  The frame pointer
-   is automatically handled.  */
-
-#define CAN_ELIMINATE(FROM, TO) \
-  (TO == BR_REG (0) ? current_function_is_leaf : 1)
-
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It
    specifies the initial difference between the specified pair of
    registers.  This macro must be defined if `ELIMINABLE_REGS' is
Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c      (revision 151057)
+++ gcc/config/m68k/m68k.c      (working copy)
@@ -132,6 +132,7 @@
 static void m68k_sched_dfa_post_advance_cycle (void);
 static int m68k_sched_first_cycle_multipass_dfa_lookahead (void);
 
+static bool m68k_can_eliminate (const int, const int);
 static bool m68k_legitimate_address_p (enum machine_mode, rtx, bool);
 static bool m68k_handle_option (size_t, const char *, int);
 static rtx find_addr_reg (rtx);
@@ -263,6 +264,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    m68k_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE m68k_can_eliminate
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
@@ -866,6 +870,14 @@
   current_frame.funcdef_no = current_function_funcdef_no;
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+m68k_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
 HOST_WIDE_INT
 m68k_initial_elimination_offset (int from, int to)
 {
Index: gcc/config/m68k/m68k.h
===================================================================
--- gcc/config/m68k/m68k.h      (revision 151057)
+++ gcc/config/m68k/m68k.h      (working copy)
@@ -663,9 +663,6 @@
  { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM },         \
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }}
 
-#define CAN_ELIMINATE(FROM, TO) \
-  ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
   (OFFSET) = m68k_initial_elimination_offset(FROM, TO)
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 151057)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -1088,6 +1088,7 @@
 
 const int INSN_NOT_AVAILABLE = -1;
 static enum machine_mode rs6000_eh_return_filter_mode (void);
+static bool rs6000_can_eliminate (const int, const int);
 
 /* Hash table stuff for keeping track of TOC entries.  */
 
@@ -1453,6 +1454,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE rs6000_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
@@ -25011,6 +25015,26 @@
   return gen_rtx_REG (mode, regno);
 }
 
+
+/* Given FROM and TO register numbers, say whether this elimination is allowed.
+   Frame pointer elimination is automatically handled.
+
+   For the RS/6000, if frame pointer elimination is being done, we would like
+   to convert ap into fp, not sp.
+
+   We need r30 if -mminimal-toc was specified, and there are constant pool
+   references.  */
+
+bool
+rs6000_can_eliminate (const int from, const int to)
+{
+  return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
+          ? ! frame_pointer_needed
+          : from == RS6000_PIC_OFFSET_TABLE_REGNUM
+            ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC || get_pool_size () == 0
+            : true);
+}
+
 /* Define the offset between two registers, FROM to be eliminated and its
    replacement TO, at the start of a routine.  */
 HOST_WIDE_INT
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h  (revision 151057)
+++ gcc/config/rs6000/rs6000.h  (working copy)
@@ -1786,22 +1786,6 @@
  { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},     \
  { RS6000_PIC_OFFSET_TABLE_REGNUM, RS6000_PIC_OFFSET_TABLE_REGNUM } }
 
-/* Given FROM and TO register numbers, say whether this elimination is allowed.
-   Frame pointer elimination is automatically handled.
-
-   For the RS/6000, if frame pointer elimination is being done, we would like
-   to convert ap into fp, not sp.
-
-   We need r30 if -mminimal-toc was specified, and there are constant pool
-   references.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                                \
- ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM         \
-  ? ! frame_pointer_needed                                             \
-  : (FROM) == RS6000_PIC_OFFSET_TABLE_REGNUM                           \
-  ? ! TARGET_MINIMAL_TOC || TARGET_NO_TOC || get_pool_size () == 0     \
-  : 1)
-
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
Index: gcc/config/score/score.c
===================================================================
--- gcc/config/score/score.c    (revision 151057)
+++ gcc/config/score/score.c    (working copy)
@@ -116,6 +116,9 @@
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P    score_legitimate_address_p
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE            score_can_eliminate
+
 struct extern_list *extern_head = 0;
 
 /* default 0 = NO_REGS  */
@@ -426,6 +429,16 @@
   gcc_unreachable ();
 }
 
+/* We can always eliminate to the hard frame pointer.  We can eliminate
+   to the stack pointer unless a frame pointer is needed.  */
+
+static bool
+score_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == HARD_FRAME_POINTER_REGNUM
+          || (to  == STACK_POINTER_REGNUM && !frame_pointer_needed));
+}
+
 /* 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/config/score/score.h
===================================================================
--- gcc/config/score/score.h    (revision 151057)
+++ gcc/config/score/score.h    (working copy)
@@ -564,13 +564,6 @@
    { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},      \
    { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
 
-/* We can always eliminate to the hard frame pointer.  We can eliminate
-   to the stack pointer unless a frame pointer is needed.  */
-#define CAN_ELIMINATE(FROM, TO)        \
-  (((TO) == HARD_FRAME_POINTER_REGNUM) \
-   || ((TO) == STACK_POINTER_REGNUM    \
-       && !frame_pointer_needed))
-
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
   (OFFSET) = score_initial_elimination_offset ((FROM), (TO))
 
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c        (revision 151057)
+++ gcc/config/arm/arm.c        (working copy)
@@ -218,6 +218,7 @@
 static tree arm_convert_to_type (tree type, tree expr);
 static bool arm_scalar_mode_supported_p (enum machine_mode);
 static bool arm_frame_pointer_required (void);
+static bool arm_can_eliminate (const int, const int);
 
 
 /* Table of machine attributes.  */
@@ -485,6 +486,9 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED arm_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE arm_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -14065,7 +14069,25 @@
     }
 }
 
+/* Given FROM and TO register numbers, say whether this elimination is
+   allowed.  Frame pointer elimination is automatically handled.
 
+   All eliminations are permissible.  Note that ARG_POINTER_REGNUM and
+   HARD_FRAME_POINTER_REGNUM are in fact the same thing.  If we need a frame
+   pointer, we must eliminate FRAME_POINTER_REGNUM into
+   HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM or
+   ARG_POINTER_REGNUM.  */
+
+bool
+arm_can_eliminate (const int from, const int to)
+{
+  return ((to == FRAME_POINTER_REGNUM && from == ARG_POINTER_REGNUM) ? false :
+          (to == STACK_POINTER_REGNUM && frame_pointer_needed) ? false :
+          (to == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? false :
+          (to == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? false :
+           true);
+}
+
 /* Emit RTL to save coprocessor registers on function entry.  Returns the
    number of bytes pushed.  */
 
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h        (revision 151057)
+++ gcc/config/arm/arm.h        (working copy)
@@ -1846,21 +1846,6 @@
  { FRAME_POINTER_REGNUM,      ARM_HARD_FRAME_POINTER_REGNUM   },\
  { FRAME_POINTER_REGNUM,      THUMB_HARD_FRAME_POINTER_REGNUM }}
 
-/* Given FROM and TO register numbers, say whether this elimination is
-   allowed.  Frame pointer elimination is automatically handled.
-
-   All eliminations are permissible.  Note that ARG_POINTER_REGNUM and
-   HARD_FRAME_POINTER_REGNUM are in fact the same thing.  If we need a frame
-   pointer, we must eliminate FRAME_POINTER_REGNUM into
-   HARD_FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM or
-   ARG_POINTER_REGNUM.  */
-#define CAN_ELIMINATE(FROM, TO)                                                \
-  (((TO) == FRAME_POINTER_REGNUM && (FROM) == ARG_POINTER_REGNUM) ? 0 :        \
-   ((TO) == STACK_POINTER_REGNUM && frame_pointer_needed) ? 0 :                \
-   ((TO) == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? 0 :       \
-   ((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 :       \
-   1)
-
 /* Define the offset between two registers, one to be eliminated, and the
    other its replacement, at the start of a routine.  */
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c      (revision 151057)
+++ gcc/config/mips/mips.c      (working copy)
@@ -8989,6 +8989,15 @@
   return false;
 }
 
+/* Make sure that we're not trying to eliminate to the wrong hard frame
+   pointer.  */
+
+static bool
+mips_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
+}
+
 /* Implement INITIAL_ELIMINATION_OFFSET.  FROM is either the frame pointer
    or argument pointer.  TO is either the stack pointer or hard frame
    pointer.  */
@@ -15010,6 +15019,9 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED mips_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE mips_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-mips.h"
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h      (revision 151057)
+++ gcc/config/mips/mips.h      (working copy)
@@ -2166,11 +2166,6 @@
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30},                           \
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
 
-/* 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/v850/v850.c
===================================================================
--- gcc/config/v850/v850.c      (revision 151057)
+++ gcc/config/v850/v850.c      (working copy)
@@ -72,6 +72,7 @@
                                    const_tree, bool);
 static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
                                   tree, bool);
+static bool v850_can_eliminate       (const int, const int);
 
 /* Information about the various small memory areas.  */
 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
@@ -173,6 +174,9 @@
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE v850_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Set the maximum size of small memory area TYPE to the value given
@@ -2957,4 +2961,12 @@
   ca->anonymous_args = (!TARGET_GHS ? 1 : 0);
 }
 
+/* Worker function for TARGET_CAN_ELIMINATE.  */
+
+bool
+v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
 #include "gt-v850.h"
Index: gcc/config/v850/v850.h
===================================================================
--- gcc/config/v850/v850.h      (revision 151057)
+++ gcc/config/v850/v850.h      (working copy)
@@ -538,16 +538,6 @@
  { ARG_POINTER_REGNUM,  STACK_POINTER_REGNUM },                        \
  { ARG_POINTER_REGNUM,   HARD_FRAME_POINTER_REGNUM }}                  \
 
-/* A C expression that returns nonzero if the compiler is allowed to
-   try to replace register number FROM-REG with register number
-   TO-REG.  This macro need only be defined if `ELIMINABLE_REGS' is
-   defined, and will usually be the constant 1, since most of the
-   cases preventing register elimination are things that the compiler
-   already knows about.  */
-
-#define CAN_ELIMINATE(FROM, TO) \
- ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It
    specifies the initial difference between the specified pair of
    registers.  This macro must be defined if `ELIMINABLE_REGS' is
Index: gcc/config/h8300/h8300.c
===================================================================
--- gcc/config/h8300/h8300.c    (revision 151057)
+++ gcc/config/h8300/h8300.c    (working copy)
@@ -1825,6 +1825,20 @@
   return 0;
 }
 
+/* Given FROM and TO register numbers, say whether this elimination is allowed.
+   Frame pointer elimination is automatically handled.
+
+   For the h8300, if frame pointer elimination is being done, we would like to
+   convert ap and rp into sp, not fp.
+
+   All other eliminations are valid.  */
+
+static bool
+h8300_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
 /* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).
    Define the offset between two registers, one to be eliminated, and
    the other its replacement, at the start of a routine.  */
@@ -5801,4 +5815,8 @@
 #undef TARGET_DEFAULT_TARGET_FLAGS
 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
 
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE h8300_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/h8300/h8300.h
===================================================================
--- gcc/config/h8300/h8300.h    (revision 151057)
+++ gcc/config/h8300/h8300.h    (working copy)
@@ -558,17 +558,6 @@
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                        \
  { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
 
-/* Given FROM and TO register numbers, say whether this elimination is allowed.
-   Frame pointer elimination is automatically handled.
-
-   For the h8300, if frame pointer elimination is being done, we would like to
-   convert ap and rp into sp, not fp.
-
-   All other eliminations are valid.  */
-
-#define CAN_ELIMINATE(FROM, TO)                                        \
-  ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
 
Index: gcc/config/bfin/bfin.c
===================================================================
--- gcc/config/bfin/bfin.c      (revision 151057)
+++ gcc/config/bfin/bfin.c      (working copy)
@@ -883,6 +883,17 @@
   return n;
 }
 
+/* Given FROM and TO register numbers, say whether this elimination is
+   allowed.  Frame pointer elimination is automatically handled.
+
+   All other eliminations are valid.  */
+
+static bool
+bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+  return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
 /* Return the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
 
@@ -6338,4 +6349,7 @@
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
 
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE bfin_can_eliminate
+
 struct gcc_target targetm = TARGET_INITIALIZER;
Index: gcc/config/bfin/bfin.h
===================================================================
--- gcc/config/bfin/bfin.h      (revision 151057)
+++ gcc/config/bfin/bfin.h      (working copy)
@@ -376,14 +376,6 @@
  { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},  \
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}        \
 
-/* Given FROM and TO register numbers, say whether this elimination is
-   allowed.  Frame pointer elimination is automatically handled.
-
-   All other eliminations are valid.  */
-
-#define CAN_ELIMINATE(FROM, TO) \
-  ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
 
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c       (revision 151057)
+++ gcc/reload1.c       (working copy)
@@ -318,8 +318,9 @@
   int to;                      /* Register number used as replacement.  */
   HOST_WIDE_INT initial_offset;        /* Initial difference between values.  */
   int can_eliminate;           /* Nonzero if this elimination can be done.  */
-  int can_eliminate_previous;  /* Value of CAN_ELIMINATE in previous scan over
-                                  insns made by reload.  */
+  int can_eliminate_previous;  /* Value returned by TARGET_CAN_ELIMINATE
+                                  target hook in previous scan over insns
+                                  made by reload.  */
   HOST_WIDE_INT offset;                /* Current offset between the two regs.  */
   HOST_WIDE_INT previous_offset;/* Offset at end of previous insn.  */
   int ref_outside_mem;         /* "to" has been referenced outside a MEM.  */
@@ -3705,7 +3706,7 @@
     if ((ep->from == HARD_FRAME_POINTER_REGNUM 
          && targetm.frame_pointer_required ())
 #ifdef ELIMINABLE_REGS
-       || ! CAN_ELIMINATE (ep->from, ep->to)
+       || ! targetm.can_eliminate (ep->from, ep->to)
 #endif
        )
       ep->can_eliminate = 0;
@@ -3811,7 +3812,7 @@
       ep->from = ep1->from;
       ep->to = ep1->to;
       ep->can_eliminate = ep->can_eliminate_previous
-       = (CAN_ELIMINATE (ep->from, ep->to)
+       = (targetm.can_eliminate (ep->from, ep->to)
           && ! (ep->to == STACK_POINTER_REGNUM
                 && frame_pointer_needed 
                 && (! SUPPORTS_STACK_ALIGNMENT



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