From 14133a4d8ab6d9ccd7e7e2e827f4451180a7e17a Mon Sep 17 00:00:00 2001 From: Kaz Kojima Date: Fri, 19 Dec 2014 04:43:11 +0000 Subject: [PATCH] * Add TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT target macro. From-SVN: r218887 --- gcc/ChangeLog | 12 ++++++++++++ gcc/config/sh/sh.c | 28 ++++++++++++++++++++++++++++ gcc/doc/tm.texi | 9 +++++++++ gcc/doc/tm.texi.in | 2 ++ gcc/lra-constraints.c | 26 ++++++++++++++++++++++++++ gcc/target.def | 13 +++++++++++++ gcc/targhooks.c | 8 ++++++++ gcc/targhooks.h | 2 ++ 8 files changed, 100 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 315496c08a8..b22e5aa3607 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-12-19 Kaz Kojima + + * 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 * lra-constraints.c (get_equiv): Don't return memory equivalence diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index eb19c42894b..815f4d90a9f 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 50e80f64226..a3fda454ff9 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 a99cc72b2e2..20c0129de79 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 9e9539c1a84..382281c8dc8 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 a380381695d..6258b3a7bec 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 42fd82e692b..5e723b4d59b 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 9734220dea2..26e4f5f2e3d 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, -- 2.30.2