]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add a target hook for sibcall epilogues
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Dec 2023 09:35:57 +0000 (09:35 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Dec 2023 09:35:57 +0000 (09:35 +0000)
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
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.md
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/function.cc
gcc/target.def

index 9edb5831611ecd95e3bc3e03b1a833d2a6627912..cc4210cd4567469864fbc6e6f12829492f45a739 100644 (file)
@@ -2502,7 +2502,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,
index d2718cc87b306e9673b166cc40e0af2ba72aa17b..b0b7d33714d1663da4b8e03c620af30ac14618c2 100644 (file)
@@ -888,7 +888,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);
index fca64daf2a013aa6f78a795dece373a7cc93b4b3..c864f4c0f6ff84c1987d407232f6961a0ff8a826 100644 (file)
@@ -7971,7 +7971,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)
 {
   aarch64_frame &frame = cfun->machine->frame;
   poly_int64 initial_adjust = frame.initial_adjust;
@@ -8102,7 +8102,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)
     {
       /* If the EH_RETURN_TAKEN_RTX flag is set then we need
         to unwind the stack and jump to the handler, otherwise
@@ -8137,7 +8137,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 (aarch_ra_sign_key)
        {
@@ -8155,7 +8155,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);
 }
 
@@ -26427,6 +26427,9 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_CONST_ANCHOR
 #define TARGET_CONST_ANCHOR 0x1000000
 
+#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"
index 4a3af6df7e7caf1fab9483239ce41845a92e23b7..202190c2cbf0a43b5d474c3fb76b666768b34a42 100644 (file)
   [(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;
   "
 )
index 6709c42a48f688747b324292da586e90937aece8..bc8ee04d7d59f324ee4cb6ffa43842c27128ba6f 100644 (file)
@@ -11898,6 +11898,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,
index d1d7cfafdcad2963ee739e2dbc1a7795fb4e7aa7..5f636abf9fc04ba90b3909d83330c672bf646ae2 100644 (file)
@@ -7786,6 +7786,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
index 704930160c3eee171343beb26ab652d640be1d51..89841787ff845496fa3bb160ef73efc192f8c97a 100644 (file)
@@ -6208,7 +6208,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);
@@ -6268,7 +6278,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
index 04715028460ad02e1149418e7f4681f934c9a40c..427fe526b5a06a0e2c00ae448f8de8dd304f16e8 100644 (file)
@@ -4174,6 +4174,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