240 lines
8.5 KiB
Diff
240 lines
8.5 KiB
Diff
From e906213086639df81085a0101bf88fb66c1dbc2b Mon Sep 17 00:00:00 2001
|
|
From: Richard Sandiford <richard.sandiford@arm.com>
|
|
Date: Tue, 5 Dec 2023 09:35:57 +0000
|
|
Subject: [PATCH 050/157] [Backport][SME] Add a target hook for sibcall
|
|
epilogues
|
|
|
|
Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2e0aefa77157396acb48833407637303edba450a
|
|
|
|
Epilogues for sibling calls are generated using the
|
|
sibcall_epilogue pattern. One disadvantage of this approach
|
|
is that the target doesn't know which call the epilogue is for,
|
|
even though the code that generates the pattern has the call
|
|
to hand.
|
|
|
|
Although call instructions are currently rtxes, and so could be
|
|
passed as an operand to the pattern, the main point of introducing
|
|
rtx_insn was to move towards separating the rtx and insn types
|
|
(a good thing IMO). There also isn't an existing practice of
|
|
passing genuine instructions (as opposed to labels) to
|
|
instruction patterns.
|
|
|
|
This patch therefore adds a hook that can be defined as an
|
|
alternative to sibcall_epilogue. The advantage is that it
|
|
can be passed the call; the disadvantage is that it can't
|
|
use .md conveniences like generating instructions from
|
|
textual patterns (although most epilogues are too complex
|
|
to benefit much from that anyway).
|
|
|
|
gcc/
|
|
* doc/tm.texi.in: Add TARGET_EMIT_EPILOGUE_FOR_SIBCALL.
|
|
* doc/tm.texi: Regenerate.
|
|
* target.def (emit_epilogue_for_sibcall): New hook.
|
|
* calls.cc (can_implement_as_sibling_call_p): Use it.
|
|
* function.cc (thread_prologue_and_epilogue_insns): Likewise.
|
|
(reposition_prologue_and_epilogue_notes): Likewise.
|
|
* config/aarch64/aarch64-protos.h (aarch64_expand_epilogue): Take
|
|
an rtx_call_insn * rather than a bool.
|
|
* config/aarch64/aarch64.cc (aarch64_expand_epilogue): Likewise.
|
|
(TARGET_EMIT_EPILOGUE_FOR_SIBCALL): Define.
|
|
* config/aarch64/aarch64.md (epilogue): Update call.
|
|
(sibcall_epilogue): Delete.
|
|
---
|
|
gcc/calls.cc | 3 ++-
|
|
gcc/config/aarch64/aarch64-protos.h | 2 +-
|
|
gcc/config/aarch64/aarch64.cc | 11 +++++++----
|
|
gcc/config/aarch64/aarch64.md | 11 +----------
|
|
gcc/doc/tm.texi | 8 ++++++++
|
|
gcc/doc/tm.texi.in | 2 ++
|
|
gcc/function.cc | 15 +++++++++++++--
|
|
gcc/target.def | 9 +++++++++
|
|
8 files changed, 43 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/gcc/calls.cc b/gcc/calls.cc
|
|
index 4d0bc45be..c1db66883 100644
|
|
--- a/gcc/calls.cc
|
|
+++ b/gcc/calls.cc
|
|
@@ -2461,7 +2461,8 @@ can_implement_as_sibling_call_p (tree exp,
|
|
tree addr,
|
|
const args_size &args_size)
|
|
{
|
|
- if (!targetm.have_sibcall_epilogue ())
|
|
+ if (!targetm.have_sibcall_epilogue ()
|
|
+ && !targetm.emit_epilogue_for_sibcall)
|
|
{
|
|
maybe_complain_about_tail_call
|
|
(exp,
|
|
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
|
|
index 86e444a60..97984f3ab 100644
|
|
--- a/gcc/config/aarch64/aarch64-protos.h
|
|
+++ b/gcc/config/aarch64/aarch64-protos.h
|
|
@@ -887,7 +887,7 @@ const char * aarch64_gen_far_branch (rtx *, int, const char *, const char *);
|
|
const char * aarch64_output_probe_stack_range (rtx, rtx);
|
|
const char * aarch64_output_probe_sve_stack_clash (rtx, rtx, rtx, rtx);
|
|
void aarch64_err_no_fpadvsimd (machine_mode);
|
|
-void aarch64_expand_epilogue (bool);
|
|
+void aarch64_expand_epilogue (rtx_call_insn *);
|
|
rtx aarch64_ptrue_all (unsigned int);
|
|
opt_machine_mode aarch64_ptrue_all_mode (rtx);
|
|
rtx aarch64_convert_sve_data_to_pred (rtx, machine_mode, rtx);
|
|
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
|
|
index fd1114b52..055b436b1 100644
|
|
--- a/gcc/config/aarch64/aarch64.cc
|
|
+++ b/gcc/config/aarch64/aarch64.cc
|
|
@@ -10046,7 +10046,7 @@ aarch64_use_return_insn_p (void)
|
|
from a deallocated stack, and we optimize the unwind records by
|
|
emitting them all together if possible. */
|
|
void
|
|
-aarch64_expand_epilogue (bool for_sibcall)
|
|
+aarch64_expand_epilogue (rtx_call_insn *sibcall)
|
|
{
|
|
poly_int64 initial_adjust = cfun->machine->frame.initial_adjust;
|
|
HOST_WIDE_INT callee_adjust = cfun->machine->frame.callee_adjust;
|
|
@@ -10194,7 +10194,7 @@ aarch64_expand_epilogue (bool for_sibcall)
|
|
explicitly authenticate.
|
|
*/
|
|
if (aarch64_return_address_signing_enabled ()
|
|
- && (for_sibcall || !TARGET_ARMV8_3))
|
|
+ && (sibcall || !TARGET_ARMV8_3))
|
|
{
|
|
switch (aarch64_ra_sign_key)
|
|
{
|
|
@@ -10212,7 +10212,7 @@ aarch64_expand_epilogue (bool for_sibcall)
|
|
}
|
|
|
|
/* Stack adjustment for exception handler. */
|
|
- if (crtl->calls_eh_return && !for_sibcall)
|
|
+ if (crtl->calls_eh_return && !sibcall)
|
|
{
|
|
/* We need to unwind the stack by the offset computed by
|
|
EH_RETURN_STACKADJ_RTX. We have already reset the CFA
|
|
@@ -10223,7 +10223,7 @@ aarch64_expand_epilogue (bool for_sibcall)
|
|
}
|
|
|
|
emit_use (gen_rtx_REG (DImode, LR_REGNUM));
|
|
- if (!for_sibcall)
|
|
+ if (!sibcall)
|
|
emit_jump_insn (ret_rtx);
|
|
}
|
|
|
|
@@ -28246,6 +28246,9 @@ aarch64_libgcc_floating_mode_supported_p
|
|
#undef TARGET_HAVE_SHADOW_CALL_STACK
|
|
#define TARGET_HAVE_SHADOW_CALL_STACK true
|
|
|
|
+#undef TARGET_EMIT_EPILOGUE_FOR_SIBCALL
|
|
+#define TARGET_EMIT_EPILOGUE_FOR_SIBCALL aarch64_expand_epilogue
|
|
+
|
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
|
|
|
#include "gt-aarch64.h"
|
|
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
|
|
index 7267a74d6..a78476c8a 100644
|
|
--- a/gcc/config/aarch64/aarch64.md
|
|
+++ b/gcc/config/aarch64/aarch64.md
|
|
@@ -871,16 +871,7 @@
|
|
[(clobber (const_int 0))]
|
|
""
|
|
"
|
|
- aarch64_expand_epilogue (false);
|
|
- DONE;
|
|
- "
|
|
-)
|
|
-
|
|
-(define_expand "sibcall_epilogue"
|
|
- [(clobber (const_int 0))]
|
|
- ""
|
|
- "
|
|
- aarch64_expand_epilogue (true);
|
|
+ aarch64_expand_epilogue (nullptr);
|
|
DONE;
|
|
"
|
|
)
|
|
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
|
|
index d930d233d..369f4b8da 100644
|
|
--- a/gcc/doc/tm.texi
|
|
+++ b/gcc/doc/tm.texi
|
|
@@ -11703,6 +11703,14 @@ the hook might return true if the prologue and epilogue need to switch
|
|
between instruction sets.
|
|
@end deftypefn
|
|
|
|
+@deftypefn {Target Hook} void TARGET_EMIT_EPILOGUE_FOR_SIBCALL (rtx_call_insn *@var{call})
|
|
+If defined, this hook emits an epilogue sequence for sibling (tail)
|
|
+call instruction @var{call}. Another way of providing epilogues
|
|
+for sibling calls is to define the @code{sibcall_epilogue} instruction
|
|
+pattern; the main advantage of this hook over the pattern is that it
|
|
+has access to the call instruction.
|
|
+@end deftypefn
|
|
+
|
|
@deftypefn {Target Hook} void TARGET_MACHINE_DEPENDENT_REORG (void)
|
|
If non-null, this hook performs a target-specific pass over the
|
|
instruction stream. The compiler will run it at all optimization levels,
|
|
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
|
|
index 19eabec48..748b0777a 100644
|
|
--- a/gcc/doc/tm.texi.in
|
|
+++ b/gcc/doc/tm.texi.in
|
|
@@ -7710,6 +7710,8 @@ to by @var{ce_info}.
|
|
|
|
@hook TARGET_USE_LATE_PROLOGUE_EPILOGUE
|
|
|
|
+@hook TARGET_EMIT_EPILOGUE_FOR_SIBCALL
|
|
+
|
|
@hook TARGET_MACHINE_DEPENDENT_REORG
|
|
|
|
@hook TARGET_INIT_BUILTINS
|
|
diff --git a/gcc/function.cc b/gcc/function.cc
|
|
index 7c90b5f23..ddab43ca4 100644
|
|
--- a/gcc/function.cc
|
|
+++ b/gcc/function.cc
|
|
@@ -6209,7 +6209,17 @@ thread_prologue_and_epilogue_insns (void)
|
|
if (!(CALL_P (insn) && SIBLING_CALL_P (insn)))
|
|
continue;
|
|
|
|
- if (rtx_insn *ep_seq = targetm.gen_sibcall_epilogue ())
|
|
+ rtx_insn *ep_seq;
|
|
+ if (targetm.emit_epilogue_for_sibcall)
|
|
+ {
|
|
+ start_sequence ();
|
|
+ targetm.emit_epilogue_for_sibcall (as_a<rtx_call_insn *> (insn));
|
|
+ ep_seq = get_insns ();
|
|
+ end_sequence ();
|
|
+ }
|
|
+ else
|
|
+ ep_seq = targetm.gen_sibcall_epilogue ();
|
|
+ if (ep_seq)
|
|
{
|
|
start_sequence ();
|
|
emit_note (NOTE_INSN_EPILOGUE_BEG);
|
|
@@ -6259,7 +6269,8 @@ reposition_prologue_and_epilogue_notes (void)
|
|
{
|
|
if (!targetm.have_prologue ()
|
|
&& !targetm.have_epilogue ()
|
|
- && !targetm.have_sibcall_epilogue ())
|
|
+ && !targetm.have_sibcall_epilogue ()
|
|
+ && !targetm.emit_epilogue_for_sibcall)
|
|
return;
|
|
|
|
/* Since the hash table is created on demand, the fact that it is
|
|
diff --git a/gcc/target.def b/gcc/target.def
|
|
index fd4899612..cf9f96eba 100644
|
|
--- a/gcc/target.def
|
|
+++ b/gcc/target.def
|
|
@@ -4141,6 +4141,15 @@ between instruction sets.",
|
|
bool, (),
|
|
hook_bool_void_false)
|
|
|
|
+DEFHOOK
|
|
+(emit_epilogue_for_sibcall,
|
|
+ "If defined, this hook emits an epilogue sequence for sibling (tail)\n\
|
|
+call instruction @var{call}. Another way of providing epilogues\n\
|
|
+for sibling calls is to define the @code{sibcall_epilogue} instruction\n\
|
|
+pattern; the main advantage of this hook over the pattern is that it\n\
|
|
+has access to the call instruction.",
|
|
+ void, (rtx_call_insn *call), NULL)
|
|
+
|
|
/* Do machine-dependent code transformations. Called just before
|
|
delayed-branch scheduling. */
|
|
DEFHOOK
|
|
--
|
|
2.33.0
|
|
|