* Add TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT target macro.
authorKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:43:11 +0000 (04:43 +0000)
committerKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:43:11 +0000 (04:43 +0000)
From-SVN: r218887

gcc/ChangeLog
gcc/config/sh/sh.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/lra-constraints.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h

index 315496c08a82010177c28cbb1878cacffdbd8730..b22e5aa36079b4652e8d0977dd8d1e19f22475df 100644 (file)
@@ -1,3 +1,15 @@
+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
index eb19c42894bb81f70ca356f0bece996d402b19ff..815f4d90a9f4b33cc81a2044149854c9865bd752 100644 (file)
@@ -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)
 {
index 50e80f642263da7ed67f82fb81728e215c0c9f8f..a3fda454ff91d175fbdcf94c07c4ef8308e1e40f 100644 (file)
@@ -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
index a99cc72b2e22d0771f665b7952fdc30719aaa670..20c0129de79d9b4a59b77a3a697d610cc9aabab4 100644 (file)
@@ -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
index 9e9539c1a845e7eaf3abd64e61eb67fef88592a4..382281c8dc802262330c53c69506c85d4dda9d55 100644 (file)
@@ -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;
index a380381695d1b44be5895887eca2aab8d95fa875..6258b3a7bec46b42100ef50addee68ceba6d831f 100644 (file)
@@ -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
index 42fd82e692b111cb6199c6648124df6c7aaa0a88..5e723b4d59ba0ceb1fb407f90159a67230a6bfbf 100644 (file)
@@ -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)
 {
index 9734220dea2f998ee17e2834695b8d9b698cc14d..26e4f5f2e3d18a03a66654ac4487aaec99afa839 100644 (file)
@@ -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,