aarch64.c (aarch64_simd_call_p): New function.
authorSteve Ellcey <sellcey@marvell.com>
Fri, 11 Jan 2019 15:53:02 +0000 (15:53 +0000)
committerSteve Ellcey <sje@gcc.gnu.org>
Fri, 11 Jan 2019 15:53:02 +0000 (15:53 +0000)
2019-01-11  Steve Ellcey  <sellcey@marvell.com>

* config/aarch64/aarch64.c (aarch64_simd_call_p): New function.
(aarch64_remove_extra_call_preserved_regs): New function.
(TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): New macro.
* doc/tm.texi.in (TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): New hook.
* doc/tm.texi: Regenerate.
* final.c (get_call_reg_set_usage): Call new hook.
* target.def (remove_extra_call_preserved_regs): New hook.
* targhooks.c (default_remove_extra_call_preserved_regs): New function.
* targhooks.h (default_remove_extra_call_preserved_regs): New function.

From-SVN: r267846

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/final.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h

index 13b178471e052745df25be021f5abe3e72e1ccb0..4b5a67a857a1caf37ed86f61ec93e695bd1d952b 100644 (file)
@@ -1,3 +1,15 @@
+2019-01-11  Steve Ellcey  <sellcey@marvell.com>
+
+       * config/aarch64/aarch64.c (aarch64_simd_call_p): New function.
+       (aarch64_remove_extra_call_preserved_regs): New function.
+       (TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): New macro.
+       * doc/tm.texi.in (TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS): New hook.
+       * doc/tm.texi: Regenerate.
+       * final.c (get_call_reg_set_usage): Call new hook.
+       * target.def (remove_extra_call_preserved_regs): New hook.
+       * targhooks.c (default_remove_extra_call_preserved_regs): New function.
+       * targhooks.h (default_remove_extra_call_preserved_regs): New function.
+
 2019-01-11  Jakub Jelinek  <jakub@redhat.com>
 
        PR bootstrap/88714
index 1c300af19bc8a9aff9397de7c0ebbdb6d2b3d0e3..588fc80bbd7ccf8c3570656e151abc9ec130c03a 100644 (file)
@@ -1655,6 +1655,45 @@ aarch64_reg_save_mode (tree fndecl, unsigned regno)
           : (aarch64_simd_decl_p (fndecl) ? E_TFmode : E_DFmode);
 }
 
+/* Return true if the instruction is a call to a SIMD function, false
+   if it is not a SIMD function or if we do not know anything about
+   the function.  */
+
+static bool
+aarch64_simd_call_p (rtx_insn *insn)
+{
+  rtx symbol;
+  rtx call;
+  tree fndecl;
+
+  gcc_assert (CALL_P (insn));
+  call = get_call_rtx_from (insn);
+  symbol = XEXP (XEXP (call, 0), 0);
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return false;
+  fndecl = SYMBOL_REF_DECL (symbol);
+  if (!fndecl)
+    return false;
+
+  return aarch64_simd_decl_p (fndecl);
+}
+
+/* Implement TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS.  If INSN calls
+   a function that uses the SIMD ABI, take advantage of the extra
+   call-preserved registers that the ABI provides.  */
+
+void
+aarch64_remove_extra_call_preserved_regs (rtx_insn *insn,
+                                         HARD_REG_SET *return_set)
+{
+  if (aarch64_simd_call_p (insn))
+    {
+      for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+       if (FP_SIMD_SAVED_REGNUM_P (regno))
+         CLEAR_HARD_REG_BIT (*return_set, regno);
+    }
+}
+
 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  The callee only saves
    the lower 64 bits of a 128-bit register.  Tell the compiler the callee
    clobbers the top 64 bits when restoring the bottom 64 bits.  */
@@ -18825,6 +18864,10 @@ aarch64_libgcc_floating_mode_supported_p
 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
   aarch64_hard_regno_call_part_clobbered
 
+#undef TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS
+#define TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS \
+  aarch64_remove_extra_call_preserved_regs
+
 #undef TARGET_CONSTANT_ALIGNMENT
 #define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment
 
