summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog109
-rw-r--r--gcc/config/alpha/alpha-protos.h1
-rw-r--r--gcc/config/alpha/alpha.c8
-rw-r--r--gcc/config/alpha/vms.h4
-rw-r--r--gcc/config/arm/arm.c22
-rw-r--r--gcc/config/arm/arm.h15
-rw-r--r--gcc/config/avr/avr-protos.h1
-rw-r--r--gcc/config/avr/avr.c5
-rw-r--r--gcc/config/avr/avr.h2
-rw-r--r--gcc/config/bfin/bfin.c14
-rw-r--r--gcc/config/bfin/bfin.h8
-rw-r--r--gcc/config/crx/crx.c12
-rw-r--r--gcc/config/crx/crx.h3
-rw-r--r--gcc/config/fr30/fr30.c13
-rw-r--r--gcc/config/fr30/fr30.h9
-rw-r--r--gcc/config/frv/frv.c14
-rw-r--r--gcc/config/frv/frv.h11
-rw-r--r--gcc/config/h8300/h8300.c17
-rw-r--r--gcc/config/h8300/h8300.h13
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c9
-rw-r--r--gcc/config/i386/i386.h5
-rw-r--r--gcc/config/ia64/ia64.c15
-rw-r--r--gcc/config/ia64/ia64.h11
-rw-r--r--gcc/config/iq2000/iq2000.c22
-rw-r--r--gcc/config/iq2000/iq2000.h13
-rw-r--r--gcc/config/m32r/m32r.c15
-rw-r--r--gcc/config/m32r/m32r.h12
-rw-r--r--gcc/config/m68hc11/m68hc11.c17
-rw-r--r--gcc/config/m68hc11/m68hc11.h13
-rw-r--r--gcc/config/m68k/m68k.c12
-rw-r--r--gcc/config/m68k/m68k.h6
-rw-r--r--gcc/config/mep/mep.c13
-rw-r--r--gcc/config/mep/mep.h5
-rw-r--r--gcc/config/mips/mips.c12
-rw-r--r--gcc/config/mips/mips.h5
-rw-r--r--gcc/config/rs6000/rs6000.c24
-rw-r--r--gcc/config/rs6000/rs6000.h16
-rw-r--r--gcc/config/s390/s390-protos.h5
-rw-r--r--gcc/config/s390/s390.c7
-rw-r--r--gcc/config/s390/s390.h3
-rw-r--r--gcc/config/score/score.c15
-rw-r--r--gcc/config/score/score.h7
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c4
-rw-r--r--gcc/config/sparc/sparc.h6
-rw-r--r--gcc/config/stormy16/stormy16.c13
-rw-r--r--gcc/config/stormy16/stormy16.h7
-rw-r--r--gcc/config/v850/v850.c12
-rw-r--r--gcc/config/v850/v850.h12
-rw-r--r--gcc/defaults.h4
-rw-r--r--gcc/doc/tm.texi12
-rw-r--r--gcc/hooks.c7
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/ira.c2
-rw-r--r--gcc/reload1.c9
-rw-r--r--gcc/system.h3
-rw-r--r--gcc/target-def.h5
-rw-r--r--gcc/target.h4
59 files changed, 435 insertions, 211 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 277d6a210e7..4d4a8e659f0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,112 @@
+2009-08-25 Anatoly Sokolov <aesok@post.ru>
+
+ * 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.
+
2009-08-25 Uros Bizjak <ubizjak@gmail.com>
* config/alpha/alpha.md (*cmpdf_ieee_ext[123]): Remove.
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 43665d3af20..7e9d14b5f4b 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -114,7 +114,6 @@ extern void avms_asm_output_external (FILE *, tree, const char *);
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
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 08de3636536..1c15e53f996 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -7483,8 +7483,10 @@ alpha_initial_elimination_offset (unsigned int from,
#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 @@ alpha_init_libfuncs (void)
#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
diff --git a/gcc/config/alpha/vms.h b/gcc/config/alpha/vms.h
index e3781b57163..cb84a040eee 100644
--- a/gcc/config/alpha/vms.h
+++ b/gcc/config/alpha/vms.h
@@ -142,10 +142,6 @@ along with GCC; see the file COPYING3. If not see
#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))
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1ac6510312c..1cc9557361a 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -218,6 +218,7 @@ static tree arm_promoted_type (const_tree t);
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 @@ static const struct attribute_spec arm_attribute_table[] =
#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,6 +14069,24 @@ arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
}
}
+/* 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. */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index c84d58bbcb0..ae32da563e1 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1846,21 +1846,6 @@ typedef struct
{ 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) \
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 719829d431f..c39b97be177 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -34,7 +34,6 @@ extern enum reg_class avr_reg_class_from_letter (int c);
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);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index d08d89fb697..2c562e9a18f 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -90,6 +90,7 @@ static rtx avr_builtin_setjmp_frame_value (void);
static bool avr_hard_regno_scratch_ok (unsigned int);
static unsigned int avr_case_values_threshold (void);
static bool avr_frame_pointer_required_p (void);
+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 @@ static const struct attribute_spec avr_attribute_table[] =
#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 @@ avr_regs_to_save (HARD_REG_SET *set)
/* 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
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 7100ad17fe8..ff409398249 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -364,8 +364,6 @@ enum reg_class {
{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)
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 13887480d1f..61da6db38eb 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -883,6 +883,17 @@ n_regs_saved_by_prologue (void)
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 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#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;
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index a79420476c6..a9ff6fa8b47 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -376,14 +376,6 @@ extern const char *bfin_library_id_string;
{ 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. */
diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c
index 4aa617fa28e..a0b43a4aa18 100644
--- a/gcc/config/crx/crx.c
+++ b/gcc/config/crx/crx.c
@@ -129,6 +129,7 @@ static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
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 @@ static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
#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 @@ crx_compute_frame (void)
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
diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h
index dcddaf03ecd..ed6d3d6edd2 100644
--- a/gcc/config/crx/crx.h
+++ b/gcc/config/crx/crx.h
@@ -298,9 +298,6 @@ enum reg_class
{ 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)); \
diff --git a/gcc/config/fr30/fr30.c b/gcc/config/fr30/fr30.c
index fc412eef8f0..431af8f63f9 100644
--- a/gcc/config/fr30/fr30.c
+++ b/gcc/config/fr30/fr30.c
@@ -120,6 +120,7 @@ static bool fr30_must_pass_in_stack (enum machine_mode, const_tree);
static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
static bool fr30_frame_pointer_required (void);
+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 @@ static bool fr30_frame_pointer_required (void);
#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. */
diff --git a/gcc/config/fr30/fr30.h b/gcc/config/fr30/fr30.h
index 9af74a97c14..f055a1a05dc 100644
--- a/gcc/config/fr30/fr30.h
+++ b/gcc/config/fr30/fr30.h
@@ -549,15 +549,6 @@ enum reg_class
{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. */
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 658b5b4c275..63e65fb8bbf 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -382,6 +382,7 @@ static bool frv_secondary_reload (bool, rtx, enum reg_class,
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 @@ static bool frv_frame_pointer_required (void);
#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 @@ frv_frame_pointer_required (void)
}
+/* 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. */
diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h
index dfb3fb8eeb1..0516ecf2cac 100644
--- a/gcc/config/frv/frv.h
+++ b/gcc/config/frv/frv.h
@@ -1594,17 +1594,6 @@ typedef struct frv_stack {
{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. */
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index c3dd29723fe..02b3ff6094a 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1825,6 +1825,20 @@ h8300_expand_movsi (rtx operands[])
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,7 @@ h8300_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
#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;
diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h
index dd95ed7253d..884e49a9d4a 100644
--- a/gcc/config/h8300/h8300.h
+++ b/gcc/config/h8300/h8300.h
@@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler.
Renesas H8/300 (generic)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com),
Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -558,17 +558,6 @@ enum reg_class {
{ 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. */
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 324062ec7df..183352b73ba 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -28,7 +28,6 @@ extern int ix86_can_use_return_insn_p (void);
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);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 8b73fca0c6f..b761ab2545d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7794,8 +7794,8 @@ ix86_nsaved_sseregs (void)
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 @@ ix86_can_eliminate (int from, int to)
|| (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 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
#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"
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 15ac4d38247..88e310eccd4 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1684,11 +1684,6 @@ typedef struct ix86_args {
{ 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. */
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 42eec174c9e..85bca08d385 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009
+ Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -199,6 +200,7 @@ static rtx gen_movdi_x (rtx, rtx, rtx);
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 +524,9 @@ static const struct attribute_spec ia64_attribute_table[] =
#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 +2644,14 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
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
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index f91e63942f8..40c85501cda 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -1,6 +1,6 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -1027,13 +1027,6 @@ enum reg_class
{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
diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c
index ff0c868aaf2..85a8e5ac9f4 100644
--- a/gcc/config/iq2000/iq2000.c
+++ b/gcc/config/iq2000/iq2000.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on Vitesse IQ2000 processors
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -165,6 +165,7 @@ static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
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 @@ static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
#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 @@ compute_frame_size (HOST_WIDE_INT size)
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. */
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index c1506a4a1f1..43bacfdd28e 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Vitesse IQ2000 processors
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -354,17 +354,6 @@ enum reg_class
{ 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))
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 372ede596c0..fdd89bc27a5 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -87,6 +87,7 @@ static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
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 @@ static const struct attribute_spec m32r_attribute_table[] =
#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 @@ m32r_compute_frame_size (int size) /* # of var. bytes allocated. */
/* 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;
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 0ddbcfae263..da6a105247b 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -793,18 +793,6 @@ extern enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
{ 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
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index 6cb0ed5f321..d30b84ccfd5 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -91,6 +91,7 @@ static int m68hc11_make_autoinc_notes (rtx *, void *);
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 @@ static const struct attribute_spec m68hc11_attribute_table[] =
#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 @@ m68hc11_is_trap_symbol (rtx sym)
/* 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
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index e795485f9c1..9b19c33e0f8 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Stephane Carrez (stcarrez@nerim.fr)
@@ -883,17 +883,6 @@ extern enum reg_class m68hc11_tmp_regs_class;
{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. */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 1027d1c724c..033872c28a1 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -132,6 +132,7 @@ static void m68k_sched_dfa_pre_advance_cycle (void);
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 @@ const char *m68k_library_id_string = "_current_shared_library_a5_offset_";
#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 @@ m68k_compute_frame_layout (void)
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)
{
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 24598c5ba07..b2cfb1d8fd1 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GCC for Motorola 680x0/ColdFire.
Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -663,9 +664,6 @@ __transfer_from_trampoline () \
{ 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)
diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c
index cf2e7d53fc0..b255339bfc3 100644
--- a/gcc/config/mep/mep.c
+++ b/gcc/config/mep/mep.c
@@ -227,6 +227,7 @@ static rtx mep_expand_builtin_saveregs (void);
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 @@ static tree mep_gimplify_va_arg_expr (tree, tree, tree *, tree *);
#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 @@ mep_reg_size (int regno)
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)
{
diff --git a/gcc/config/mep/mep.h b/gcc/config/mep/mep.h
index 1cdd7468284..58a688614cc 100644
--- a/gcc/config/mep/mep.h
+++ b/gcc/config/mep/mep.h
@@ -498,11 +498,6 @@ extern unsigned int mep_selected_isa;
{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)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 04a1f0ed8cd..42363992376 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -8989,6 +8989,15 @@ mips_frame_pointer_required (void)
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 @@ mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx insn,
#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"
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 76ab40a1e57..2c9199a12c3 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -2166,11 +2166,6 @@ enum reg_class
{ 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))
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 95f8ab5aae2..cb64d28f4c9 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1088,6 +1088,7 @@ static const enum reg_class *rs6000_ira_cover_classes (void);
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 @@ static const struct attribute_spec rs6000_attribute_table[] =
#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 @@ rs6000_libcall_value (enum machine_mode mode)
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
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 0c5e59333ab..d837d44c9be 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1786,22 +1786,6 @@ typedef struct rs6000_args
{ 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) \
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 8b9ad5aedb5..be68bd530c3 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for IBM S/390.
- Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008 Free
- Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com)
@@ -36,7 +36,6 @@ extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment);
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);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 47b939c676a..05896064d6e 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -7335,8 +7335,8 @@ s390_class_max_nregs (enum reg_class rclass, enum machine_mode mode)
/* 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 @@ s390_reorg (void)
#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"
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 4772367eee5..3c93fb770f6 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -646,9 +646,6 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
{ 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))
diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c
index 0241383fc86..12eb76b1a41 100644
--- a/gcc/config/score/score.c
+++ b/gcc/config/score/score.c
@@ -1,5 +1,5 @@
/* Output routines for Sunplus S+CORE processor
- Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Sunnorth.
This file is part of GCC.
@@ -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 @@ score_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
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. */
diff --git a/gcc/config/score/score.h b/gcc/config/score/score.h
index ed3f1a4b3c0..ea3e0168995 100644
--- a/gcc/config/score/score.h
+++ b/gcc/config/score/score.h
@@ -564,13 +564,6 @@ extern enum reg_class score_char_to_class[256];
{ 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))
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 552d5596331..4ece6c0b161 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -50,7 +50,6 @@ extern int short_branch (int, int);
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);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index a0adfd02168..ea439142dea 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -420,6 +420,7 @@ static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static void sparc_file_end (void);
static bool sparc_frame_pointer_required (void);
+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 @@ static bool fpu_option_set = false;
#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
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 3b713611f84..c5c762a44ec 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1369,12 +1369,6 @@ extern char leaf_reg_remap[];
{{ 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! */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 06b96c7b8ce..1c076b2c649 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1016,6 +1016,16 @@ xstormy16_compute_stack_layout (void)
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 @@ xstormy16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
#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"
diff --git a/gcc/config/stormy16/stormy16.h b/gcc/config/stormy16/stormy16.h
index cb35a13ab6a..49505b507b0 100644
--- a/gcc/config/stormy16/stormy16.h
+++ b/gcc/config/stormy16/stormy16.h
@@ -1,6 +1,6 @@
/* Xstormy16 cpu description.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007,
- 2008 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
This file is part of GCC.
@@ -375,11 +375,6 @@ enum reg_class
{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)
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 5e1594a9be5..19268e2bd3b 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -72,6 +72,7 @@ static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
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 @@ static const struct attribute_spec v850_attribute_table[] =
#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 @@ v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
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"
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index b841963bd2b..026a2292588 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. NEC V850 series
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2008 Free Software Foundation, Inc.
+ 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GCC.
@@ -538,16 +538,6 @@ enum reg_class
{ 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
diff --git a/gcc/defaults.h b/gcc/defaults.h
index b6cec4b249b..f1d96833070 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1147,10 +1147,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#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). */
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index df4973d8368..818df81a4d3 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3812,16 +3812,16 @@ Note that the elimination of the argument pointer with the stack pointer is
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
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 5af3cd1c411..0547ca81bb6 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -56,6 +56,13 @@ hook_bool_bool_false (bool a ATTRIBUTE_UNUSED)
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)
diff --git a/gcc/hooks.h b/gcc/hooks.h
index b057d5d6118..2704e25234f 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -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);
diff --git a/gcc/ira.c b/gcc/ira.c
index e4caf31fb8d..c6a87237621 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1458,7 +1458,7 @@ setup_eliminable_regset (void)
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])
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 7900841a239..25af8404e10 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -318,8 +318,9 @@ struct elim_table
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 @@ update_eliminables (HARD_REG_SET *pset)
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 @@ init_elim_table (void)
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
diff --git a/gcc/system.h b/gcc/system.h
index 5d47f2e1839..f73097a035d 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -693,7 +693,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index b8a28a442ae..3cef10a55cc 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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, \
diff --git a/gcc/target.h b/gcc/target.h
index 786f98793ac..7f7f177904f 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -971,6 +971,10 @@ struct gcc_target
/* 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