[OpenACC] Enable 'attach' clause for combined constructs
[llvm-project.git] / llvm / test / CodeGen / X86 / x86-32-intrcc.ll
bloba0f937e2c323b6d03299d71ba42e1b28dc9916d0
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp --version 2
2 ; RUN: llc -mtriple=i686-unknown-unknown < %s | FileCheck %s
3 ; RUN: llc -mtriple=i686-unknown-unknown -O0 < %s | FileCheck %s -check-prefix=CHECK0
5 %struct.interrupt_frame = type { i32, i32, i32, i32, i32 }
7 @sink_address = global ptr null
8 @sink_i32 = global i32 0
11 ; Spills eax, putting original esp at +4.
12 ; Stack is dyamically realigned to 16 bytes, and then reloaded to ebp - 4
13 ; With no error code, the stack is not incremented by 4 bytes before returning
14 define x86_intrcc void @test_isr_no_ecode(ptr byval(%struct.interrupt_frame) %frame) nounwind {
15 ; CHECK-LABEL: test_isr_no_ecode:
16 ; CHECK:       # %bb.0:
17 ; CHECK-NEXT:    pushl %ebp
18 ; CHECK-NEXT:    movl %esp, %ebp
19 ; CHECK-NEXT:    pushl %eax
20 ; CHECK-NEXT:    andl $-16, %esp
21 ; CHECK-NEXT:    cld
22 ; CHECK-NEXT:    movl 12(%ebp), %eax
23 ; CHECK-NEXT:    #APP
24 ; CHECK-NEXT:    #NO_APP
25 ; CHECK-NEXT:    leal -4(%ebp), %esp
26 ; CHECK-NEXT:    popl %eax
27 ; CHECK-NEXT:    popl %ebp
28 ; CHECK-NEXT:    iretl
30 ; CHECK0-LABEL: test_isr_no_ecode:
31 ; CHECK0:       # %bb.0:
32 ; CHECK0-NEXT:    pushl %ebp
33 ; CHECK0-NEXT:    movl %esp, %ebp
34 ; CHECK0-NEXT:    pushl %eax
35 ; CHECK0-NEXT:    andl $-16, %esp
36 ; CHECK0-NEXT:    cld
37 ; CHECK0-NEXT:    leal 4(%ebp), %eax
38 ; CHECK0-NEXT:    movl 8(%eax), %eax
39 ; CHECK0-NEXT:    #APP
40 ; CHECK0-NEXT:    #NO_APP
41 ; CHECK0-NEXT:    leal -4(%ebp), %esp
42 ; CHECK0-NEXT:    popl %eax
43 ; CHECK0-NEXT:    popl %ebp
44 ; CHECK0-NEXT:    iretl
45 ; CHECK-NEXT;    movl %esp, %ebp
46   %pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
47   %flags = load i32, ptr %pflags, align 4
48   call void asm sideeffect "", "r"(i32 %flags)
49   ret void
52 ; Spills eax and ecx, putting original esp at +8.
53 ; Stack is dynamically realigned to 16 bytes, and then reloaded to ebp - 8
54 ; Error code is popped from the stack with an increment of 4 before returning
55 define x86_intrcc void @test_isr_ecode(ptr byval(%struct.interrupt_frame) %frame, i32 %ecode) nounwind {
56 ; CHECK-LABEL: test_isr_ecode:
57 ; CHECK:       # %bb.0:
58 ; CHECK-NEXT:    pushl %ebp
59 ; CHECK-NEXT:    movl %esp, %ebp
60 ; CHECK-NEXT:    pushl %ecx
61 ; CHECK-NEXT:    pushl %eax
62 ; CHECK-NEXT:    andl $-16, %esp
63 ; CHECK-NEXT:    cld
64 ; CHECK-NEXT:    movl 4(%ebp), %eax
65 ; CHECK-NEXT:    movl 16(%ebp), %ecx
66 ; CHECK-NEXT:    #APP
67 ; CHECK-NEXT:    #NO_APP
68 ; CHECK-NEXT:    leal -8(%ebp), %esp
69 ; CHECK-NEXT:    popl %eax
70 ; CHECK-NEXT:    popl %ecx
71 ; CHECK-NEXT:    popl %ebp
72 ; CHECK-NEXT:    addl $4, %esp
73 ; CHECK-NEXT:    iretl
75 ; CHECK0-LABEL: test_isr_ecode:
76 ; CHECK0:       # %bb.0:
77 ; CHECK0-NEXT:    pushl %ebp
78 ; CHECK0-NEXT:    movl %esp, %ebp
79 ; CHECK0-NEXT:    pushl %ecx
80 ; CHECK0-NEXT:    pushl %eax
81 ; CHECK0-NEXT:    andl $-16, %esp
82 ; CHECK0-NEXT:    cld
83 ; CHECK0-NEXT:    movl 4(%ebp), %ecx
84 ; CHECK0-NEXT:    leal 8(%ebp), %eax
85 ; CHECK0-NEXT:    movl 8(%eax), %eax
86 ; CHECK0-NEXT:    #APP
87 ; CHECK0-NEXT:    #NO_APP
88 ; CHECK0-NEXT:    leal -8(%ebp), %esp
89 ; CHECK0-NEXT:    popl %eax
90 ; CHECK0-NEXT:    popl %ecx
91 ; CHECK0-NEXT:    popl %ebp
92 ; CHECK0-NEXT:    addl $4, %esp
93 ; CHECK0-NEXT:    iretl
94   %pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
95   %flags = load i32, ptr %pflags, align 4
96   call x86_fastcallcc void asm sideeffect "", "r,r"(i32 %flags, i32 %ecode)
97   ret void
100 ; All clobbered registers must be saved
101 define x86_intrcc void @test_isr_clobbers(ptr byval(%struct.interrupt_frame) %frame, i32 %ecode) nounwind {
102 ; CHECK-LABEL: test_isr_clobbers:
103 ; CHECK:       # %bb.0:
104 ; CHECK-NEXT:    pushl %ebp
105 ; CHECK-NEXT:    movl %esp, %ebp
106 ; CHECK-NEXT:    pushl %ecx
107 ; CHECK-NEXT:    pushl %ebx
108 ; CHECK-NEXT:    pushl %eax
109 ; CHECK-NEXT:    andl $-16, %esp
110 ; CHECK-NEXT:    cld
111 ; CHECK-NEXT:    pushl %ebp
112 ; CHECK-NEXT:    #APP
113 ; CHECK-NEXT:    #NO_APP
114 ; CHECK-NEXT:    popl %ebp
115 ; CHECK-NEXT:    leal -12(%ebp), %esp
116 ; CHECK-NEXT:    popl %eax
117 ; CHECK-NEXT:    popl %ebx
118 ; CHECK-NEXT:    popl %ecx
119 ; CHECK-NEXT:    popl %ebp
120 ; CHECK-NEXT:    addl $4, %esp
121 ; CHECK-NEXT:    iretl
123 ; CHECK0-LABEL: test_isr_clobbers:
124 ; CHECK0:       # %bb.0:
125 ; CHECK0-NEXT:    pushl %ebp
126 ; CHECK0-NEXT:    movl %esp, %ebp
127 ; CHECK0-NEXT:    pushl %ecx
128 ; CHECK0-NEXT:    pushl %ebx
129 ; CHECK0-NEXT:    pushl %eax
130 ; CHECK0-NEXT:    andl $-16, %esp
131 ; CHECK0-NEXT:    cld
132 ; CHECK0-NEXT:    pushl %ebp
133 ; CHECK0-NEXT:    #APP
134 ; CHECK0-NEXT:    #NO_APP
135 ; CHECK0-NEXT:    popl %ebp
136 ; CHECK0-NEXT:    leal -12(%ebp), %esp
137 ; CHECK0-NEXT:    popl %eax
138 ; CHECK0-NEXT:    popl %ebx
139 ; CHECK0-NEXT:    popl %ecx
140 ; CHECK0-NEXT:    popl %ebp
141 ; CHECK0-NEXT:    addl $4, %esp
142 ; CHECK0-NEXT:    iretl
143   call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{ebp}"()
144   ret void
147 @f80 = common global x86_fp80 0xK00000000000000000000, align 4
149 ; Test that the presence of x87 does not crash the FP stackifier
150 define x86_intrcc void @test_isr_x87(ptr byval(%struct.interrupt_frame) %frame) nounwind {
151 ; CHECK-LABEL: test_isr_x87:
152 ; CHECK:       # %bb.0: # %entry
153 ; CHECK-NEXT:    pushl %ebp
154 ; CHECK-NEXT:    movl %esp, %ebp
155 ; CHECK-NEXT:    andl $-16, %esp
156 ; CHECK-NEXT:    fldt f80
157 ; CHECK-NEXT:    fld1
158 ; CHECK-NEXT:    faddp %st, %st(1)
159 ; CHECK-NEXT:    fstpt f80
160 ; CHECK-NEXT:    movl %ebp, %esp
161 ; CHECK-NEXT:    popl %ebp
162 ; CHECK-NEXT:    iretl
164 ; CHECK0-LABEL: test_isr_x87:
165 ; CHECK0:       # %bb.0: # %entry
166 ; CHECK0-NEXT:    pushl %ebp
167 ; CHECK0-NEXT:    movl %esp, %ebp
168 ; CHECK0-NEXT:    andl $-16, %esp
169 ; CHECK0-NEXT:    fldt f80
170 ; CHECK0-NEXT:    fld1
171 ; CHECK0-NEXT:    faddp %st, %st(1)
172 ; CHECK0-NEXT:    fstpt f80
173 ; CHECK0-NEXT:    movl %ebp, %esp
174 ; CHECK0-NEXT:    popl %ebp
175 ; CHECK0-NEXT:    iretl
176 entry:
177   %ld = load x86_fp80, ptr @f80, align 4
178   %add = fadd x86_fp80 %ld, 0xK3FFF8000000000000000
179   store x86_fp80 %add, ptr @f80, align 4
180   ret void
183 ; Use the interrupt_frame pointer to check the offsets.
184 ; No return address, arguments start at EBP+4.
185 define dso_local x86_intrcc void @test_fp_1(ptr byval(%struct.interrupt_frame) %p) #0 {
186 ; CHECK-LABEL: test_fp_1:
187 ; CHECK:       # %bb.0: # %entry
188 ; CHECK-NEXT:    pushl %ebp
189 ; CHECK-NEXT:    movl %esp, %ebp
190 ; CHECK-NEXT:    pushl %ecx
191 ; CHECK-NEXT:    pushl %eax
192 ; CHECK-NEXT:    andl $-16, %esp
193 ; CHECK-NEXT:    leal 20(%ebp), %eax
194 ; CHECK-NEXT:    leal 4(%ebp), %ecx
195 ; CHECK-NEXT:    movl %ecx, sink_address
196 ; CHECK-NEXT:    movl %eax, sink_address
197 ; CHECK-NEXT:    leal -8(%ebp), %esp
198 ; CHECK-NEXT:    popl %eax
199 ; CHECK-NEXT:    popl %ecx
200 ; CHECK-NEXT:    popl %ebp
201 ; CHECK-NEXT:    iretl
203 ; CHECK0-LABEL: test_fp_1:
204 ; CHECK0:       # %bb.0: # %entry
205 ; CHECK0-NEXT:    pushl %ebp
206 ; CHECK0-NEXT:    movl %esp, %ebp
207 ; CHECK0-NEXT:    pushl %ecx
208 ; CHECK0-NEXT:    pushl %eax
209 ; CHECK0-NEXT:    andl $-16, %esp
210 ; CHECK0-NEXT:    leal 4(%ebp), %ecx
211 ; CHECK0-NEXT:    movl %ecx, %eax
212 ; CHECK0-NEXT:    addl $16, %eax
213 ; CHECK0-NEXT:    movl %ecx, sink_address
214 ; CHECK0-NEXT:    movl %eax, sink_address
215 ; CHECK0-NEXT:    leal -8(%ebp), %esp
216 ; CHECK0-NEXT:    popl %eax
217 ; CHECK0-NEXT:    popl %ecx
218 ; CHECK0-NEXT:    popl %ebp
219 ; CHECK0-NEXT:    iretl
220 entry:
221   %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i32 0, i32 4
222   store volatile ptr %p, ptr @sink_address
223   store volatile ptr %arrayidx2, ptr @sink_address
224   ret void
227 ; The error code is between EBP and the interrupt_frame.
228 define dso_local x86_intrcc void @test_fp_2(ptr byval(%struct.interrupt_frame) %p, i32 %err) #0 {
229 ; CHECK-LABEL: test_fp_2:
230 ; CHECK:       # %bb.0: # %entry
231 ; CHECK-NEXT:    pushl %ebp
232 ; CHECK-NEXT:    movl %esp, %ebp
233 ; CHECK-NEXT:    pushl %edx
234 ; CHECK-NEXT:    pushl %ecx
235 ; CHECK-NEXT:    pushl %eax
236 ; CHECK-NEXT:    andl $-16, %esp
237 ; CHECK-NEXT:    movl 4(%ebp), %eax
238 ; CHECK-NEXT:    leal 24(%ebp), %ecx
239 ; CHECK-NEXT:    leal 8(%ebp), %edx
240 ; CHECK-NEXT:    movl %edx, sink_address
241 ; CHECK-NEXT:    movl %ecx, sink_address
242 ; CHECK-NEXT:    movl %eax, sink_i32
243 ; CHECK-NEXT:    leal -12(%ebp), %esp
244 ; CHECK-NEXT:    popl %eax
245 ; CHECK-NEXT:    popl %ecx
246 ; CHECK-NEXT:    popl %edx
247 ; CHECK-NEXT:    popl %ebp
248 ; CHECK-NEXT:    addl $4, %esp
249 ; CHECK-NEXT:    iretl
251 ; CHECK0-LABEL: test_fp_2:
252 ; CHECK0:       # %bb.0: # %entry
253 ; CHECK0-NEXT:    pushl %ebp
254 ; CHECK0-NEXT:    movl %esp, %ebp
255 ; CHECK0-NEXT:    pushl %edx
256 ; CHECK0-NEXT:    pushl %ecx
257 ; CHECK0-NEXT:    pushl %eax
258 ; CHECK0-NEXT:    andl $-16, %esp
259 ; CHECK0-NEXT:    movl 4(%ebp), %eax
260 ; CHECK0-NEXT:    leal 8(%ebp), %edx
261 ; CHECK0-NEXT:    movl %edx, %ecx
262 ; CHECK0-NEXT:    addl $16, %ecx
263 ; CHECK0-NEXT:    movl %edx, sink_address
264 ; CHECK0-NEXT:    movl %ecx, sink_address
265 ; CHECK0-NEXT:    movl %eax, sink_i32
266 ; CHECK0-NEXT:    leal -12(%ebp), %esp
267 ; CHECK0-NEXT:    popl %eax
268 ; CHECK0-NEXT:    popl %ecx
269 ; CHECK0-NEXT:    popl %edx
270 ; CHECK0-NEXT:    popl %ebp
271 ; CHECK0-NEXT:    addl $4, %esp
272 ; CHECK0-NEXT:    iretl
273 entry:
274   %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i32 0, i32 4
275   store volatile ptr %p, ptr @sink_address
276   store volatile ptr %arrayidx2, ptr @sink_address
277   store volatile i32 %err, ptr @sink_i32
278   ret void
281 ; Test argument copy elision when copied to a local alloca.
282 define x86_intrcc void @test_copy_elide(ptr byval(%struct.interrupt_frame) %frame, i32 %err) #0 {
283 ; CHECK-LABEL: test_copy_elide:
284 ; CHECK:       # %bb.0: # %entry
285 ; CHECK-NEXT:    pushl %ebp
286 ; CHECK-NEXT:    movl %esp, %ebp
287 ; CHECK-NEXT:    pushl %eax
288 ; CHECK-NEXT:    andl $-16, %esp
289 ; CHECK-NEXT:    leal 4(%ebp), %eax
290 ; CHECK-NEXT:    movl %eax, sink_address
291 ; CHECK-NEXT:    leal -4(%ebp), %esp
292 ; CHECK-NEXT:    popl %eax
293 ; CHECK-NEXT:    popl %ebp
294 ; CHECK-NEXT:    addl $4, %esp
295 ; CHECK-NEXT:    iretl
297 ; CHECK0-LABEL: test_copy_elide:
298 ; CHECK0:       # %bb.0: # %entry
299 ; CHECK0-NEXT:    pushl %ebp
300 ; CHECK0-NEXT:    movl %esp, %ebp
301 ; CHECK0-NEXT:    pushl %eax
302 ; CHECK0-NEXT:    andl $-16, %esp
303 ; CHECK0-NEXT:    movl 4(%ebp), %eax
304 ; CHECK0-NEXT:    leal 4(%ebp), %eax
305 ; CHECK0-NEXT:    movl %eax, sink_address
306 ; CHECK0-NEXT:    leal -4(%ebp), %esp
307 ; CHECK0-NEXT:    popl %eax
308 ; CHECK0-NEXT:    popl %ebp
309 ; CHECK0-NEXT:    addl $4, %esp
310 ; CHECK0-NEXT:    iretl
311 entry:
312   %err.addr = alloca i32, align 4
313   store i32 %err, ptr %err.addr, align 4
314   store volatile ptr %err.addr, ptr @sink_address
315   ret void
318 ; Disabling dynamic realignment with attributes should work
319 define x86_intrcc void @test_isr_no_realign(ptr byval(%struct.interrupt_frame) %frame) #1 {
320 ; CHECK-LABEL: test_isr_no_realign:
321 ; CHECK:       # %bb.0:
322 ; CHECK-NEXT:    pushl %eax
323 ; CHECK-NEXT:    cld
324 ; CHECK-NEXT:    movl 12(%esp), %eax
325 ; CHECK-NEXT:    #APP
326 ; CHECK-NEXT:    #NO_APP
327 ; CHECK-NEXT:    popl %eax
328 ; CHECK-NEXT:    iretl
330 ; CHECK0-LABEL: test_isr_no_realign:
331 ; CHECK0:       # %bb.0:
332 ; CHECK0-NEXT:    pushl %eax
333 ; CHECK0-NEXT:    cld
334 ; CHECK0-NEXT:    leal 4(%esp), %eax
335 ; CHECK0-NEXT:    movl 8(%eax), %eax
336 ; CHECK0-NEXT:    #APP
337 ; CHECK0-NEXT:    #NO_APP
338 ; CHECK0-NEXT:    popl %eax
339 ; CHECK0-NEXT:    iretl
340   %pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
341   %flags = load i32, ptr %pflags, align 4
342   call void asm sideeffect "", "r"(i32 %flags)
343   ret void
346 ; The stackrealign attribute should work, and the function's alignment
347 ; should be respected over the default 16-byte alignment required by the calling
348 ; convention.
349 define x86_intrcc void @test_isr_realign(ptr byval(%struct.interrupt_frame) %frame, i32 %ecode) #2 {
350 ; CHECK-LABEL: test_isr_realign:
351 ; CHECK:       # %bb.0:
352 ; CHECK-NEXT:    pushl %ebp
353 ; CHECK-NEXT:    movl %esp, %ebp
354 ; CHECK-NEXT:    pushl %eax
355 ; CHECK-NEXT:    andl $-32, %esp
356 ; CHECK-NEXT:    subl $32, %esp
357 ; CHECK-NEXT:    movl 4(%ebp), %eax
358 ; CHECK-NEXT:    movl %eax, (%esp)
359 ; CHECK-NEXT:    leal -4(%ebp), %esp
360 ; CHECK-NEXT:    popl %eax
361 ; CHECK-NEXT:    popl %ebp
362 ; CHECK-NEXT:    addl $4, %esp
363 ; CHECK-NEXT:    iretl
365 ; CHECK0-LABEL: test_isr_realign:
366 ; CHECK0:       # %bb.0:
367 ; CHECK0-NEXT:    pushl %ebp
368 ; CHECK0-NEXT:    movl %esp, %ebp
369 ; CHECK0-NEXT:    pushl %eax
370 ; CHECK0-NEXT:    andl $-32, %esp
371 ; CHECK0-NEXT:    subl $32, %esp
372 ; CHECK0-NEXT:    movl 4(%ebp), %eax
373 ; CHECK0-NEXT:    movl %eax, (%esp)
374 ; CHECK0-NEXT:    leal -4(%ebp), %esp
375 ; CHECK0-NEXT:    popl %eax
376 ; CHECK0-NEXT:    popl %ebp
377 ; CHECK0-NEXT:    addl $4, %esp
378 ; CHECK0-NEXT:    iretl
379   %ecode.stack = alloca i32, align 32
380   store i32 %ecode, ptr %ecode.stack
381   ret void
385 attributes #0 = { nounwind "frame-pointer"="all" }
386 attributes #1 = { nounwind "no-realign-stack" }
387 attributes #2 = { nounwind "stackrealign" }