index ddde4a7287b8185b7b40c9351950c6d721a1086f..daf29f046c35db5e29258f1077b30c7aadcba7ce 100644 (file)
@@ -1905,6 +1905,18 @@ The default implementation returns false, which is correct
 for targets that don't have partly call-clobbered registers.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS (rtx_insn *@var{insn}, HARD_REG_SET *@var{used_regs})
+This hook removes registers from the set of call-clobbered registers
+ in @var{used_regs} if, contrary to the default rules, something guarantees
+ that @samp{insn} preserves those registers.  For example, some targets
+ support variant ABIs in which functions preserve more registers than
+ normal functions would.  Removing those extra registers from @var{used_regs}
+ can lead to better register allocation.
+ The default implementation does nothing, which is always safe.
+ Defining the hook is purely an optimization.
+@end deftypefn
+
 @findex fixed_regs
 @findex call_used_regs
 @findex global_regs
index 976a7009fa6d850a9f717d1e9dbf5ba82b2598c6..d9f40a1a5f37492e895d053aee2b1437471b4694 100644 (file)
@@ -1707,6 +1707,8 @@ of @code{CALL_USED_REGISTERS}.
 @cindex call-saved register
 @hook TARGET_HARD_REGNO_CALL_PART_CLOBBERED
 
+@hook TARGET_REMOVE_EXTRA_CALL_PRESERVED_REGS
+
 @findex fixed_regs
 @findex call_used_regs
 @findex global_regs
index 6dc1cd1b0c8c4bd764a7a77cd4ed6a1fe95603c0..f6edd6a1dfcd7ff752fd4ce411a29c51f3d85c60 100644 (file)
@@ -5095,7 +5095,7 @@ get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set,
          return true;
        }
     }
-
   COPY_HARD_REG_SET (*reg_set, default_set);
+  targetm.remove_extra_call_preserved_regs (insn, reg_set);
   return false;
 }
index 2aeb1ff844558beac1e431e45cf1b18a8bd20d02..e361c41d3def8848e030df4fdcc9334072f20e01 100644 (file)
@@ -5775,6 +5775,20 @@ for targets that don't have partly call-clobbered registers.",
  bool, (unsigned int regno, machine_mode mode),
  hook_bool_uint_mode_false)
 
+DEFHOOK
+(remove_extra_call_preserved_regs,
+ "This hook removes registers from the set of call-clobbered registers\n\
+ in @var{used_regs} if, contrary to the default rules, something guarantees\n\
+ that @samp{insn} preserves those registers.  For example, some targets\n\
+ support variant ABIs in which functions preserve more registers than\n\
+ normal functions would.  Removing those extra registers from @var{used_regs}\n\
+ can lead to better register allocation.\n\
+ \n\
+ The default implementation does nothing, which is always safe.\n\
+ Defining the hook is purely an optimization.",
+ void, (rtx_insn *insn, HARD_REG_SET *used_regs),
+ default_remove_extra_call_preserved_regs)
+
 /* Return the smallest number of different values for which it is best to
    use a jump-table instead of a tree of conditional branches.  */
 DEFHOOK
index 898848f6a822b4f31f065dcd9787089ff0529d24..6bd9767b4699c2f0b6e717dcc97fb1a201e5fd4a 100644 (file)
@@ -2374,4 +2374,9 @@ default_speculation_safe_value (machine_mode mode ATTRIBUTE_UNUSED,
   return result;
 }
 
+void
+default_remove_extra_call_preserved_regs (rtx_insn *, HARD_REG_SET *)
+{
+}
+
 #include "gt-targhooks.h"
index 3b6e404f0807c9d5fca135f0285f4859aa60bf35..01ee0be3c92866fd4034a43b0155240637472572 100644 (file)
@@ -284,5 +284,7 @@ extern tree default_preferred_else_value (unsigned, tree, unsigned, tree *);
 extern bool default_have_speculation_safe_value (bool);
 extern bool speculation_safe_value_not_needed (bool);
 extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);
+extern void default_remove_extra_call_preserved_regs (rtx_insn *,
+                                                     HARD_REG_SET *);
 
 #endif /* GCC_TARGHOOKS_H */