This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Hookize CAN_ELIMINATE
- From: Anatoly Sokolov <aesok at post dot ru>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 22 Aug 2009 20:04:57 +0400
- Subject: [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