summaryrefslogtreecommitdiff
path: root/0149-Backport-SME-Add-a-target-hook-for-sibcall-epilogues.patch
blob: d8924323e524e2e9a30da480983680e0b0e63648 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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