aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKaz Kojima <kkojima@gcc.gnu.org>2014-12-19 04:43:11 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2014-12-19 04:43:11 +0000
commit14133a4d8ab6d9ccd7e7e2e827f4451180a7e17a (patch)
treed3eb5c21dfd81a4058b594337113d83becb21397 /gcc
parentd6220b11a7d208c4713bd4da4bbec792a25ffde9 (diff)
downloadgcc-14133a4d8ab6d9ccd7e7e2e827f4451180a7e17a.zip
gcc-14133a4d8ab6d9ccd7e7e2e827f4451180a7e17a.tar.gz
gcc-14133a4d8ab6d9ccd7e7e2e827f4451180a7e17a.tar.bz2
* Add TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT target macro.
From-SVN: r218887
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/sh/sh.c28
-rw-r--r--gcc/doc/tm.texi9
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/lra-constraints.c26
-rw-r--r--gcc/target.def13
-rw-r--r--gcc/targhooks.c8
-rw-r--r--gcc/targhooks.h2
8 files changed, 100 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 315496c..b22e5aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
2014-12-19 Kaz Kojima <kkojima@gcc.gnu.org>
+ * lra-constraints.c (process_address_1): Try if target can split
+ displacement with targetm.legitimize_address_displacement.
+ * target.def (legitimize_address_displacement): New hook.
+ * targhooks.c (default_legitimize_address_displacement): New function.
+ * targhooks.h (default_legitimize_address_displacement): Declare.
+ * config/sh/sh.c (sh_legitimize_address_displacement): New function.
+ (TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT): Define.
+ * doc/tm.texi.in (TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT): New hook.
+ * doc/tm.texi: Regenerate.
+
+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.
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index eb19c42..815f4d9 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -292,6 +292,7 @@ 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 bool sh_legitimize_address_displacement (rtx *, rtx *, machine_mode);
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 *);
@@ -634,6 +635,10 @@ static const struct attribute_spec sh_attribute_table[] =
#undef TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
#define TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P sh_cannot_substitute_mem_equiv_p
+#undef TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT
+#define TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT \
+ sh_legitimize_address_displacement
+
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT sh_trampoline_init
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
@@ -13236,6 +13241,29 @@ sh_cannot_substitute_mem_equiv_p (rtx)
return true;
}
+/* Return true if DISP can be legitimized. */
+static bool
+sh_legitimize_address_displacement (rtx *disp, rtx *offs,
+ machine_mode mode)
+{
+ if (TARGET_SHMEDIA)
+ return false;
+
+ if (((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
+ || (TARGET_SH2E && mode == SFmode))
+ return false;
+
+ struct disp_adjust adj = sh_find_mov_disp_adjust (mode, INTVAL (*disp));
+ if (adj.offset_adjust != NULL_RTX && adj.mov_disp != NULL_RTX)
+ {
+ *disp = adj.mov_disp;
+ *offs = adj.offset_adjust;
+ return true;
+ }
+
+ return false;
+}
+
static void
sh_conditional_register_usage (void)
{
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 50e80f6..a3fda45 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2857,6 +2857,15 @@ 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} bool TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT (rtx *@var{disp}, rtx *@var{offset}, machine_mode @var{mode})
+A target hook which returns @code{true} if *@var{disp} is
+legitimezed to valid address displacement with subtracting *@var{offset}
+at memory mode @var{mode}.
+The default version of this target hook returns @code{false}.
+This hook will benefit machines with limited base plus displacement
+addressing.
+@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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index a99cc72..20c0129 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -2483,6 +2483,8 @@ as below:
@hook TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
+@hook TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT
+
@hook TARGET_SPILL_CLASS
@hook TARGET_CSTORE_MODE
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 9e9539c..382281c 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -3015,6 +3015,32 @@ process_address_1 (int nop, bool check_only_p,
delete_insns_since (PREV_INSN (last_insn));
}
}
+ /* Try if target can split displacement into legitimite new disp
+ and offset. If it's the case, we replace the last insn with
+ insns for base + offset => new_reg and set new_reg + new disp
+ to *ad.inner. */
+ last_insn = get_last_insn ();
+ if ((set = single_set (last_insn)) != NULL_RTX
+ && GET_CODE (SET_SRC (set)) == PLUS
+ && REG_P (XEXP (SET_SRC (set), 0))
+ && REGNO (XEXP (SET_SRC (set), 0)) < FIRST_PSEUDO_REGISTER
+ && CONST_INT_P (XEXP (SET_SRC (set), 1)))
+ {
+ rtx addend, disp = XEXP (SET_SRC (set), 1);
+ if (targetm.legitimize_address_displacement (&disp, &addend,
+ ad.mode))
+ {
+ rtx_insn *new_insns;
+ start_sequence ();
+ lra_emit_add (new_reg, XEXP (SET_SRC (set), 0), addend);
+ new_insns = get_insns ();
+ end_sequence ();
+ new_reg = gen_rtx_PLUS (Pmode, new_reg, disp);
+ delete_insns_since (PREV_INSN (last_insn));
+ add_insn (new_insns);
+ insns = get_insns ();
+ }
+ }
end_sequence ();
emit_insn (insns);
*ad.inner = new_reg;
diff --git a/gcc/target.def b/gcc/target.def
index a380381..6258b3a 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5051,6 +5051,19 @@ 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 legitimize base plus
+ displacement addressing. */
+DEFHOOK
+(legitimize_address_displacement,
+ "A target hook which returns @code{true} if *@var{disp} is\n\
+legitimezed to valid address displacement with subtracting *@var{offset}\n\
+at memory mode @var{mode}.\n\
+The default version of this target hook returns @code{false}.\n\
+This hook will benefit machines with limited base plus displacement\n\
+addressing.",
+ bool, (rtx *disp, rtx *offset, machine_mode mode),
+ default_legitimize_address_displacement)
+
/* This target hook allows the backend to perform additional
processing while initializing for variable expansion. */
DEFHOOK
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 42fd82e..5e723b4 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -167,6 +167,14 @@ default_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
return x;
}
+bool
+default_legitimize_address_displacement (rtx *disp ATTRIBUTE_UNUSED,
+ rtx *offset ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
rtx
default_expand_builtin_saveregs (void)
{
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 9734220..26e4f5f 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -24,6 +24,8 @@ extern bool default_legitimate_address_p (machine_mode, rtx, bool);
extern void default_external_libcall (rtx);
extern rtx default_legitimize_address (rtx, rtx, machine_mode);
+extern bool default_legitimize_address_displacement (rtx *, rtx *,
+ machine_mode);
extern int default_unspec_may_trap_p (const_rtx, unsigned);
extern machine_mode default_promote_function_mode (const_tree, machine_mode,