summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch')
-rw-r--r--meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch1570
1 files changed, 1570 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch b/meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch
new file mode 100644
index 0000000000..5354c77d6f
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-6.4/backport/0005-x86-Add-mfunction-return.patch
@@ -0,0 +1,1570 @@
1From e3270814b9e0caad63fbcdfd7ae9da2d52c97497 Mon Sep 17 00:00:00 2001
2From: "H.J. Lu" <hjl.tools@gmail.com>
3Date: Sat, 6 Jan 2018 22:29:56 -0800
4Subject: [PATCH 05/12] x86: Add -mfunction-return=
5
6Add -mfunction-return= option to convert function return to call and
7return thunks. The default is 'keep', which keeps function return
8unmodified. 'thunk' converts function return to call and return thunk.
9'thunk-inline' converts function return to inlined call and return thunk.
10'thunk-extern' converts function return to external call and return
11thunk provided in a separate object file. You can control this behavior
12for a specific function by using the function attribute function_return.
13
14Function return thunk is the same as memory thunk for -mindirect-branch=
15where the return address is at the top of the stack:
16
17__x86_return_thunk:
18 call L2
19L1:
20 pause
21 lfence
22 jmp L1
23L2:
24 lea 8(%rsp), %rsp|lea 4(%esp), %esp
25 ret
26
27and function return becomes
28
29 jmp __x86_return_thunk
30
31-mindirect-branch= tests are updated with -mfunction-return=keep to
32avoid false test failures when -mfunction-return=thunk is added to
33RUNTESTFLAGS for "make check".
34
35gcc/
36
37 Backport from mainline
38 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
39
40 * config/i386/i386-protos.h (ix86_output_function_return): New.
41 * config/i386/i386.c (ix86_set_indirect_branch_type): Also
42 set function_return_type.
43 (indirect_thunk_name): Add ret_p to indicate thunk for function
44 return.
45 (output_indirect_thunk_function): Pass false to
46 indirect_thunk_name.
47 (ix86_output_indirect_branch_via_reg): Likewise.
48 (ix86_output_indirect_branch_via_push): Likewise.
49 (output_indirect_thunk_function): Create alias for function
50 return thunk if regno < 0.
51 (ix86_output_function_return): New function.
52 (ix86_handle_fndecl_attribute): Handle function_return.
53 (ix86_attribute_table): Add function_return.
54 * config/i386/i386.h (machine_function): Add
55 function_return_type.
56 * config/i386/i386.md (simple_return_internal): Use
57 ix86_output_function_return.
58 (simple_return_internal_long): Likewise.
59 * config/i386/i386.opt (mfunction-return=): New option.
60 (indirect_branch): Mention -mfunction-return=.
61 * doc/extend.texi: Document function_return function attribute.
62 * doc/invoke.texi: Document -mfunction-return= option.
63
64gcc/testsuite/
65
66 Backport from mainline
67 2018-01-14 H.J. Lu <hongjiu.lu@intel.com>
68
69 * gcc.target/i386/indirect-thunk-1.c (dg-options): Add
70 -mfunction-return=keep.
71 * gcc.target/i386/indirect-thunk-2.c: Likewise.
72 * gcc.target/i386/indirect-thunk-3.c: Likewise.
73 * gcc.target/i386/indirect-thunk-4.c: Likewise.
74 * gcc.target/i386/indirect-thunk-5.c: Likewise.
75 * gcc.target/i386/indirect-thunk-6.c: Likewise.
76 * gcc.target/i386/indirect-thunk-7.c: Likewise.
77 * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
78 * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
79 * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
80 * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
81 * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
82 * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
83 * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
84 * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
85 * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
86 * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
87 * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
88 * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
89 * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
90 * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
91 * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
92 * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
93 * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
94 * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
95 * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
96 * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
97 * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
98 * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
99 * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
100 * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
101 * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
102 * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
103 * gcc.target/i386/ret-thunk-1.c: New test.
104 * gcc.target/i386/ret-thunk-10.c: Likewise.
105 * gcc.target/i386/ret-thunk-11.c: Likewise.
106 * gcc.target/i386/ret-thunk-12.c: Likewise.
107 * gcc.target/i386/ret-thunk-13.c: Likewise.
108 * gcc.target/i386/ret-thunk-14.c: Likewise.
109 * gcc.target/i386/ret-thunk-15.c: Likewise.
110 * gcc.target/i386/ret-thunk-16.c: Likewise.
111 * gcc.target/i386/ret-thunk-2.c: Likewise.
112 * gcc.target/i386/ret-thunk-3.c: Likewise.
113 * gcc.target/i386/ret-thunk-4.c: Likewise.
114 * gcc.target/i386/ret-thunk-5.c: Likewise.
115 * gcc.target/i386/ret-thunk-6.c: Likewise.
116 * gcc.target/i386/ret-thunk-7.c: Likewise.
117 * gcc.target/i386/ret-thunk-8.c: Likewise.
118 * gcc.target/i386/ret-thunk-9.c: Likewise.
119
120i386: Don't use ASM_OUTPUT_DEF for TARGET_MACHO
121
122ASM_OUTPUT_DEF isn't defined for TARGET_MACHO. Use ASM_OUTPUT_LABEL to
123generate the __x86_return_thunk label, instead of the set directive.
124Update testcase to remove the __x86_return_thunk label check. Since
125-fno-pic is ignored on Darwin, update testcases to sscan or "push"
126only on Linux.
127
128gcc/
129
130 Backport from mainline
131 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
132
133 PR target/83839
134 * config/i386/i386.c (output_indirect_thunk_function): Use
135 ASM_OUTPUT_LABEL, instead of ASM_OUTPUT_DEF, for TARGET_MACHO
136 for __x86.return_thunk.
137
138gcc/testsuite/
139
140 Backport from mainline
141 2018-01-15 H.J. Lu <hongjiu.lu@intel.com>
142
143 PR target/83839
144 * gcc.target/i386/indirect-thunk-1.c: Scan for "push" only on
145 Linux.
146 * gcc.target/i386/indirect-thunk-2.c: Likewise.
147 * gcc.target/i386/indirect-thunk-3.c: Likewise.
148 * gcc.target/i386/indirect-thunk-4.c: Likewise.
149 * gcc.target/i386/indirect-thunk-7.c: Likewise.
150 * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
151 * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
152 * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
153 * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
154 * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
155 * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
156 * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
157 * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
158 * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
159 * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
160 * gcc.target/i386/indirect-thunk-register-1.c: Likewise.
161 * gcc.target/i386/indirect-thunk-register-3.c: Likewise.
162 * gcc.target/i386/indirect-thunk-register-4.c: Likewise.
163 * gcc.target/i386/ret-thunk-10.c: Likewise.
164 * gcc.target/i386/ret-thunk-11.c: Likewise.
165 * gcc.target/i386/ret-thunk-12.c: Likewise.
166 * gcc.target/i386/ret-thunk-13.c: Likewise.
167 * gcc.target/i386/ret-thunk-14.c: Likewise.
168 * gcc.target/i386/ret-thunk-15.c: Likewise.
169 * gcc.target/i386/ret-thunk-9.c: Don't check the
170 __x86_return_thunk label.
171 Scan for "push" only for Linux.
172
173Upstream-Status: Pending
174
175Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
176
177---
178 gcc/config/i386/i386-protos.h | 1 +
179 gcc/config/i386/i386.c | 152 +++++++++++++++++++--
180 gcc/config/i386/i386.h | 3 +
181 gcc/config/i386/i386.md | 9 +-
182 gcc/config/i386/i386.opt | 6 +-
183 gcc/doc/extend.texi | 9 ++
184 gcc/doc/invoke.texi | 14 +-
185 gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 4 +-
186 gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 4 +-
187 gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 4 +-
188 gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 4 +-
189 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
190 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
191 gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 4 +-
192 .../gcc.target/i386/indirect-thunk-attr-1.c | 4 +-
193 .../gcc.target/i386/indirect-thunk-attr-2.c | 4 +-
194 .../gcc.target/i386/indirect-thunk-attr-3.c | 4 +-
195 .../gcc.target/i386/indirect-thunk-attr-4.c | 4 +-
196 .../gcc.target/i386/indirect-thunk-attr-5.c | 4 +-
197 .../gcc.target/i386/indirect-thunk-attr-6.c | 4 +-
198 .../gcc.target/i386/indirect-thunk-attr-7.c | 4 +-
199 .../gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
200 .../gcc.target/i386/indirect-thunk-bnd-1.c | 4 +-
201 .../gcc.target/i386/indirect-thunk-bnd-2.c | 4 +-
202 .../gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
203 .../gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
204 .../gcc.target/i386/indirect-thunk-extern-1.c | 4 +-
205 .../gcc.target/i386/indirect-thunk-extern-2.c | 4 +-
206 .../gcc.target/i386/indirect-thunk-extern-3.c | 4 +-
207 .../gcc.target/i386/indirect-thunk-extern-4.c | 4 +-
208 .../gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
209 .../gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
210 .../gcc.target/i386/indirect-thunk-extern-7.c | 4 +-
211 .../gcc.target/i386/indirect-thunk-inline-1.c | 4 +-
212 .../gcc.target/i386/indirect-thunk-inline-2.c | 4 +-
213 .../gcc.target/i386/indirect-thunk-inline-3.c | 4 +-
214 .../gcc.target/i386/indirect-thunk-inline-4.c | 4 +-
215 .../gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
216 .../gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
217 .../gcc.target/i386/indirect-thunk-inline-7.c | 4 +-
218 gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 13 ++
219 gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 23 ++++
220 gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 23 ++++
221 gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 22 +++
222 gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 22 +++
223 gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 22 +++
224 gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 22 +++
225 gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 18 +++
226 gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 13 ++
227 gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 12 ++
228 gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 12 ++
229 gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 15 ++
230 gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 14 ++
231 gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 13 ++
232 gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 14 ++
233 gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 24 ++++
234 56 files changed, 516 insertions(+), 74 deletions(-)
235 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-1.c
236 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-10.c
237 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-11.c
238 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-12.c
239 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-13.c
240 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-14.c
241 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-15.c
242 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-16.c
243 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-2.c
244 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-3.c
245 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-4.c
246 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-5.c
247 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-6.c
248 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-7.c
249 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-8.c
250 create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-9.c
251
252diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
253index eca4cbf..620d70e 100644
254--- a/gcc/config/i386/i386-protos.h
255+++ b/gcc/config/i386/i386-protos.h
256@@ -312,6 +312,7 @@ extern enum attr_cpu ix86_schedule;
257
258 extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
259 extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
260+extern const char * ix86_output_function_return (bool long_p);
261 extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
262 enum machine_mode mode);
263
264diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
265index 0b9fc4d..34e26a3 100644
266--- a/gcc/config/i386/i386.c
267+++ b/gcc/config/i386/i386.c
268@@ -6390,6 +6390,31 @@ ix86_set_indirect_branch_type (tree fndecl)
269 else
270 cfun->machine->indirect_branch_type = ix86_indirect_branch;
271 }
272+
273+ if (cfun->machine->function_return_type == indirect_branch_unset)
274+ {
275+ tree attr = lookup_attribute ("function_return",
276+ DECL_ATTRIBUTES (fndecl));
277+ if (attr != NULL)
278+ {
279+ tree args = TREE_VALUE (attr);
280+ if (args == NULL)
281+ gcc_unreachable ();
282+ tree cst = TREE_VALUE (args);
283+ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
284+ cfun->machine->function_return_type = indirect_branch_keep;
285+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
286+ cfun->machine->function_return_type = indirect_branch_thunk;
287+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
288+ cfun->machine->function_return_type = indirect_branch_thunk_inline;
289+ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
290+ cfun->machine->function_return_type = indirect_branch_thunk_extern;
291+ else
292+ gcc_unreachable ();
293+ }
294+ else
295+ cfun->machine->function_return_type = ix86_function_return;
296+ }
297 }
298
299 /* Establish appropriate back-end context for processing the function
300@@ -11036,8 +11061,12 @@ static int indirect_thunks_bnd_used;
301 /* Fills in the label name that should be used for the indirect thunk. */
302
303 static void
304-indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
305+indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
306+ bool ret_p)
307 {
308+ if (regno >= 0 && ret_p)
309+ gcc_unreachable ();
310+
311 if (USE_HIDDEN_LINKONCE)
312 {
313 const char *bnd = need_bnd_p ? "_bnd" : "";
314@@ -11052,7 +11081,10 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
315 bnd, reg_prefix, reg_names[regno]);
316 }
317 else
318- sprintf (name, "__x86_indirect_thunk%s", bnd);
319+ {
320+ const char *ret = ret_p ? "return" : "indirect";
321+ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
322+ }
323 }
324 else
325 {
326@@ -11065,10 +11097,20 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
327 }
328 else
329 {
330- if (need_bnd_p)
331- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
332+ if (ret_p)
333+ {
334+ if (need_bnd_p)
335+ ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
336+ else
337+ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
338+ }
339 else
340- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
341+ {
342+ if (need_bnd_p)
343+ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
344+ else
345+ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
346+ }
347 }
348 }
349 }
350@@ -11163,7 +11205,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
351 tree decl;
352
353 /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
354- indirect_thunk_name (name, regno, need_bnd_p);
355+ indirect_thunk_name (name, regno, need_bnd_p, false);
356 decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
357 get_identifier (name),
358 build_function_type_list (void_type_node, NULL_TREE));
359@@ -11206,6 +11248,36 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
360 ASM_OUTPUT_LABEL (asm_out_file, name);
361 }
362
363+ if (regno < 0)
364+ {
365+ /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
366+ char alias[32];
367+
368+ indirect_thunk_name (alias, regno, need_bnd_p, true);
369+#if TARGET_MACHO
370+ if (TARGET_MACHO)
371+ {
372+ fputs ("\t.weak_definition\t", asm_out_file);
373+ assemble_name (asm_out_file, alias);
374+ fputs ("\n\t.private_extern\t", asm_out_file);
375+ assemble_name (asm_out_file, alias);
376+ putc ('\n', asm_out_file);
377+ ASM_OUTPUT_LABEL (asm_out_file, alias);
378+ }
379+#else
380+ ASM_OUTPUT_DEF (asm_out_file, alias, name);
381+ if (USE_HIDDEN_LINKONCE)
382+ {
383+ fputs ("\t.globl\t", asm_out_file);
384+ assemble_name (asm_out_file, alias);
385+ putc ('\n', asm_out_file);
386+ fputs ("\t.hidden\t", asm_out_file);
387+ assemble_name (asm_out_file, alias);
388+ putc ('\n', asm_out_file);
389+ }
390+#endif
391+ }
392+
393 DECL_INITIAL (decl) = make_node (BLOCK);
394 current_function_decl = decl;
395 allocate_struct_function (decl, false);
396@@ -27687,7 +27759,7 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
397 else
398 indirect_thunks_used |= 1 << i;
399 }
400- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
401+ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
402 thunk_name = thunk_name_buf;
403 }
404 else
405@@ -27796,7 +27868,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
406 else
407 indirect_thunk_needed = true;
408 }
409- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
410+ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
411 thunk_name = thunk_name_buf;
412 }
413 else
414@@ -27931,6 +28003,46 @@ ix86_output_indirect_jmp (rtx call_op, bool ret_p)
415 return "%!jmp\t%A0";
416 }
417
418+/* Output function return. CALL_OP is the jump target. Add a REP
419+ prefix to RET if LONG_P is true and function return is kept. */
420+
421+const char *
422+ix86_output_function_return (bool long_p)
423+{
424+ if (cfun->machine->function_return_type != indirect_branch_keep)
425+ {
426+ char thunk_name[32];
427+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
428+
429+ if (cfun->machine->function_return_type
430+ != indirect_branch_thunk_inline)
431+ {
432+ bool need_thunk = (cfun->machine->function_return_type
433+ == indirect_branch_thunk);
434+ indirect_thunk_name (thunk_name, -1, need_bnd_p, true);
435+ if (need_bnd_p)
436+ {
437+ indirect_thunk_bnd_needed |= need_thunk;
438+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
439+ }
440+ else
441+ {
442+ indirect_thunk_needed |= need_thunk;
443+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
444+ }
445+ }
446+ else
447+ output_indirect_thunk (need_bnd_p, -1);
448+
449+ return "";
450+ }
451+
452+ if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
453+ return "%!ret";
454+
455+ return "rep%; ret";
456+}
457+
458 /* Output the assembly for a call instruction. */
459
460 const char *
461@@ -45461,6 +45573,28 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
462 }
463 }
464
465+ if (is_attribute_p ("function_return", name))
466+ {
467+ tree cst = TREE_VALUE (args);
468+ if (TREE_CODE (cst) != STRING_CST)
469+ {
470+ warning (OPT_Wattributes,
471+ "%qE attribute requires a string constant argument",
472+ name);
473+ *no_add_attrs = true;
474+ }
475+ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
476+ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
477+ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
478+ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
479+ {
480+ warning (OPT_Wattributes,
481+ "argument to %qE attribute is not "
482+ "(keep|thunk|thunk-inline|thunk-extern)", name);
483+ *no_add_attrs = true;
484+ }
485+ }
486+
487 return NULL_TREE;
488 }
489
490@@ -49690,6 +49824,8 @@ static const struct attribute_spec ix86_attribute_table[] =
491 ix86_handle_callee_pop_aggregate_return, true },
492 { "indirect_branch", 1, 1, true, false, false,
493 ix86_handle_fndecl_attribute, false },
494+ { "function_return", 1, 1, true, false, false,
495+ ix86_handle_fndecl_attribute, false },
496
497 /* End element. */
498 { NULL, 0, 0, false, false, false, NULL, false }
499diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
500index 9dccdb0..b34bc11 100644
501--- a/gcc/config/i386/i386.h
502+++ b/gcc/config/i386/i386.h
503@@ -2579,6 +2579,9 @@ struct GTY(()) machine_function {
504 "indirect_jump" or "tablejump". */
505 BOOL_BITFIELD has_local_indirect_jump : 1;
506
507+ /* How to generate function return. */
508+ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
509+
510 /* If true, there is register available for argument passing. This
511 is used only in ix86_function_ok_for_sibcall by 32-bit to determine
512 if there is scratch register available for indirect sibcall. In
513diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
514index 153e162..2da671e 100644
515--- a/gcc/config/i386/i386.md
516+++ b/gcc/config/i386/i386.md
517@@ -12489,7 +12489,7 @@
518 (define_insn "simple_return_internal"
519 [(simple_return)]
520 "reload_completed"
521- "%!ret"
522+ "* return ix86_output_function_return (false);"
523 [(set_attr "length" "1")
524 (set_attr "atom_unit" "jeu")
525 (set_attr "length_immediate" "0")
526@@ -12503,12 +12503,7 @@
527 [(simple_return)
528 (unspec [(const_int 0)] UNSPEC_REP)]
529 "reload_completed"
530-{
531- if (ix86_bnd_prefixed_insn_p (insn))
532- return "%!ret";
533-
534- return "rep%; ret";
535-}
536+ "* return ix86_output_function_return (true);"
537 [(set_attr "length" "2")
538 (set_attr "atom_unit" "jeu")
539 (set_attr "length_immediate" "0")
540diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
541index 5ffa334..ad5916f 100644
542--- a/gcc/config/i386/i386.opt
543+++ b/gcc/config/i386/i386.opt
544@@ -902,9 +902,13 @@ mindirect-branch=
545 Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
546 Convert indirect call and jump to call and return thunks.
547
548+mfunction-return=
549+Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
550+Convert function return to call and return thunk.
551+
552 Enum
553 Name(indirect_branch) Type(enum indirect_branch)
554-Known indirect branch choices (for use with the -mindirect-branch= option):
555+Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
556
557 EnumValue
558 Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
559diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
560index 8668dae..2cb6bd1 100644
561--- a/gcc/doc/extend.texi
562+++ b/gcc/doc/extend.texi
563@@ -5429,6 +5429,15 @@ call and jump to call and return thunk. @samp{thunk-inline} converts
564 indirect call and jump to inlined call and return thunk.
565 @samp{thunk-extern} converts indirect call and jump to external call
566 and return thunk provided in a separate object file.
567+
568+@item function_return("@var{choice}")
569+@cindex @code{function_return} function attribute, x86
570+On x86 targets, the @code{function_return} attribute causes the compiler
571+to convert function return with @var{choice}. @samp{keep} keeps function
572+return unmodified. @samp{thunk} converts function return to call and
573+return thunk. @samp{thunk-inline} converts function return to inlined
574+call and return thunk. @samp{thunk-extern} converts function return to
575+external call and return thunk provided in a separate object file.
576 @end table
577
578 On the x86, the inliner does not inline a
579diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
580index ff9a194..fa63dc5 100644
581--- a/gcc/doc/invoke.texi
582+++ b/gcc/doc/invoke.texi
583@@ -1169,7 +1169,8 @@ See RS/6000 and PowerPC Options.
584 -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
585 -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
586 -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
587--mmitigate-rop -mindirect-branch=@var{choice}}
588+-mmitigate-rop -mindirect-branch=@var{choice} @gol
589+-mfunction-return=@var{choice}}
590
591 @emph{x86 Windows Options}
592 @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
593@@ -24229,6 +24230,17 @@ to external call and return thunk provided in a separate object file.
594 You can control this behavior for a specific function by using the
595 function attribute @code{indirect_branch}. @xref{Function Attributes}.
596
597+@item -mfunction-return=@var{choice}
598+@opindex -mfunction-return
599+Convert function return with @var{choice}. The default is @samp{keep},
600+which keeps function return unmodified. @samp{thunk} converts function
601+return to call and return thunk. @samp{thunk-inline} converts function
602+return to inlined call and return thunk. @samp{thunk-extern} converts
603+function return to external call and return thunk provided in a separate
604+object file. You can control this behavior for a specific function by
605+using the function attribute @code{function_return}.
606+@xref{Function Attributes}.
607+
608 @end table
609
610 These @samp{-m} switches are supported in addition to the above
611diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
612index d983e1c..e365ef5 100644
613--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
614+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
615@@ -1,5 +1,5 @@
616 /* { dg-do compile } */
617-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
618+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
619
620 typedef void (*dispatch_t)(long offset);
621
622@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
623 dispatch(offset);
624 }
625
626-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
627+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
628 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
629 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
630 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
631diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
632index 58f09b4..05a51ad 100644
633--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
634+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
635@@ -1,5 +1,5 @@
636 /* { dg-do compile } */
637-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
638+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
639
640 typedef void (*dispatch_t)(long offset);
641
642@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
643 dispatch[offset](offset);
644 }
645
646-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
647+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
648 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
649 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
650 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
651diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
652index f20d35c..3c0d4c3 100644
653--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
654+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
655@@ -1,5 +1,5 @@
656 /* { dg-do compile } */
657-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
658+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
659
660 typedef void (*dispatch_t)(long offset);
661
662@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
663 return 0;
664 }
665
666-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
667+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
668 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
669 /* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
670 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
671diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
672index 0eff8fb..14d4ef6 100644
673--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
674+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
675@@ -1,5 +1,5 @@
676 /* { dg-do compile } */
677-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
678+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
679
680 typedef void (*dispatch_t)(long offset);
681
682@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
683 return 0;
684 }
685
686-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
687+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
688 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
689 /* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
690 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
691diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
692index a25b20d..b4836c3 100644
693--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
694+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
695@@ -1,5 +1,5 @@
696 /* { dg-do compile { target *-*-linux* } } */
697-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
698+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
699
700 extern void bar (void);
701
702diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
703index cff114a..1f06bd1 100644
704--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
705+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
706@@ -1,5 +1,5 @@
707 /* { dg-do compile { target *-*-linux* } } */
708-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
709+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
710
711 extern void bar (void);
712
713diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
714index afdb600..bc6b47a 100644
715--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
716+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
717@@ -1,5 +1,5 @@
718 /* { dg-do compile } */
719-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
720+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
721
722 void func0 (void);
723 void func1 (void);
724@@ -35,7 +35,7 @@ bar (int i)
725 }
726 }
727
728-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
729+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */
730 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
731 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
732 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
733diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
734index d64d978..2257be3 100644
735--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
736+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
737@@ -1,5 +1,5 @@
738 /* { dg-do compile } */
739-/* { dg-options "-O2 -fno-pic" } */
740+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
741
742 typedef void (*dispatch_t)(long offset);
743
744@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
745 dispatch(offset);
746 }
747
748-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
749+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
750 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
751 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
752 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
753diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
754index 9306745..e9cfdc5 100644
755--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
756+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
757@@ -1,5 +1,5 @@
758 /* { dg-do compile } */
759-/* { dg-options "-O2 -fno-pic" } */
760+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
761
762 typedef void (*dispatch_t)(long offset);
763
764@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
765 dispatch[offset](offset);
766 }
767
768-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
769+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
770 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
771 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
772 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
773diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
774index 97744d6..f938db0 100644
775--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
776+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
777@@ -1,5 +1,5 @@
778 /* { dg-do compile } */
779-/* { dg-options "-O2 -fno-pic" } */
780+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
781
782 typedef void (*dispatch_t)(long offset);
783
784@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
785 return 0;
786 }
787
788-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
789+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
790 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
791 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
792 /* { dg-final { scan-assembler {\tpause} } } */
793diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
794index bfce3ea..4e58599 100644
795--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
796+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
797@@ -1,5 +1,5 @@
798 /* { dg-do compile } */
799-/* { dg-options "-O2 -fno-pic" } */
800+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
801
802 typedef void (*dispatch_t)(long offset);
803
804@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
805 return 0;
806 }
807
808-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
809+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
810 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
811 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
812 /* { dg-final { scan-assembler {\tpause} } } */
813diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
814index 0833606..b8d5024 100644
815--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
816+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
817@@ -1,5 +1,5 @@
818 /* { dg-do compile } */
819-/* { dg-options "-O2 -fno-pic" } */
820+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
821
822 typedef void (*dispatch_t)(long offset);
823
824@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
825 return 0;
826 }
827
828-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
829+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
830 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
831 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
832 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
833diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
834index 2eba0fb..455adab 100644
835--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
836+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
837@@ -1,5 +1,5 @@
838 /* { dg-do compile } */
839-/* { dg-options "-O2 -fno-pic" } */
840+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
841
842 typedef void (*dispatch_t)(long offset);
843
844@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
845 return 0;
846 }
847
848-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
849+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
850 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
851 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
852 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
853diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
854index f58427e..4595b84 100644
855--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
856+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
857@@ -1,5 +1,5 @@
858 /* { dg-do compile } */
859-/* { dg-options "-O2 -fno-pic" } */
860+/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
861
862 void func0 (void);
863 void func1 (void);
864@@ -36,7 +36,7 @@ bar (int i)
865 }
866 }
867
868-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
869+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */
870 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
871 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
872 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
873diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
874index 564ed39..d730d31 100644
875--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
876+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
877@@ -1,5 +1,5 @@
878 /* { dg-do compile } */
879-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
880+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
881
882 void func0 (void);
883 void func1 (void);
884diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
885index 50fbee2..5e3e118 100644
886--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
887+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
888@@ -1,5 +1,5 @@
889 /* { dg-do compile { target { ! x32 } } } */
890-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
891+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
892
893 void (*dispatch) (char *);
894 char buf[10];
895@@ -10,7 +10,7 @@ foo (void)
896 dispatch (buf);
897 }
898
899-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
900+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
901 /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
902 /* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
903 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
904diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
905index 2976e67..2801aa4 100644
906--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
907+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
908@@ -1,5 +1,5 @@
909 /* { dg-do compile { target { ! x32 } } } */
910-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
911+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
912
913 void (*dispatch) (char *);
914 char buf[10];
915@@ -11,7 +11,7 @@ foo (void)
916 return 0;
917 }
918
919-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
920+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
921 /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
922 /* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
923 /* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
924diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
925index da4bc98..70b4fb3 100644
926--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
927+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
928@@ -1,5 +1,5 @@
929 /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
930-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
931+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
932
933 void bar (char *);
934 char buf[10];
935diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
936index c64d12e..3baf03e 100644
937--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
938+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
939@@ -1,5 +1,5 @@
940 /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
941-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
942+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
943
944 void bar (char *);
945 char buf[10];
946diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
947index 49f27b4..edeb264 100644
948--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
949+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
950@@ -1,5 +1,5 @@
951 /* { dg-do compile } */
952-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
953+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
954
955 typedef void (*dispatch_t)(long offset);
956
957@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
958 dispatch(offset);
959 }
960
961-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
962+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
963 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
964 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
965 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
966diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
967index a1e3eb6..1d00413 100644
968--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
969+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
970@@ -1,5 +1,5 @@
971 /* { dg-do compile } */
972-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
973+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
974
975 typedef void (*dispatch_t)(long offset);
976
977@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
978 dispatch[offset](offset);
979 }
980
981-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
982+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
983 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
984 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
985 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
986diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
987index 395634e..06ebf1c 100644
988--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
989+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
990@@ -1,5 +1,5 @@
991 /* { dg-do compile } */
992-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
993+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
994
995 typedef void (*dispatch_t)(long offset);
996
997@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
998 return 0;
999 }
1000
1001-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1002+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1003 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1004 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
1005 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
1006diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
1007index fd3f633..1c8f944 100644
1008--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
1009+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
1010@@ -1,5 +1,5 @@
1011 /* { dg-do compile } */
1012-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
1013+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
1014
1015 typedef void (*dispatch_t)(long offset);
1016
1017@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
1018 return 0;
1019 }
1020
1021-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1022+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1023 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1024 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
1025 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
1026diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
1027index ba2f92b..21740ac 100644
1028--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
1029+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
1030@@ -1,5 +1,5 @@
1031 /* { dg-do compile { target *-*-linux* } } */
1032-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
1033+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
1034
1035 extern void bar (void);
1036
1037diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
1038index 0c5a2d4..a77c1f4 100644
1039--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
1040+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
1041@@ -1,5 +1,5 @@
1042 /* { dg-do compile { target *-*-linux* } } */
1043-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
1044+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
1045
1046 extern void bar (void);
1047
1048diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
1049index 6652523..86e9fd1 100644
1050--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
1051+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
1052@@ -1,5 +1,5 @@
1053 /* { dg-do compile } */
1054-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
1055+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
1056
1057 void func0 (void);
1058 void func1 (void);
1059@@ -35,7 +35,7 @@ bar (int i)
1060 }
1061 }
1062
1063-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
1064+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */
1065 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1066 /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
1067 /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1068diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
1069index 68c0ff7..3ecde87 100644
1070--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
1071+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
1072@@ -1,5 +1,5 @@
1073 /* { dg-do compile } */
1074-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
1075+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1076
1077 typedef void (*dispatch_t)(long offset);
1078
1079@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
1080 dispatch(offset);
1081 }
1082
1083-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1084+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1085 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1086 /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1087 /* { dg-final { scan-assembler {\tpause} } } */
1088diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
1089index e2da1fc..df32a19 100644
1090--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
1091+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
1092@@ -1,5 +1,5 @@
1093 /* { dg-do compile } */
1094-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
1095+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1096
1097 typedef void (*dispatch_t)(long offset);
1098
1099@@ -11,7 +11,7 @@ male_indirect_jump (long offset)
1100 dispatch[offset](offset);
1101 }
1102
1103-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1104+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1105 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1106 /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1107 /* { dg-final { scan-assembler {\tpause} } } */
1108diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
1109index 244fec7..9540996 100644
1110--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
1111+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
1112@@ -1,5 +1,5 @@
1113 /* { dg-do compile } */
1114-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
1115+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1116
1117 typedef void (*dispatch_t)(long offset);
1118
1119@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
1120 return 0;
1121 }
1122
1123-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1124+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1125 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
1126 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
1127 /* { dg-final { scan-assembler-times {\tpause} 1 } } */
1128diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
1129index 107ebe3..f3db6e2 100644
1130--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
1131+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
1132@@ -1,5 +1,5 @@
1133 /* { dg-do compile } */
1134-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
1135+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1136
1137 typedef void (*dispatch_t)(long offset);
1138
1139@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
1140 return 0;
1141 }
1142
1143-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
1144+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */
1145 /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
1146 /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
1147 /* { dg-final { scan-assembler-times {\tpause} 1 } } */
1148diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
1149index 17b04ef..0f687c3 100644
1150--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
1151+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
1152@@ -1,5 +1,5 @@
1153 /* { dg-do compile { target *-*-linux* } } */
1154-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
1155+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
1156
1157 extern void bar (void);
1158
1159diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
1160index d9eb112..b27c6fc 100644
1161--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
1162+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
1163@@ -1,5 +1,5 @@
1164 /* { dg-do compile { target *-*-linux* } } */
1165-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
1166+/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
1167
1168 extern void bar (void);
1169
1170diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
1171index d02b1dc..764a375 100644
1172--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
1173+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
1174@@ -1,5 +1,5 @@
1175 /* { dg-do compile } */
1176-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
1177+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1178
1179 void func0 (void);
1180 void func1 (void);
1181@@ -35,7 +35,7 @@ bar (int i)
1182 }
1183 }
1184
1185-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
1186+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */
1187 /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1188 /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1189 /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1190diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
1191new file mode 100644
1192index 0000000..7223f67
1193--- /dev/null
1194+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
1195@@ -0,0 +1,13 @@
1196+/* { dg-do compile } */
1197+/* { dg-options "-O2 -mfunction-return=thunk" } */
1198+
1199+void
1200+foo (void)
1201+{
1202+}
1203+
1204+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1205+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1206+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1207+/* { dg-final { scan-assembler {\tpause} } } */
1208+/* { dg-final { scan-assembler {\tlfence} } } */
1209diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
1210new file mode 100644
1211index 0000000..3a6727b
1212--- /dev/null
1213+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
1214@@ -0,0 +1,23 @@
1215+/* { dg-do compile } */
1216+/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
1217+
1218+extern void (*bar) (void);
1219+
1220+int
1221+foo (void)
1222+{
1223+ bar ();
1224+ return 0;
1225+}
1226+
1227+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1228+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1229+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1230+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
1231+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
1232+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1233+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1234+/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
1235+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1236+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
1237+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1238diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
1239new file mode 100644
1240index 0000000..b8f6818
1241--- /dev/null
1242+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
1243@@ -0,0 +1,23 @@
1244+/* { dg-do compile } */
1245+/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
1246+
1247+extern void (*bar) (void);
1248+
1249+int
1250+foo (void)
1251+{
1252+ bar ();
1253+ return 0;
1254+}
1255+
1256+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1257+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
1258+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
1259+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1260+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1261+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1262+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1263+/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
1264+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1265+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
1266+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1267diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
1268new file mode 100644
1269index 0000000..01b0a02
1270--- /dev/null
1271+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
1272@@ -0,0 +1,22 @@
1273+/* { dg-do compile } */
1274+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
1275+
1276+extern void (*bar) (void);
1277+
1278+int
1279+foo (void)
1280+{
1281+ bar ();
1282+ return 0;
1283+}
1284+
1285+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1286+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
1287+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
1288+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1289+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1290+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1291+/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
1292+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1293+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
1294+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1295diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
1296new file mode 100644
1297index 0000000..4b497b5
1298--- /dev/null
1299+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
1300@@ -0,0 +1,22 @@
1301+/* { dg-do compile } */
1302+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
1303+
1304+extern void (*bar) (void);
1305+extern int foo (void) __attribute__ ((function_return("thunk")));
1306+
1307+int
1308+foo (void)
1309+{
1310+ bar ();
1311+ return 0;
1312+}
1313+
1314+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1315+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
1316+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
1317+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1318+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 3 } } */
1319+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 3 } } */
1320+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
1321+/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1322+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1323diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
1324new file mode 100644
1325index 0000000..4ae4c44
1326--- /dev/null
1327+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
1328@@ -0,0 +1,22 @@
1329+/* { dg-do compile } */
1330+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
1331+
1332+extern void (*bar) (void);
1333+
1334+__attribute__ ((function_return("thunk-inline")))
1335+int
1336+foo (void)
1337+{
1338+ bar ();
1339+ return 0;
1340+}
1341+
1342+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
1343+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
1344+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1345+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1346+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1347+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1348+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1349+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1350+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1351diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
1352new file mode 100644
1353index 0000000..5b5bc76
1354--- /dev/null
1355+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
1356@@ -0,0 +1,22 @@
1357+/* { dg-do compile } */
1358+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
1359+
1360+extern void (*bar) (void);
1361+
1362+__attribute__ ((function_return("thunk-extern"), indirect_branch("thunk")))
1363+int
1364+foo (void)
1365+{
1366+ bar ();
1367+ return 0;
1368+}
1369+
1370+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1371+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1372+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1373+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
1374+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
1375+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1376+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1377+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
1378+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1379diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
1380new file mode 100644
1381index 0000000..a16cad1
1382--- /dev/null
1383+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
1384@@ -0,0 +1,18 @@
1385+/* { dg-do compile } */
1386+/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk-extern -fno-pic" } */
1387+
1388+extern void (*bar) (void);
1389+
1390+__attribute__ ((function_return("keep"), indirect_branch("keep")))
1391+int
1392+foo (void)
1393+{
1394+ bar ();
1395+ return 0;
1396+}
1397+
1398+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
1399+/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
1400+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1401+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
1402+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
1403diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
1404new file mode 100644
1405index 0000000..c6659e3
1406--- /dev/null
1407+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
1408@@ -0,0 +1,13 @@
1409+/* { dg-do compile } */
1410+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
1411+
1412+void
1413+foo (void)
1414+{
1415+}
1416+
1417+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1418+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1419+/* { dg-final { scan-assembler {\tpause} } } */
1420+/* { dg-final { scan-assembler {\tlfence} } } */
1421+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1422diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
1423new file mode 100644
1424index 0000000..0f7f388
1425--- /dev/null
1426+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
1427@@ -0,0 +1,12 @@
1428+/* { dg-do compile } */
1429+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
1430+
1431+void
1432+foo (void)
1433+{
1434+}
1435+
1436+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1437+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1438+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
1439+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
1440diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
1441new file mode 100644
1442index 0000000..9ae37e8
1443--- /dev/null
1444+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
1445@@ -0,0 +1,12 @@
1446+/* { dg-do compile } */
1447+/* { dg-options "-O2 -mfunction-return=keep" } */
1448+
1449+void
1450+foo (void)
1451+{
1452+}
1453+
1454+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1455+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1456+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
1457+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
1458diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
1459new file mode 100644
1460index 0000000..4bd0d2a
1461--- /dev/null
1462+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
1463@@ -0,0 +1,15 @@
1464+/* { dg-do compile } */
1465+/* { dg-options "-O2 -mfunction-return=keep" } */
1466+
1467+extern void foo (void) __attribute__ ((function_return("thunk")));
1468+
1469+void
1470+foo (void)
1471+{
1472+}
1473+
1474+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1475+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1476+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1477+/* { dg-final { scan-assembler {\tpause} } } */
1478+/* { dg-final { scan-assembler {\tlfence} } } */
1479diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
1480new file mode 100644
1481index 0000000..053841f
1482--- /dev/null
1483+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
1484@@ -0,0 +1,14 @@
1485+/* { dg-do compile } */
1486+/* { dg-options "-O2 -mfunction-return=keep" } */
1487+
1488+__attribute__ ((function_return("thunk-inline")))
1489+void
1490+foo (void)
1491+{
1492+}
1493+
1494+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1495+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1496+/* { dg-final { scan-assembler {\tpause} } } */
1497+/* { dg-final { scan-assembler {\tlfence} } } */
1498+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1499diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
1500new file mode 100644
1501index 0000000..262e678
1502--- /dev/null
1503+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
1504@@ -0,0 +1,13 @@
1505+/* { dg-do compile } */
1506+/* { dg-options "-O2 -mfunction-return=keep" } */
1507+
1508+__attribute__ ((function_return("thunk-extern")))
1509+void
1510+foo (void)
1511+{
1512+}
1513+
1514+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1515+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1516+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
1517+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
1518diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
1519new file mode 100644
1520index 0000000..c1658e9
1521--- /dev/null
1522+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
1523@@ -0,0 +1,14 @@
1524+/* { dg-do compile } */
1525+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
1526+
1527+extern void foo (void) __attribute__ ((function_return("keep")));
1528+
1529+void
1530+foo (void)
1531+{
1532+}
1533+
1534+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
1535+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
1536+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
1537+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
1538diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
1539new file mode 100644
1540index 0000000..fa24a1f
1541--- /dev/null
1542+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
1543@@ -0,0 +1,24 @@
1544+/* { dg-do compile } */
1545+/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
1546+
1547+extern void (*bar) (void);
1548+
1549+int
1550+foo (void)
1551+{
1552+ bar ();
1553+ return 0;
1554+}
1555+
1556+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
1557+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
1558+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
1559+/* { dg-final { scan-assembler "__x86_indirect_thunk:" } } */
1560+/* { dg-final { scan-assembler-times {\tpause} 1 { target { ! x32 } } } } */
1561+/* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */
1562+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */
1563+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
1564+/* { dg-final { scan-assembler-times {\tpause} 2 { target { x32 } } } } */
1565+/* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
1566+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
1567+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
1568--
15692.7.4
1570