summaryrefslogtreecommitdiff
path: root/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
diff options
context:
space:
mode:
Diffstat (limited to '0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch')
-rw-r--r--0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch239
1 files changed, 239 insertions, 0 deletions
diff --git a/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch b/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
new file mode 100644
index 0000000..d892432
--- /dev/null
+++ b/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
@@ -0,0 +1,239 @@
+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
+