+2014-12-19 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * lra-constraints.c (get_equiv): Don't return memory equivalence
+ when targetm.cannot_substitute_mem_equiv_p is true.
+ * target.def (cannot_substitute_mem_equiv_p): New hook.
+ * config/sh/sh.c (sh_cannot_substitute_mem_equiv_p): New function.
+ (TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P): Define.
+ * doc/tm.texi.in (TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P): New hook.
+ * doc/tm.texi: Regenerate.
+
2014-12-19 Kaz Kojima <kkojima@gcc.gnu.org>
* lra-constraints.c (process_address_1): Swap base_term and
static bool sh_legitimate_address_p (machine_mode, rtx, bool);
static rtx sh_legitimize_address (rtx, rtx, machine_mode);
static rtx sh_delegitimize_address (rtx);
+static bool sh_cannot_substitute_mem_equiv_p (rtx);
static int shmedia_target_regs_stack_space (HARD_REG_SET *);
static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
static int shmedia_target_regs_stack_adjust (HARD_REG_SET *);
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P sh_legitimate_address_p
+#undef TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
+#define TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P sh_cannot_substitute_mem_equiv_p
+
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT sh_trampoline_init
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
return NO_REGS;
}
+/* Return true if SUBST can't safely replace its equivalent during RA. */
+static bool
+sh_cannot_substitute_mem_equiv_p (rtx)
+{
+ if (TARGET_SHMEDIA)
+ return false;
+
+ /* If SUBST is mem[base+index] or QI/HImode mem[base+disp], the insn
+ uses R0 and may cause spill failure when R0 is already used.
+ We have to return true for that case at least.
+ Moreover SH has strong R0 parity and also have not enough numbers of
+ the hard registers to make the equiv substitution win in the size
+ and the speed on average working sets. The pseudos produced to
+ hold the equiv values can't get good hard registers for bad cases
+ and end up memory save/restore insns which make the code worse. */
+ return true;
+}
+
static void
sh_conditional_register_usage (void)
{
A target hook which returns true if an address with the same structure can have different maximal legitimate displacement. For example, the displacement can depend on memory mode or on operand combinations in the insn. The default version of this target hook returns always false.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P (rtx @var{subst})
+A target hook which returns @code{true} if @var{subst} can't
+substitute safely pseudos with equivalent memory values during
+register allocation.
+The default version of this target hook returns @code{false}.
+On most machines, this default should be used. For generally
+machines with non orthogonal register usage for addressing, such
+as SH, this hook can be used to avoid excessive spilling.
+@end deftypefn
+
@deftypefn {Target Hook} reg_class_t TARGET_SPILL_CLASS (reg_class_t, @var{machine_mode})
This hook defines a class of registers which could be used for spilling pseudos of the given mode and class, or @code{NO_REGS} if only memory should be used. Not defining this hook is equivalent to returning @code{NO_REGS} for all inputs.
@end deftypefn
@hook TARGET_DIFFERENT_ADDR_DISPLACEMENT_P
+@hook TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
+
@hook TARGET_SPILL_CLASS
@hook TARGET_CSTORE_MODE
|| lra_get_regno_hard_regno (regno) >= 0)
return x;
if ((res = ira_reg_equiv[regno].memory) != NULL_RTX)
- return res;
+ {
+ if (targetm.cannot_substitute_mem_equiv_p (res))
+ return x;
+ return res;
+ }
if ((res = ira_reg_equiv[regno].constant) != NULL_RTX)
return res;
if ((res = ira_reg_equiv[regno].invariant) != NULL_RTX)
reg_class_t, (reg_class_t rclass),
default_preferred_rename_class)
+/* This target hook allows the backend to avoid unsafe substitution
+ during register allocation. */
+DEFHOOK
+(cannot_substitute_mem_equiv_p,
+ "A target hook which returns @code{true} if @var{subst} can't\n\
+substitute safely pseudos with equivalent memory values during\n\
+register allocation.\n\
+The default version of this target hook returns @code{false}.\n\
+On most machines, this default should be used. For generally\n\
+machines with non orthogonal register usage for addressing, such\n\
+as SH, this hook can be used to avoid excessive spilling.",
+ bool, (rtx subst),
+ hook_bool_rtx_false)
+
/* This target hook allows the backend to perform additional
processing while initializing for variable expansion. */
DEFHOOK