This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC PATCH 4/9] Add TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT target macro
- From: Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Oleg Endo <oleg dot endo at t-online dot de>
- Date: Thu, 18 Dec 2014 10:00:46 +0900 (JST)
- Subject: [RFC PATCH 4/9] Add TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT target macro
- Authentication-results: sourceware.org; auth=none
This patch adds a target macro discussed in PR55212
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55212#c76
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55212#c78
is to avoid bad codes on SH.
SH has very limited base+displacement addressing and it looks
that the old reload has some mechanism so to split
reg := mem[base + bad_displacement]
to
new_base := base + (bad_displacement - legitimate_displacement)
reg := mem[new_base + legitimate_displacement]
The new target macro is to give same effect on LRA.
This helps SH especially for the address like stack_pointer + offset
where offset has 4-bit except for SH2A.
I've tried to define this target macro for ARM thumb and found
only one CSiBE test replaypc-0.4.0.preproc/build-ndx is improved
at 4 bytes with -Os. I guess that 8-bit offset field for sp+offset
addressing on ARM thumb is very good for this issue.
Again it would be better if something can cover this case without
new target macros.
--
* 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.
diff --git a/lra-constraints.c b/lra-constraints.c
index 1666380..7bdb288 100644
--- a/lra-constraints.c
+++ b/lra-constraints.c
@@ -3009,6 +3009,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/target.def b/target.def
index b0c86b8..c21c9e3 100644
--- a/target.def
+++ b/target.def
@@ -5051,6 +5051,19 @@ 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/targhooks.c b/targhooks.c
index 42fd82e..5e723b4 100644
--- a/targhooks.c
+++ b/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/targhooks.h b/targhooks.h
index 9734220..26e4f5f 100644
--- a/targhooks.h
+++ b/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,
diff --git a/config/sh/sh.c b/config/sh/sh.c
index c445199..6f34b33 100644
--- a/config/sh/sh.c
+++ b/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 +636,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 +13242,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/doc/tm.texi.in b/doc/tm.texi.in
index a99cc72..20c0129 100644
--- a/doc/tm.texi.in
+++ b/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