+2011-04-21 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * target.def (cannot_force_const_mem): Add a mode argument.
+ * doc/tm.texi.in (TARGET_CANNOT_FORCE_CONST_MEM): Update accordingly.
+ * doc/tm.texi: Regenerate.
+ * hooks.h (hook_bool_mode_rtx_false): Declare.
+ * hooks.c (hook_bool_mode_const_rtx_false): Fix commentary.
+ (hook_bool_mode_const_rtx_true): Likewise.
+ (hook_bool_mode_rtx_false): New function.
+ * reload.c (CONST_POOL_OK_P): Take a mode argument and require it
+ to be non-VOID. Update call to cannot_force_const_mem.
+ (find_reloads): Update accordingly.
+ * varasm.c (force_const_mem): Update call to cannot_force_const_mem.
+ * config/alpha/alpha.c (alpha_cannot_force_const_mem): Add a mode
+ argument.
+ * config/arm/arm-protos.h (arm_cannot_force_const_mem): Likewise.
+ * config/arm/arm.h (LEGITIMATE_CONSTANT_P): Update call.
+ * config/arm/arm.c (arm_cannot_force_const_mem): Add a mode argument.
+ * config/bfin/bfin.c (bfin_cannot_force_const_mem): Likewise.
+ * config/frv/frv.c (frv_cannot_force_const_mem): Likewise.
+ * config/i386/i386.c (ix86_cannot_force_const_mem): Likewise.
+ * config/ia64/ia64.c (ia64_cannot_force_const_mem): Likewise.
+ * config/m68k/m68k.c (TARGET_CANNOT_FORCE_CONST_MEM): Redefine to...
+ (m68k_cannot_force_const_mem): ...this new function.
+ * config/mips/mips.c (mips_cannot_force_const_mem): Add a mode
+ argument.
+ (mips_const_insns, mips_legitimize_const_move): Update calls.
+ (mips_secondary_reload_class): Likewise.
+ * config/pa/pa.c (TARGET_CANNOT_FORCE_CONST_MEM): Redefine to...
+ (pa_cannot_force_const_mem): ...this new function.
+ * config/rs6000/rs6000.c (TARGET_CANNOT_FORCE_CONST_MEM): Reefine
+ to...
+ (rs6000_cannot_force_const_mem): ...this new function.
+ * config/s390/s390.c (s390_cannot_force_const_mem): Add a mode
+ argument.
+ * config/sparc/sparc.c (sparc_cannot_force_const_mem): Likewise.
+ * config/xtensa/xtensa.c (TARGET_CANNOT_FORCE_CONST_MEM): Redefine
+ to...
+ (xtensa_cannot_force_const_mem): ...this new function.
+
2011-04-20 Nathan Froyd <froydnj@codesourcery.com>
* config/mips/mips.c (mips16_build_function_stub): Call
should never be spilling symbolic operands to the constant pool, ever. */
static bool
-alpha_cannot_force_const_mem (rtx x)
+alpha_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
enum rtx_code code = GET_CODE (x);
return code == SYMBOL_REF || code == LABEL_REF || code == CONST;
extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
bool);
extern bool arm_tls_referenced_p (rtx);
-extern bool arm_cannot_force_const_mem (rtx);
+extern bool arm_cannot_force_const_mem (enum machine_mode, rtx);
extern int cirrus_memory_offset (rtx);
extern int arm_coproc_mem_operand (rtx, bool);
/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
bool
-arm_cannot_force_const_mem (rtx x)
+arm_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
rtx base, offset;
|| flag_pic)
#define LEGITIMATE_CONSTANT_P(X) \
- (!arm_cannot_force_const_mem (X) \
+ (!arm_cannot_force_const_mem (VOIDmode, X) \
&& (TARGET_32BIT ? ARM_LEGITIMATE_CONSTANT_P (X) \
: THUMB_LEGITIMATE_CONSTANT_P (X)))
another way. */
static bool
-bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
+bfin_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x ATTRIBUTE_UNUSED)
{
/* We have only one class of non-legitimate constants, and our movsi
expander knows how to handle them. Dropping these constants into the
static void frv_asm_out_constructor (rtx, int);
static void frv_asm_out_destructor (rtx, int);
static bool frv_function_symbol_referenced_p (rtx);
-static bool frv_cannot_force_const_mem (rtx);
+static bool frv_cannot_force_const_mem (enum machine_mode, rtx);
static const char *unspec_got_name (int);
static void frv_output_const_unspec (FILE *,
const struct frv_unspec *);
4. In many cases, it's more efficient to calculate the constant in-line. */
static bool
-frv_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
+frv_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x ATTRIBUTE_UNUSED)
{
return TARGET_FDPIC;
}
is checked above. */
static bool
-ix86_cannot_force_const_mem (rtx x)
+ix86_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
/* We can always put integral constants and vectors in memory. */
switch (GET_CODE (x))
static tree ia64_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
static bool ia64_vector_mode_supported_p (enum machine_mode mode);
-static bool ia64_cannot_force_const_mem (rtx);
+static bool ia64_cannot_force_const_mem (enum machine_mode, rtx);
static const char *ia64_mangle_type (const_tree);
static const char *ia64_invalid_conversion (const_tree, const_tree);
static const char *ia64_invalid_unary_op (int, const_tree);
/* Don't allow TLS addresses to get spilled to memory. */
static bool
-ia64_cannot_force_const_mem (rtx x)
+ia64_cannot_force_const_mem (enum machine_mode mode, rtx x)
{
- if (GET_MODE (x) == RFmode)
+ if (mode == RFmode)
return true;
return tls_symbolic_operand_type (x) != 0;
}
const_tree, bool);
static rtx m68k_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
const_tree, bool);
+static bool m68k_cannot_force_const_mem (enum machine_mode mode, rtx x);
\f
/* Specify the identification number of the library being built */
#define TARGET_STRUCT_VALUE_RTX m68k_struct_value_rtx
#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
+#define TARGET_CANNOT_FORCE_CONST_MEM m68k_cannot_force_const_mem
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL m68k_ok_for_sibcall_p
return m68k_tls_reference_p (x, false);
}
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
+
+static bool
+m68k_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return m68k_illegitimate_symbolic_constant_p (x);
+}
+
/* Return true if X is a legitimate constant address that can reach
bytes in the range [X, X + REACH). STRICT_P says whether we need
strict checking. */
/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
static bool
-mips_cannot_force_const_mem (rtx x)
+mips_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{
enum mips_symbol_type type;
rtx base, offset;
{
if (SMALL_INT (offset))
return n + 1;
- else if (!targetm.cannot_force_const_mem (x))
+ else if (!targetm.cannot_force_const_mem (GET_MODE (x), x))
return n + 1 + mips_build_integer (codes, INTVAL (offset));
}
}
forced into memory, as it usually produces better code. */
split_const (src, &base, &offset);
if (offset != const0_rtx
- && (targetm.cannot_force_const_mem (src)
+ && (targetm.cannot_force_const_mem (mode, src)
|| (!TARGET_MIPS16 && can_create_pseudo_p ())))
{
base = mips_force_temporary (dest, base);
/* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */
return NO_REGS;
- if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (x))
+ if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x))
/* We can force the constant to memory and use lwc1
and ldc1. As above, we will use pairs of lwc1s if
ldc1 is not supported. */
static void pa_conditional_register_usage (void);
static enum machine_mode pa_c_mode_for_suffix (char);
static section *pa_function_section (tree, enum node_frequency, bool, bool);
+static bool pa_cannot_force_const_mem (enum machine_mode, rtx);
/* The following extra sections are only used for SOM. */
static GTY(()) section *som_readonly_data_section;
#define TARGET_SCALAR_MODE_SUPPORTED_P pa_scalar_mode_supported_p
#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM pa_tls_referenced_p
+#define TARGET_CANNOT_FORCE_CONST_MEM pa_cannot_force_const_mem
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD pa_secondary_reload
return for_each_rtx (&x, &pa_tls_symbol_ref_1, 0);
}
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
+
+static bool
+pa_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return pa_tls_referenced_p (x);
+}
+
/* Emit insns to move operands[1] into operands[0].
Return 1 if we have written out everything that needs to be done to
static bool rs6000_can_eliminate (const int, const int);
static void rs6000_conditional_register_usage (void);
static void rs6000_trampoline_init (rtx, tree, rtx);
+static bool rs6000_cannot_force_const_mem (enum machine_mode, rtx);
/* Hash table stuff for keeping track of TOC entries. */
#define TARGET_HAVE_TLS HAVE_AS_TLS
#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM rs6000_tls_referenced_p
+#define TARGET_CANNOT_FORCE_CONST_MEM rs6000_cannot_force_const_mem
#undef TARGET_DELEGITIMIZE_ADDRESS
#define TARGET_DELEGITIMIZE_ADDRESS rs6000_delegitimize_address
return for_each_rtx (&x, &rs6000_tls_symbol_ref_1, 0);
}
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
+
+static bool
+rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return rs6000_tls_referenced_p (x);
+}
+
/* Return 1 if *X is a thread-local symbol. This is the same as
rs6000_tls_symbol_ref except for the type of the unused argument. */
not constant (TLS) or not known at final link time (PIC). */
static bool
-s390_cannot_force_const_mem (rtx x)
+s390_cannot_force_const_mem (enum machine_mode mode, rtx x)
{
switch (GET_CODE (x))
{
return flag_pic != 0;
case CONST:
- return s390_cannot_force_const_mem (XEXP (x, 0));
+ return s390_cannot_force_const_mem (mode, XEXP (x, 0));
case PLUS:
case MINUS:
- return s390_cannot_force_const_mem (XEXP (x, 0))
- || s390_cannot_force_const_mem (XEXP (x, 1));
+ return s390_cannot_force_const_mem (mode, XEXP (x, 0))
+ || s390_cannot_force_const_mem (mode, XEXP (x, 1));
case UNSPEC:
switch (XINT (x, 1))
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
HOST_WIDE_INT, const_tree);
static struct machine_function * sparc_init_machine_status (void);
-static bool sparc_cannot_force_const_mem (rtx);
+static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
static rtx sparc_tls_get_addr (void);
static rtx sparc_tls_got (void);
static const char *get_some_local_dynamic_name (void);
not constant (TLS) or not known at final link time (PIC). */
static bool
-sparc_cannot_force_const_mem (rtx x)
+sparc_cannot_force_const_mem (enum machine_mode mode, rtx x)
{
switch (GET_CODE (x))
{
return flag_pic != 0;
case CONST:
- return sparc_cannot_force_const_mem (XEXP (x, 0));
+ return sparc_cannot_force_const_mem (mode, XEXP (x, 0));
case PLUS:
case MINUS:
- return sparc_cannot_force_const_mem (XEXP (x, 0))
- || sparc_cannot_force_const_mem (XEXP (x, 1));
+ return sparc_cannot_force_const_mem (mode, XEXP (x, 0))
+ || sparc_cannot_force_const_mem (mode, XEXP (x, 1));
case UNSPEC:
return true;
default:
static void xtensa_asm_trampoline_template (FILE *);
static void xtensa_trampoline_init (rtx, tree, rtx);
static bool xtensa_output_addr_const_extra (FILE *, rtx);
+static bool xtensa_cannot_force_const_mem (enum machine_mode, rtx);
static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t);
static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t);
#define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS)
#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_tls_referenced_p
+#define TARGET_CANNOT_FORCE_CONST_MEM xtensa_cannot_force_const_mem
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P xtensa_legitimate_address_p
}
+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
+
+static bool
+xtensa_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+ return xtensa_tls_referenced_p (x);
+}
+
+
/* Return the debugger register number to use for 'regno'. */
int
into their original form.
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_CANNOT_FORCE_CONST_MEM (rtx @var{x})
+@deftypefn {Target Hook} bool TARGET_CANNOT_FORCE_CONST_MEM (enum machine_mode @var{mode}, rtx @var{x})
This hook should return true if @var{x} is of a form that cannot (or
-should not) be spilled to the constant pool. The default version of
-this hook returns false.
+should not) be spilled to the constant pool. @var{mode} is the mode
+of @var{x}.
+
+The default version of this hook returns false.
The primary reason to define this hook is to prevent reload from
deciding that a non-legitimate constant would be better reloaded
@hook TARGET_CANNOT_FORCE_CONST_MEM
This hook should return true if @var{x} is of a form that cannot (or
-should not) be spilled to the constant pool. The default version of
-this hook returns false.
+should not) be spilled to the constant pool. @var{mode} is the mode
+of @var{x}.
+
+The default version of this hook returns false.
The primary reason to define this hook is to prevent reload from
deciding that a non-legitimate constant would be better reloaded
return true;
}
-/* Generic hook that takes (enum machine_mode, rtx) and returns false. */
+/* Generic hook that takes (enum machine_mode, const_rtx) and returns false. */
bool
hook_bool_mode_const_rtx_false (enum machine_mode mode ATTRIBUTE_UNUSED,
const_rtx value ATTRIBUTE_UNUSED)
return false;
}
-/* Generic hook that takes (enum machine_mode, rtx) and returns true. */
+/* Generic hook that takes (enum machine_mode, const_rtx) and returns true. */
bool
hook_bool_mode_const_rtx_true (enum machine_mode mode ATTRIBUTE_UNUSED,
const_rtx value ATTRIBUTE_UNUSED)
return true;
}
+/* Generic hook that takes (enum machine_mode, rtx) and returns false. */
+bool
+hook_bool_mode_rtx_false (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx value ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* Generic hook that takes (FILE *, const char *) and does nothing. */
void
hook_void_FILEptr_constcharptr (FILE *a ATTRIBUTE_UNUSED, const char *b ATTRIBUTE_UNUSED)
extern bool hook_bool_mode_true (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);
+extern bool hook_bool_mode_rtx_false (enum machine_mode, rtx);
extern bool hook_bool_tree_false (tree);
extern bool hook_bool_const_tree_false (const_tree);
extern bool hook_bool_tree_true (tree);
#include "target.h"
#include "ira.h"
-/* True if X is a constant that can be forced into the constant pool. */
-#define CONST_POOL_OK_P(X) \
- (CONSTANT_P (X) \
+/* True if X is a constant that can be forced into the constant pool.
+ MODE is the mode of the operand, or VOIDmode if not known. */
+#define CONST_POOL_OK_P(MODE, X) \
+ ((MODE) != VOIDmode \
+ && CONSTANT_P (X) \
&& GET_CODE (X) != HIGH \
- && !targetm.cannot_force_const_mem (X))
+ && !targetm.cannot_force_const_mem (MODE, X))
/* True if C is a non-empty register class that has too few registers
to be safely used as a reload target class. */
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0))
win = 1;
- if (CONST_POOL_OK_P (operand))
+ if (CONST_POOL_OK_P (operand_mode[i], operand))
badop = 0;
constmemok = 1;
break;
&& offsettable_memref_p (reg_equiv_mem (REGNO (operand))))
|| (reg_equiv_address (REGNO (operand)) != 0))))
win = 1;
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
|| MEM_P (operand))
badop = 0;
constmemok = 1;
an early reload pass. Note that the test here is
precisely the same as in the code below that calls
force_const_mem. */
- if (CONST_POOL_OK_P (operand)
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
&& ((targetm.preferred_reload_class (operand,
this_alternative[i])
== NO_REGS)
- || no_input_reloads)
- && operand_mode[i] != VOIDmode)
+ || no_input_reloads))
{
const_to_mem = 1;
if (this_alternative[i] != NO_REGS)
op = XEXP (op, 1);
}
- if (CONST_POOL_OK_P (op)
+ if (CONST_POOL_OK_P (mode, op)
&& ((targetm.preferred_reload_class (op, goal_alternative[i])
== NO_REGS)
- || no_input_reloads)
- && mode != VOIDmode)
+ || no_input_reloads))
{
int this_address_reloaded;
rtx tem = force_const_mem (mode, op);
DEFHOOK
(cannot_force_const_mem,
"",
- bool, (rtx x),
- hook_bool_rtx_false)
+ bool, (enum machine_mode mode, rtx x),
+ hook_bool_mode_rtx_false)
DEFHOOK_UNDOC
(cannot_copy_insn_p,
void **slot;
/* If we're not allowed to drop X into the constant pool, don't. */
- if (targetm.cannot_force_const_mem (x))
+ if (targetm.cannot_force_const_mem (mode, x))
return NULL_RTX;
/* Record that this function has used a constant pool entry. */