diff options
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-6.4/backport/0011-i386-Update-mfunction-return-for-return-with-pop.patch')
-rw-r--r-- | meta/recipes-devtools/gcc/gcc-6.4/backport/0011-i386-Update-mfunction-return-for-return-with-pop.patch | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-6.4/backport/0011-i386-Update-mfunction-return-for-return-with-pop.patch b/meta/recipes-devtools/gcc/gcc-6.4/backport/0011-i386-Update-mfunction-return-for-return-with-pop.patch new file mode 100644 index 0000000000..3b036fbe18 --- /dev/null +++ b/meta/recipes-devtools/gcc/gcc-6.4/backport/0011-i386-Update-mfunction-return-for-return-with-pop.patch | |||
@@ -0,0 +1,453 @@ | |||
1 | From b3a2269c7884378a9afd394ac7e669aab0443b57 Mon Sep 17 00:00:00 2001 | ||
2 | From: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | ||
3 | Date: Mon, 26 Feb 2018 15:29:30 +0000 | ||
4 | Subject: [PATCH 11/12] i386: Update -mfunction-return= for return with pop | ||
5 | |||
6 | When -mfunction-return= is used, simple_return_pop_internal should pop | ||
7 | return address into ECX register, adjust stack by bytes to pop from stack | ||
8 | and jump to the return thunk via ECX register. | ||
9 | |||
10 | Revision 257992 removed the bool argument from ix86_output_indirect_jmp. | ||
11 | Update comments to reflect it. | ||
12 | |||
13 | Tested on i686 and x86-64. | ||
14 | |||
15 | Backport from mainline | ||
16 | * config/i386/i386.c (ix86_output_indirect_jmp): Update comments. | ||
17 | |||
18 | PR target/84530 | ||
19 | * config/i386/i386-protos.h (ix86_output_indirect_jmp): Remove | ||
20 | the bool argument. | ||
21 | (ix86_output_indirect_function_return): New prototype. | ||
22 | (ix86_split_simple_return_pop_internal): Likewise. | ||
23 | * config/i386/i386.c (indirect_return_via_cx): New. | ||
24 | (indirect_return_via_cx_bnd): Likewise. | ||
25 | (indirect_thunk_name): Handle return va CX_REG. | ||
26 | (output_indirect_thunk_function): Create alias for | ||
27 | __x86_return_thunk_[re]cx and __x86_return_thunk_[re]cx_bnd. | ||
28 | (ix86_output_indirect_jmp): Remove the bool argument. | ||
29 | (ix86_output_indirect_function_return): New function. | ||
30 | (ix86_split_simple_return_pop_internal): Likewise. | ||
31 | * config/i386/i386.md (*indirect_jump): Don't pass false | ||
32 | to ix86_output_indirect_jmp. | ||
33 | (*tablejump_1): Likewise. | ||
34 | (simple_return_pop_internal): Change it to define_insn_and_split. | ||
35 | Call ix86_split_simple_return_pop_internal to split it for | ||
36 | -mfunction-return=. | ||
37 | (simple_return_indirect_internal): Call | ||
38 | ix86_output_indirect_function_return instead of | ||
39 | ix86_output_indirect_jmp. | ||
40 | |||
41 | gcc/testsuite/ | ||
42 | |||
43 | Backport from mainline | ||
44 | PR target/84530 | ||
45 | * gcc.target/i386/ret-thunk-22.c: New test. | ||
46 | * gcc.target/i386/ret-thunk-23.c: Likewise. | ||
47 | * gcc.target/i386/ret-thunk-24.c: Likewise. | ||
48 | * gcc.target/i386/ret-thunk-25.c: Likewise. | ||
49 | * gcc.target/i386/ret-thunk-26.c: Likewise. | ||
50 | |||
51 | Upstream-Status: Pending | ||
52 | |||
53 | Signed-off-by: Juro Bystricky <juro.bystricky@intel.com> | ||
54 | |||
55 | --- | ||
56 | gcc/config/i386/i386-protos.h | 4 +- | ||
57 | gcc/config/i386/i386.c | 127 +++++++++++++++++++++++---- | ||
58 | gcc/config/i386/i386.md | 11 ++- | ||
59 | gcc/testsuite/gcc.target/i386/ret-thunk-22.c | 15 ++++ | ||
60 | gcc/testsuite/gcc.target/i386/ret-thunk-23.c | 15 ++++ | ||
61 | gcc/testsuite/gcc.target/i386/ret-thunk-24.c | 15 ++++ | ||
62 | gcc/testsuite/gcc.target/i386/ret-thunk-25.c | 15 ++++ | ||
63 | gcc/testsuite/gcc.target/i386/ret-thunk-26.c | 40 +++++++++ | ||
64 | 8 files changed, 222 insertions(+), 20 deletions(-) | ||
65 | create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-22.c | ||
66 | create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-23.c | ||
67 | create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-24.c | ||
68 | create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-25.c | ||
69 | create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-26.c | ||
70 | |||
71 | diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h | ||
72 | index 620d70e..c7a0ccb5 100644 | ||
73 | --- a/gcc/config/i386/i386-protos.h | ||
74 | +++ b/gcc/config/i386/i386-protos.h | ||
75 | @@ -311,8 +311,10 @@ extern enum attr_cpu ix86_schedule; | ||
76 | #endif | ||
77 | |||
78 | extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op); | ||
79 | -extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p); | ||
80 | +extern const char * ix86_output_indirect_jmp (rtx call_op); | ||
81 | extern const char * ix86_output_function_return (bool long_p); | ||
82 | +extern const char * ix86_output_indirect_function_return (rtx ret_op); | ||
83 | +extern void ix86_split_simple_return_pop_internal (rtx); | ||
84 | extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load, | ||
85 | enum machine_mode mode); | ||
86 | |||
87 | diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c | ||
88 | index 66502ee..21c3c18 100644 | ||
89 | --- a/gcc/config/i386/i386.c | ||
90 | +++ b/gcc/config/i386/i386.c | ||
91 | @@ -11080,6 +11080,12 @@ static int indirect_thunks_used; | ||
92 | by call and return thunks functions with the BND prefix. */ | ||
93 | static int indirect_thunks_bnd_used; | ||
94 | |||
95 | +/* True if return thunk function via CX is needed. */ | ||
96 | +static bool indirect_return_via_cx; | ||
97 | +/* True if return thunk function via CX with the BND prefix is | ||
98 | + needed. */ | ||
99 | +static bool indirect_return_via_cx_bnd; | ||
100 | + | ||
101 | #ifndef INDIRECT_LABEL | ||
102 | # define INDIRECT_LABEL "LIND" | ||
103 | #endif | ||
104 | @@ -11090,12 +11096,13 @@ static void | ||
105 | indirect_thunk_name (char name[32], unsigned int regno, | ||
106 | bool need_bnd_p, bool ret_p) | ||
107 | { | ||
108 | - if (regno != INVALID_REGNUM && ret_p) | ||
109 | + if (regno != INVALID_REGNUM && regno != CX_REG && ret_p) | ||
110 | gcc_unreachable (); | ||
111 | |||
112 | if (USE_HIDDEN_LINKONCE) | ||
113 | { | ||
114 | const char *bnd = need_bnd_p ? "_bnd" : ""; | ||
115 | + const char *ret = ret_p ? "return" : "indirect"; | ||
116 | if (regno != INVALID_REGNUM) | ||
117 | { | ||
118 | const char *reg_prefix; | ||
119 | @@ -11103,14 +11110,11 @@ indirect_thunk_name (char name[32], unsigned int regno, | ||
120 | reg_prefix = TARGET_64BIT ? "r" : "e"; | ||
121 | else | ||
122 | reg_prefix = ""; | ||
123 | - sprintf (name, "__x86_indirect_thunk%s_%s%s", | ||
124 | - bnd, reg_prefix, reg_names[regno]); | ||
125 | + sprintf (name, "__x86_%s_thunk%s_%s%s", | ||
126 | + ret, bnd, reg_prefix, reg_names[regno]); | ||
127 | } | ||
128 | else | ||
129 | - { | ||
130 | - const char *ret = ret_p ? "return" : "indirect"; | ||
131 | - sprintf (name, "__x86_%s_thunk%s", ret, bnd); | ||
132 | - } | ||
133 | + sprintf (name, "__x86_%s_thunk%s", ret, bnd); | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | @@ -11274,9 +11278,23 @@ output_indirect_thunk_function (bool need_bnd_p, unsigned int regno) | ||
138 | ASM_OUTPUT_LABEL (asm_out_file, name); | ||
139 | } | ||
140 | |||
141 | + /* Create alias for __x86_return_thunk/__x86_return_thunk_bnd or | ||
142 | + __x86_return_thunk_ecx/__x86_return_thunk_ecx_bnd. */ | ||
143 | + bool need_alias; | ||
144 | if (regno == INVALID_REGNUM) | ||
145 | + need_alias = true; | ||
146 | + else if (regno == CX_REG) | ||
147 | + { | ||
148 | + if (need_bnd_p) | ||
149 | + need_alias = indirect_return_via_cx_bnd; | ||
150 | + else | ||
151 | + need_alias = indirect_return_via_cx; | ||
152 | + } | ||
153 | + else | ||
154 | + need_alias = false; | ||
155 | + | ||
156 | + if (need_alias) | ||
157 | { | ||
158 | - /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */ | ||
159 | char alias[32]; | ||
160 | |||
161 | indirect_thunk_name (alias, regno, need_bnd_p, true); | ||
162 | @@ -28019,18 +28037,17 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm, | ||
163 | else | ||
164 | ix86_output_indirect_branch_via_push (call_op, xasm, sibcall_p); | ||
165 | } | ||
166 | -/* Output indirect jump. CALL_OP is the jump target. Jump is a | ||
167 | - function return if RET_P is true. */ | ||
168 | + | ||
169 | +/* Output indirect jump. CALL_OP is the jump target. */ | ||
170 | |||
171 | const char * | ||
172 | -ix86_output_indirect_jmp (rtx call_op, bool ret_p) | ||
173 | +ix86_output_indirect_jmp (rtx call_op) | ||
174 | { | ||
175 | if (cfun->machine->indirect_branch_type != indirect_branch_keep) | ||
176 | { | ||
177 | - /* We can't have red-zone if this isn't a function return since | ||
178 | - "call" in the indirect thunk pushes the return address onto | ||
179 | - stack, destroying red-zone. */ | ||
180 | - if (!ret_p && ix86_red_zone_size != 0) | ||
181 | + /* We can't have red-zone since "call" in the indirect thunk | ||
182 | + pushes the return address onto stack, destroying red-zone. */ | ||
183 | + if (ix86_red_zone_size != 0) | ||
184 | gcc_unreachable (); | ||
185 | |||
186 | ix86_output_indirect_branch (call_op, "%0", true); | ||
187 | @@ -28081,6 +28098,86 @@ ix86_output_function_return (bool long_p) | ||
188 | return "rep%; ret"; | ||
189 | } | ||
190 | |||
191 | +/* Output indirect function return. RET_OP is the function return | ||
192 | + target. */ | ||
193 | + | ||
194 | +const char * | ||
195 | +ix86_output_indirect_function_return (rtx ret_op) | ||
196 | +{ | ||
197 | + if (cfun->machine->function_return_type != indirect_branch_keep) | ||
198 | + { | ||
199 | + char thunk_name[32]; | ||
200 | + bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn); | ||
201 | + unsigned int regno = REGNO (ret_op); | ||
202 | + gcc_assert (regno == CX_REG); | ||
203 | + | ||
204 | + if (cfun->machine->function_return_type | ||
205 | + != indirect_branch_thunk_inline) | ||
206 | + { | ||
207 | + bool need_thunk = (cfun->machine->function_return_type | ||
208 | + == indirect_branch_thunk); | ||
209 | + indirect_thunk_name (thunk_name, regno, need_bnd_p, true); | ||
210 | + if (need_bnd_p) | ||
211 | + { | ||
212 | + if (need_thunk) | ||
213 | + { | ||
214 | + indirect_return_via_cx_bnd = true; | ||
215 | + indirect_thunks_bnd_used |= 1 << CX_REG; | ||
216 | + } | ||
217 | + fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name); | ||
218 | + } | ||
219 | + else | ||
220 | + { | ||
221 | + if (need_thunk) | ||
222 | + { | ||
223 | + indirect_return_via_cx = true; | ||
224 | + indirect_thunks_used |= 1 << CX_REG; | ||
225 | + } | ||
226 | + fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); | ||
227 | + } | ||
228 | + } | ||
229 | + else | ||
230 | + output_indirect_thunk (need_bnd_p, regno); | ||
231 | + | ||
232 | + return ""; | ||
233 | + } | ||
234 | + else | ||
235 | + return "%!jmp\t%A0"; | ||
236 | +} | ||
237 | + | ||
238 | +/* Split simple return with popping POPC bytes from stack to indirect | ||
239 | + branch with stack adjustment . */ | ||
240 | + | ||
241 | +void | ||
242 | +ix86_split_simple_return_pop_internal (rtx popc) | ||
243 | +{ | ||
244 | + struct machine_function *m = cfun->machine; | ||
245 | + rtx ecx = gen_rtx_REG (SImode, CX_REG); | ||
246 | + rtx_insn *insn; | ||
247 | + | ||
248 | + /* There is no "pascal" calling convention in any 64bit ABI. */ | ||
249 | + gcc_assert (!TARGET_64BIT); | ||
250 | + | ||
251 | + insn = emit_insn (gen_pop (ecx)); | ||
252 | + m->fs.cfa_offset -= UNITS_PER_WORD; | ||
253 | + m->fs.sp_offset -= UNITS_PER_WORD; | ||
254 | + | ||
255 | + rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD); | ||
256 | + x = gen_rtx_SET (stack_pointer_rtx, x); | ||
257 | + add_reg_note (insn, REG_CFA_ADJUST_CFA, x); | ||
258 | + add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx)); | ||
259 | + RTX_FRAME_RELATED_P (insn) = 1; | ||
260 | + | ||
261 | + x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc); | ||
262 | + x = gen_rtx_SET (stack_pointer_rtx, x); | ||
263 | + insn = emit_insn (x); | ||
264 | + add_reg_note (insn, REG_CFA_ADJUST_CFA, x); | ||
265 | + RTX_FRAME_RELATED_P (insn) = 1; | ||
266 | + | ||
267 | + /* Now return address is in ECX. */ | ||
268 | + emit_jump_insn (gen_simple_return_indirect_internal (ecx)); | ||
269 | +} | ||
270 | + | ||
271 | /* Output the assembly for a call instruction. */ | ||
272 | |||
273 | const char * | ||
274 | diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md | ||
275 | index 05a88ff..857466a 100644 | ||
276 | --- a/gcc/config/i386/i386.md | ||
277 | +++ b/gcc/config/i386/i386.md | ||
278 | @@ -11813,7 +11813,7 @@ | ||
279 | (define_insn "*indirect_jump" | ||
280 | [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))] | ||
281 | "" | ||
282 | - "* return ix86_output_indirect_jmp (operands[0], false);" | ||
283 | + "* return ix86_output_indirect_jmp (operands[0]);" | ||
284 | [(set (attr "type") | ||
285 | (if_then_else (match_test "(cfun->machine->indirect_branch_type | ||
286 | != indirect_branch_keep)") | ||
287 | @@ -11868,7 +11868,7 @@ | ||
288 | [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw")) | ||
289 | (use (label_ref (match_operand 1)))] | ||
290 | "" | ||
291 | - "* return ix86_output_indirect_jmp (operands[0], false);" | ||
292 | + "* return ix86_output_indirect_jmp (operands[0]);" | ||
293 | [(set (attr "type") | ||
294 | (if_then_else (match_test "(cfun->machine->indirect_branch_type | ||
295 | != indirect_branch_keep)") | ||
296 | @@ -12520,11 +12520,14 @@ | ||
297 | (set_attr "prefix_rep" "1") | ||
298 | (set_attr "modrm" "0")]) | ||
299 | |||
300 | -(define_insn "simple_return_pop_internal" | ||
301 | +(define_insn_and_split "simple_return_pop_internal" | ||
302 | [(simple_return) | ||
303 | (use (match_operand:SI 0 "const_int_operand"))] | ||
304 | "reload_completed" | ||
305 | "%!ret\t%0" | ||
306 | + "&& cfun->machine->function_return_type != indirect_branch_keep" | ||
307 | + [(const_int 0)] | ||
308 | + "ix86_split_simple_return_pop_internal (operands[0]); DONE;" | ||
309 | [(set_attr "length" "3") | ||
310 | (set_attr "atom_unit" "jeu") | ||
311 | (set_attr "length_immediate" "2") | ||
312 | @@ -12535,7 +12538,7 @@ | ||
313 | [(simple_return) | ||
314 | (use (match_operand:SI 0 "register_operand" "r"))] | ||
315 | "reload_completed" | ||
316 | - "* return ix86_output_indirect_jmp (operands[0], true);" | ||
317 | + "* return ix86_output_indirect_function_return (operands[0]);" | ||
318 | [(set (attr "type") | ||
319 | (if_then_else (match_test "(cfun->machine->indirect_branch_type | ||
320 | != indirect_branch_keep)") | ||
321 | diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c | ||
322 | new file mode 100644 | ||
323 | index 0000000..89e086d | ||
324 | --- /dev/null | ||
325 | +++ b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c | ||
326 | @@ -0,0 +1,15 @@ | ||
327 | +/* PR target/r84530 */ | ||
328 | +/* { dg-do compile { target ia32 } } */ | ||
329 | +/* { dg-options "-O2 -mfunction-return=thunk" } */ | ||
330 | + | ||
331 | +struct s { _Complex unsigned short x; }; | ||
332 | +struct s gs = { 100 + 200i }; | ||
333 | +struct s __attribute__((noinline)) foo (void) { return gs; } | ||
334 | + | ||
335 | +/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */ | ||
336 | +/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */ | ||
337 | +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */ | ||
338 | +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ | ||
339 | +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ | ||
340 | +/* { dg-final { scan-assembler {\tpause} } } */ | ||
341 | +/* { dg-final { scan-assembler {\tlfence} } } */ | ||
342 | diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c | ||
343 | new file mode 100644 | ||
344 | index 0000000..43f0cca | ||
345 | --- /dev/null | ||
346 | +++ b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c | ||
347 | @@ -0,0 +1,15 @@ | ||
348 | +/* PR target/r84530 */ | ||
349 | +/* { dg-do compile { target ia32 } } */ | ||
350 | +/* { dg-options "-O2 -mfunction-return=thunk-extern" } */ | ||
351 | + | ||
352 | +struct s { _Complex unsigned short x; }; | ||
353 | +struct s gs = { 100 + 200i }; | ||
354 | +struct s __attribute__((noinline)) foo (void) { return gs; } | ||
355 | + | ||
356 | +/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */ | ||
357 | +/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */ | ||
358 | +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */ | ||
359 | +/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ | ||
360 | +/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ | ||
361 | +/* { dg-final { scan-assembler-not {\tpause} } } */ | ||
362 | +/* { dg-final { scan-assembler-not {\tlfence} } } */ | ||
363 | diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c | ||
364 | new file mode 100644 | ||
365 | index 0000000..8729e35 | ||
366 | --- /dev/null | ||
367 | +++ b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c | ||
368 | @@ -0,0 +1,15 @@ | ||
369 | +/* PR target/r84530 */ | ||
370 | +/* { dg-do compile { target ia32 } } */ | ||
371 | +/* { dg-options "-O2 -mfunction-return=thunk-inline" } */ | ||
372 | + | ||
373 | +struct s { _Complex unsigned short x; }; | ||
374 | +struct s gs = { 100 + 200i }; | ||
375 | +struct s __attribute__((noinline)) foo (void) { return gs; } | ||
376 | + | ||
377 | +/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */ | ||
378 | +/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */ | ||
379 | +/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk_ecx" } } */ | ||
380 | +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ | ||
381 | +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ | ||
382 | +/* { dg-final { scan-assembler {\tpause} } } */ | ||
383 | +/* { dg-final { scan-assembler {\tlfence} } } */ | ||
384 | diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-25.c b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c | ||
385 | new file mode 100644 | ||
386 | index 0000000..f73553c | ||
387 | --- /dev/null | ||
388 | +++ b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c | ||
389 | @@ -0,0 +1,15 @@ | ||
390 | +/* PR target/r84530 */ | ||
391 | +/* { dg-do compile { target ia32 } } */ | ||
392 | +/* { dg-options "-O2 -mfunction-return=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */ | ||
393 | + | ||
394 | +struct s { _Complex unsigned short x; }; | ||
395 | +struct s gs = { 100 + 200i }; | ||
396 | +struct s __attribute__((noinline)) foo (void) { return gs; } | ||
397 | + | ||
398 | +/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */ | ||
399 | +/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */ | ||
400 | +/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_bnd_ecx" } } */ | ||
401 | +/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ | ||
402 | +/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ | ||
403 | +/* { dg-final { scan-assembler {\tpause} } } */ | ||
404 | +/* { dg-final { scan-assembler {\tlfence} } } */ | ||
405 | diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c | ||
406 | new file mode 100644 | ||
407 | index 0000000..9144e98 | ||
408 | --- /dev/null | ||
409 | +++ b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c | ||
410 | @@ -0,0 +1,40 @@ | ||
411 | +/* PR target/r84530 */ | ||
412 | +/* { dg-do run } */ | ||
413 | +/* { dg-options "-Os -mfunction-return=thunk" } */ | ||
414 | + | ||
415 | +struct S { int i; }; | ||
416 | +__attribute__((const, noinline, noclone)) | ||
417 | +struct S foo (int x) | ||
418 | +{ | ||
419 | + struct S s; | ||
420 | + s.i = x; | ||
421 | + return s; | ||
422 | +} | ||
423 | + | ||
424 | +int a[2048], b[2048], c[2048], d[2048]; | ||
425 | +struct S e[2048]; | ||
426 | + | ||
427 | +__attribute__((noinline, noclone)) void | ||
428 | +bar (void) | ||
429 | +{ | ||
430 | + int i; | ||
431 | + for (i = 0; i < 1024; i++) | ||
432 | + { | ||
433 | + e[i] = foo (i); | ||
434 | + a[i+2] = a[i] + a[i+1]; | ||
435 | + b[10] = b[10] + i; | ||
436 | + c[i] = c[2047 - i]; | ||
437 | + d[i] = d[i + 1]; | ||
438 | + } | ||
439 | +} | ||
440 | + | ||
441 | +int | ||
442 | +main () | ||
443 | +{ | ||
444 | + int i; | ||
445 | + bar (); | ||
446 | + for (i = 0; i < 1024; i++) | ||
447 | + if (e[i].i != i) | ||
448 | + __builtin_abort (); | ||
449 | + return 0; | ||
450 | +} | ||
451 | -- | ||
452 | 2.7.4 | ||
453 | |||