Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / X86 / x86-32-intrcc.ll
blob3c3944c2082bd588303dfd37b1feedb8597935db
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:    #APP
112 ; CHECK-NEXT:    #NO_APP
113 ; CHECK-NEXT:    leal -12(%ebp), %esp
114 ; CHECK-NEXT:    popl %eax
115 ; CHECK-NEXT:    popl %ebx
116 ; CHECK-NEXT:    popl %ecx
117 ; CHECK-NEXT:    popl %ebp
118 ; CHECK-NEXT:    addl $4, %esp
119 ; CHECK-NEXT:    iretl
121 ; CHECK0-LABEL: test_isr_clobbers:
122 ; CHECK0:       # %bb.0:
123 ; CHECK0-NEXT:    pushl %ebp
124 ; CHECK0-NEXT:    movl %esp, %ebp
125 ; CHECK0-NEXT:    pushl %ecx
126 ; CHECK0-NEXT:    pushl %ebx
127 ; CHECK0-NEXT:    pushl %eax
128 ; CHECK0-NEXT:    andl $-16, %esp
129 ; CHECK0-NEXT:    cld
130 ; CHECK0-NEXT:    #APP
131 ; CHECK0-NEXT:    #NO_APP
132 ; CHECK0-NEXT:    leal -12(%ebp), %esp
133 ; CHECK0-NEXT:    popl %eax
134 ; CHECK0-NEXT:    popl %ebx
135 ; CHECK0-NEXT:    popl %ecx
136 ; CHECK0-NEXT:    popl %ebp
137 ; CHECK0-NEXT:    addl $4, %esp
138 ; CHECK0-NEXT:    iretl
139   call void asm sideeffect "", "~{eax},~{ebx},~{ecx},~{ebp}"()
140   ret void
143 @f80 = common global x86_fp80 0xK00000000000000000000, align 4
145 ; Test that the presence of x87 does not crash the FP stackifier
146 define x86_intrcc void @test_isr_x87(ptr byval(%struct.interrupt_frame) %frame) nounwind {
147 ; CHECK-LABEL: test_isr_x87:
148 ; CHECK:       # %bb.0: # %entry
149 ; CHECK-NEXT:    pushl %ebp
150 ; CHECK-NEXT:    movl %esp, %ebp
151 ; CHECK-NEXT:    andl $-16, %esp
152 ; CHECK-NEXT:    fldt f80
153 ; CHECK-NEXT:    fld1
154 ; CHECK-NEXT:    faddp %st, %st(1)
155 ; CHECK-NEXT:    fstpt f80
156 ; CHECK-NEXT:    movl %ebp, %esp
157 ; CHECK-NEXT:    popl %ebp
158 ; CHECK-NEXT:    iretl
160 ; CHECK0-LABEL: test_isr_x87:
161 ; CHECK0:       # %bb.0: # %entry
162 ; CHECK0-NEXT:    pushl %ebp
163 ; CHECK0-NEXT:    movl %esp, %ebp
164 ; CHECK0-NEXT:    andl $-16, %esp
165 ; CHECK0-NEXT:    fldt f80
166 ; CHECK0-NEXT:    fld1
167 ; CHECK0-NEXT:    faddp %st, %st(1)
168 ; CHECK0-NEXT:    fstpt f80
169 ; CHECK0-NEXT:    movl %ebp, %esp
170 ; CHECK0-NEXT:    popl %ebp
171 ; CHECK0-NEXT:    iretl
172 entry:
173   %ld = load x86_fp80, ptr @f80, align 4
174   %add = fadd x86_fp80 %ld, 0xK3FFF8000000000000000
175   store x86_fp80 %add, ptr @f80, align 4
176   ret void
179 ; Use the interrupt_frame pointer to check the offsets.
180 ; No return address, arguments start at EBP+4.
181 define dso_local x86_intrcc void @test_fp_1(ptr byval(%struct.interrupt_frame) %p) #0 {
182 ; CHECK-LABEL: test_fp_1:
183 ; CHECK:       # %bb.0: # %entry
184 ; CHECK-NEXT:    pushl %ebp
185 ; CHECK-NEXT:    movl %esp, %ebp
186 ; CHECK-NEXT:    pushl %ecx
187 ; CHECK-NEXT:    pushl %eax
188 ; CHECK-NEXT:    andl $-16, %esp
189 ; CHECK-NEXT:    leal 20(%ebp), %eax
190 ; CHECK-NEXT:    leal 4(%ebp), %ecx
191 ; CHECK-NEXT:    movl %ecx, sink_address
192 ; CHECK-NEXT:    movl %eax, sink_address
193 ; CHECK-NEXT:    leal -8(%ebp), %esp
194 ; CHECK-NEXT:    popl %eax
195 ; CHECK-NEXT:    popl %ecx
196 ; CHECK-NEXT:    popl %ebp
197 ; CHECK-NEXT:    iretl
199 ; CHECK0-LABEL: test_fp_1:
200 ; CHECK0:       # %bb.0: # %entry
201 ; CHECK0-NEXT:    pushl %ebp
202 ; CHECK0-NEXT:    movl %esp, %ebp
203 ; CHECK0-NEXT:    pushl %ecx
204 ; CHECK0-NEXT:    pushl %eax
205 ; CHECK0-NEXT:    andl $-16, %esp
206 ; CHECK0-NEXT:    leal 4(%ebp), %ecx
207 ; CHECK0-NEXT:    movl %ecx, %eax
208 ; CHECK0-NEXT:    addl $16, %eax
209 ; CHECK0-NEXT:    movl %ecx, sink_address
210 ; CHECK0-NEXT:    movl %eax, sink_address
211 ; CHECK0-NEXT:    leal -8(%ebp), %esp
212 ; CHECK0-NEXT:    popl %eax
213 ; CHECK0-NEXT:    popl %ecx
214 ; CHECK0-NEXT:    popl %ebp
215 ; CHECK0-NEXT:    iretl
216 entry:
217   %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i32 0, i32 4
218   store volatile ptr %p, ptr @sink_address
219   store volatile ptr %arrayidx2, ptr @sink_address
220   ret void
223 ; The error code is between EBP and the interrupt_frame.
224 define dso_local x86_intrcc void @test_fp_2(ptr byval(%struct.interrupt_frame) %p, i32 %err) #0 {
225 ; CHECK-LABEL: test_fp_2:
226 ; CHECK:       # %bb.0: # %entry
227 ; CHECK-NEXT:    pushl %ebp
228 ; CHECK-NEXT:    movl %esp, %ebp
229 ; CHECK-NEXT:    pushl %edx
230 ; CHECK-NEXT:    pushl %ecx
231 ; CHECK-NEXT:    pushl %eax
232 ; CHECK-NEXT:    andl $-16, %esp
233 ; CHECK-NEXT:    movl 4(%ebp), %eax
234 ; CHECK-NEXT:    leal 24(%ebp), %ecx
235 ; CHECK-NEXT:    leal 8(%ebp), %edx
236 ; CHECK-NEXT:    movl %edx, sink_address
237 ; CHECK-NEXT:    movl %ecx, sink_address
238 ; CHECK-NEXT:    movl %eax, sink_i32
239 ; CHECK-NEXT:    leal -12(%ebp), %esp
240 ; CHECK-NEXT:    popl %eax
241 ; CHECK-NEXT:    popl %ecx
242 ; CHECK-NEXT:    popl %edx
243 ; CHECK-NEXT:    popl %ebp
244 ; CHECK-NEXT:    addl $4, %esp
245 ; CHECK-NEXT:    iretl
247 ; CHECK0-LABEL: test_fp_2:
248 ; CHECK0:       # %bb.0: # %entry
249 ; CHECK0-NEXT:    pushl %ebp
250 ; CHECK0-NEXT:    movl %esp, %ebp
251 ; CHECK0-NEXT:    pushl %edx
252 ; CHECK0-NEXT:    pushl %ecx
253 ; CHECK0-NEXT:    pushl %eax
254 ; CHECK0-NEXT:    andl $-16, %esp
255 ; CHECK0-NEXT:    movl 4(%ebp), %eax
256 ; CHECK0-NEXT:    leal 8(%ebp), %edx
257 ; CHECK0-NEXT:    movl %edx, %ecx
258 ; CHECK0-NEXT:    addl $16, %ecx
259 ; CHECK0-NEXT:    movl %edx, sink_address
260 ; CHECK0-NEXT:    movl %ecx, sink_address
261 ; CHECK0-NEXT:    movl %eax, sink_i32
262 ; CHECK0-NEXT:    leal -12(%ebp), %esp
263 ; CHECK0-NEXT:    popl %eax
264 ; CHECK0-NEXT:    popl %ecx
265 ; CHECK0-NEXT:    popl %edx
266 ; CHECK0-NEXT:    popl %ebp
267 ; CHECK0-NEXT:    addl $4, %esp
268 ; CHECK0-NEXT:    iretl
269 entry:
270   %arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i32 0, i32 4
271   store volatile ptr %p, ptr @sink_address
272   store volatile ptr %arrayidx2, ptr @sink_address
273   store volatile i32 %err, ptr @sink_i32
274   ret void
277 ; Test argument copy elision when copied to a local alloca.
278 define x86_intrcc void @test_copy_elide(ptr byval(%struct.interrupt_frame) %frame, i32 %err) #0 {
279 ; CHECK-LABEL: test_copy_elide:
280 ; CHECK:       # %bb.0: # %entry
281 ; CHECK-NEXT:    pushl %ebp
282 ; CHECK-NEXT:    movl %esp, %ebp
283 ; CHECK-NEXT:    pushl %eax
284 ; CHECK-NEXT:    andl $-16, %esp
285 ; CHECK-NEXT:    leal 4(%ebp), %eax
286 ; CHECK-NEXT:    movl %eax, sink_address
287 ; CHECK-NEXT:    leal -4(%ebp), %esp
288 ; CHECK-NEXT:    popl %eax
289 ; CHECK-NEXT:    popl %ebp
290 ; CHECK-NEXT:    addl $4, %esp
291 ; CHECK-NEXT:    iretl
293 ; CHECK0-LABEL: test_copy_elide:
294 ; CHECK0:       # %bb.0: # %entry
295 ; CHECK0-NEXT:    pushl %ebp
296 ; CHECK0-NEXT:    movl %esp, %ebp
297 ; CHECK0-NEXT:    pushl %eax
298 ; CHECK0-NEXT:    andl $-16, %esp
299 ; CHECK0-NEXT:    movl 4(%ebp), %eax
300 ; CHECK0-NEXT:    leal 4(%ebp), %eax
301 ; CHECK0-NEXT:    movl %eax, sink_address
302 ; CHECK0-NEXT:    leal -4(%ebp), %esp
303 ; CHECK0-NEXT:    popl %eax
304 ; CHECK0-NEXT:    popl %ebp
305 ; CHECK0-NEXT:    addl $4, %esp
306 ; CHECK0-NEXT:    iretl
307 entry:
308   %err.addr = alloca i32, align 4
309   store i32 %err, ptr %err.addr, align 4
310   store volatile ptr %err.addr, ptr @sink_address
311   ret void
314 ; Disabling dynamic realignment with attributes should work
315 define x86_intrcc void @test_isr_no_realign(ptr byval(%struct.interrupt_frame) %frame) #1 {
316 ; CHECK-LABEL: test_isr_no_realign:
317 ; CHECK:       # %bb.0:
318 ; CHECK-NEXT:    pushl %eax
319 ; CHECK-NEXT:    cld
320 ; CHECK-NEXT:    movl 12(%esp), %eax
321 ; CHECK-NEXT:    #APP
322 ; CHECK-NEXT:    #NO_APP
323 ; CHECK-NEXT:    popl %eax
324 ; CHECK-NEXT:    iretl
326 ; CHECK0-LABEL: test_isr_no_realign:
327 ; CHECK0:       # %bb.0:
328 ; CHECK0-NEXT:    pushl %eax
329 ; CHECK0-NEXT:    cld
330 ; CHECK0-NEXT:    leal 4(%esp), %eax
331 ; CHECK0-NEXT:    movl 8(%eax), %eax
332 ; CHECK0-NEXT:    #APP
333 ; CHECK0-NEXT:    #NO_APP
334 ; CHECK0-NEXT:    popl %eax
335 ; CHECK0-NEXT:    iretl
336   %pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
337   %flags = load i32, ptr %pflags, align 4
338   call void asm sideeffect "", "r"(i32 %flags)
339   ret void
342 ; The stackrealign attribute should work, and the function's alignment
343 ; should be respected over the default 16-byte alignment required by the calling
344 ; convention.
345 define x86_intrcc void @test_isr_realign(ptr byval(%struct.interrupt_frame) %frame, i32 %ecode) #2 {
346 ; CHECK-LABEL: test_isr_realign:
347 ; CHECK:       # %bb.0:
348 ; CHECK-NEXT:    pushl %ebp
349 ; CHECK-NEXT:    movl %esp, %ebp
350 ; CHECK-NEXT:    pushl %eax
351 ; CHECK-NEXT:    andl $-32, %esp
352 ; CHECK-NEXT:    subl $32, %esp
353 ; CHECK-NEXT:    movl 4(%ebp), %eax
354 ; CHECK-NEXT:    movl %eax, (%esp)
355 ; CHECK-NEXT:    leal -4(%ebp), %esp
356 ; CHECK-NEXT:    popl %eax
357 ; CHECK-NEXT:    popl %ebp
358 ; CHECK-NEXT:    addl $4, %esp
359 ; CHECK-NEXT:    iretl
361 ; CHECK0-LABEL: test_isr_realign:
362 ; CHECK0:       # %bb.0:
363 ; CHECK0-NEXT:    pushl %ebp
364 ; CHECK0-NEXT:    movl %esp, %ebp
365 ; CHECK0-NEXT:    pushl %eax
366 ; CHECK0-NEXT:    andl $-32, %esp
367 ; CHECK0-NEXT:    subl $32, %esp
368 ; CHECK0-NEXT:    movl 4(%ebp), %eax
369 ; CHECK0-NEXT:    movl %eax, (%esp)
370 ; CHECK0-NEXT:    leal -4(%ebp), %esp
371 ; CHECK0-NEXT:    popl %eax
372 ; CHECK0-NEXT:    popl %ebp
373 ; CHECK0-NEXT:    addl $4, %esp
374 ; CHECK0-NEXT:    iretl
375   %ecode.stack = alloca i32, align 32
376   store i32 %ecode, ptr %ecode.stack
377   ret void
381 attributes #0 = { nounwind "frame-pointer"="all" }
382 attributes #1 = { nounwind "no-realign-stack" }
383 attributes #2 = { nounwind "stackrealign" }