[X86][AVX2] Enabled shuffle matching for the AVX2 zero extension (128bit -> 256bit...
[oota-llvm.git] / test / CodeGen / X86 / movtopush.ll
1 ; RUN: llc < %s -mtriple=i686-windows | FileCheck %s -check-prefix=NORMAL
2 ; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64
3 ; RUN: llc < %s -mtriple=i686-windows -force-align-stack -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED 
4
5 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)
6 declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)
7
8 ; Here, we should have a reserved frame, so we don't expect pushes
9 ; NORMAL-LABEL: test1:
10 ; NORMAL: subl    $16, %esp
11 ; NORMAL-NEXT: movl    $4, 12(%esp)
12 ; NORMAL-NEXT: movl    $3, 8(%esp)
13 ; NORMAL-NEXT: movl    $2, 4(%esp)
14 ; NORMAL-NEXT: movl    $1, (%esp)
15 ; NORMAL-NEXT: call
16 ; NORMAL-NEXT: addl $16, %esp
17 define void @test1() {
18 entry:
19   call void @good(i32 1, i32 2, i32 3, i32 4)
20   ret void
21 }
22
23 ; We're optimizing for code size, so we should get pushes for x86,
24 ; even though there is a reserved call frame.
25 ; Make sure we don't touch x86-64
26 ; NORMAL-LABEL: test1b:
27 ; NORMAL-NOT: subl {{.*}} %esp
28 ; NORMAL: pushl   $4
29 ; NORMAL-NEXT: pushl   $3
30 ; NORMAL-NEXT: pushl   $2
31 ; NORMAL-NEXT: pushl   $1
32 ; NORMAL-NEXT: call
33 ; NORMAL-NEXT: addl $16, %esp
34 ; X64-LABEL: test1b:
35 ; X64: movl    $1, %ecx
36 ; X64-NEXT: movl    $2, %edx
37 ; X64-NEXT: movl    $3, %r8d
38 ; X64-NEXT: movl    $4, %r9d
39 ; X64-NEXT: callq   good
40 define void @test1b() optsize {
41 entry:
42   call void @good(i32 1, i32 2, i32 3, i32 4)
43   ret void
44 }
45
46 ; Same as above, but for minsize
47 ; NORMAL-LABEL: test1c:
48 ; NORMAL-NOT: subl {{.*}} %esp
49 ; NORMAL: pushl   $4
50 ; NORMAL-NEXT: pushl   $3
51 ; NORMAL-NEXT: pushl   $2
52 ; NORMAL-NEXT: pushl   $1
53 ; NORMAL-NEXT: call
54 ; NORMAL-NEXT: addl $16, %esp
55 define void @test1c() minsize {
56 entry:
57   call void @good(i32 1, i32 2, i32 3, i32 4)
58   ret void
59 }
60
61 ; If we have a reserved frame, we should have pushes
62 ; NORMAL-LABEL: test2:
63 ; NORMAL-NOT: subl {{.*}} %esp
64 ; NORMAL: pushl   $4
65 ; NORMAL-NEXT: pushl   $3
66 ; NORMAL-NEXT: pushl   $2
67 ; NORMAL-NEXT: pushl   $1
68 ; NORMAL-NEXT: call
69 define void @test2(i32 %k) {
70 entry:
71   %a = alloca i32, i32 %k
72   call void @good(i32 1, i32 2, i32 3, i32 4)
73   ret void
74 }
75
76 ; Again, we expect a sequence of 4 immediate pushes
77 ; Checks that we generate the right pushes for >8bit immediates
78 ; NORMAL-LABEL: test2b:
79 ; NORMAL-NOT: subl {{.*}} %esp
80 ; NORMAL: pushl   $4096
81 ; NORMAL-NEXT: pushl   $3072
82 ; NORMAL-NEXT: pushl   $2048
83 ; NORMAL-NEXT: pushl   $1024
84 ; NORMAL-NEXT: call
85 ; NORMAL-NEXT: addl $16, %esp
86 define void @test2b() optsize {
87 entry:
88   call void @good(i32 1024, i32 2048, i32 3072, i32 4096)
89   ret void
90 }
91
92 ; The first push should push a register
93 ; NORMAL-LABEL: test3:
94 ; NORMAL-NOT: subl {{.*}} %esp
95 ; NORMAL: pushl   $4
96 ; NORMAL-NEXT: pushl   $3
97 ; NORMAL-NEXT: pushl   $2
98 ; NORMAL-NEXT: pushl   %e{{..}}
99 ; NORMAL-NEXT: call
100 ; NORMAL-NEXT: addl $16, %esp
101 define void @test3(i32 %k) optsize {
102 entry:
103   call void @good(i32 %k, i32 2, i32 3, i32 4)
104   ret void
105 }
106
107 ; We don't support weird calling conventions
108 ; NORMAL-LABEL: test4:
109 ; NORMAL: subl    $12, %esp
110 ; NORMAL-NEXT: movl    $4, 8(%esp)
111 ; NORMAL-NEXT: movl    $3, 4(%esp)
112 ; NORMAL-NEXT: movl    $1, (%esp)
113 ; NORMAL-NEXT: movl    $2, %eax
114 ; NORMAL-NEXT: call
115 ; NORMAL-NEXT: addl $12, %esp
116 define void @test4() optsize {
117 entry:
118   call void @inreg(i32 1, i32 2, i32 3, i32 4)
119   ret void
120 }
121
122 ; When there is no reserved call frame, check that additional alignment
123 ; is added when the pushes don't add up to the required alignment.
124 ; ALIGNED-LABEL: test5:
125 ; ALIGNED: subl    $16, %esp
126 ; ALIGNED-NEXT: pushl   $4
127 ; ALIGNED-NEXT: pushl   $3
128 ; ALIGNED-NEXT: pushl   $2
129 ; ALIGNED-NEXT: pushl   $1
130 ; ALIGNED-NEXT: call
131 define void @test5(i32 %k) {
132 entry:
133   %a = alloca i32, i32 %k
134   call void @good(i32 1, i32 2, i32 3, i32 4)
135   ret void
136 }
137
138 ; Check that pushing the addresses of globals (Or generally, things that 
139 ; aren't exactly immediates) isn't broken.
140 ; Fixes PR21878.
141 ; NORMAL-LABEL: test6:
142 ; NORMAL: pushl    $_ext
143 ; NORMAL-NEXT: call
144 declare void @f(i8*)
145 @ext = external constant i8
146
147 define void @test6() {
148   call void @f(i8* @ext)
149   br label %bb
150 bb:
151   alloca i32
152   ret void
153 }
154
155 ; Check that we fold simple cases into the push
156 ; NORMAL-LABEL: test7:
157 ; NORMAL-NOT: subl {{.*}} %esp
158 ; NORMAL: movl 4(%esp), [[EAX:%e..]]
159 ; NORMAL-NEXT: pushl   $4
160 ; NORMAL-NEXT: pushl   ([[EAX]])
161 ; NORMAL-NEXT: pushl   $2
162 ; NORMAL-NEXT: pushl   $1
163 ; NORMAL-NEXT: call
164 ; NORMAL-NEXT: addl $16, %esp
165 define void @test7(i32* %ptr) optsize {
166 entry:
167   %val = load i32* %ptr
168   call void @good(i32 1, i32 2, i32 %val, i32 4)
169   ret void
170 }
171
172 ; But we don't want to fold stack-relative loads into the push,
173 ; because the offset will be wrong
174 ; NORMAL-LABEL: test8:
175 ; NORMAL-NOT: subl {{.*}} %esp
176 ; NORMAL: movl 4(%esp), [[EAX:%e..]]
177 ; NORMAL-NEXT: pushl   $4
178 ; NORMAL-NEXT: pushl   [[EAX]]
179 ; NORMAL-NEXT: pushl   $2
180 ; NORMAL-NEXT: pushl   $1
181 ; NORMAL-NEXT: call
182 ; NORMAL-NEXT: addl $16, %esp
183 define void @test8(i32* %ptr) optsize {
184 entry:
185   %val = ptrtoint i32* %ptr to i32
186   call void @good(i32 1, i32 2, i32 %val, i32 4)
187   ret void
188 }
189
190 ; If one function is using push instructions, and the other isn't
191 ; (because it has frame-index references), then we must resolve
192 ; these references correctly.
193 ; NORMAL-LABEL: test9:
194 ; NORMAL-NOT: leal (%esp), 
195 ; NORMAL: pushl $4
196 ; NORMAL-NEXT: pushl $3
197 ; NORMAL-NEXT: pushl $2
198 ; NORMAL-NEXT: pushl $1
199 ; NORMAL-NEXT: call
200 ; NORMAL-NEXT: addl $16, %esp
201 ; NORMAL-NEXT: subl $16, %esp
202 ; NORMAL-NEXT: leal 16(%esp), [[EAX:%e..]]
203 ; NORMAL-NEXT: movl    [[EAX]], 12(%esp)
204 ; NORMAL-NEXT: movl    $7, 8(%esp)
205 ; NORMAL-NEXT: movl    $6, 4(%esp)
206 ; NORMAL-NEXT: movl    $5, (%esp)
207 ; NORMAL-NEXT: call
208 ; NORMAL-NEXT: addl $16, %esp
209 define void @test9() optsize {
210 entry:
211   %p = alloca i32, align 4
212   call void @good(i32 1, i32 2, i32 3, i32 4)
213   %0 = ptrtoint i32* %p to i32
214   call void @good(i32 5, i32 6, i32 7, i32 %0)
215   ret void
216 }
217
218 ; We can end up with an indirect call which gets reloaded on the spot.
219 ; Make sure we reference the correct stack slot - we spill into (%esp)
220 ; and reload from 16(%esp) due to the pushes.
221 ; NORMAL-LABEL: test10:
222 ; NORMAL: movl $_good, [[ALLOC:.*]]
223 ; NORMAL-NEXT: movl [[ALLOC]], [[EAX:%e..]]
224 ; NORMAL-NEXT: movl [[EAX]], (%esp) # 4-byte Spill
225 ; NORMAL: nop
226 ; NORMAL: pushl $4
227 ; NORMAL-NEXT: pushl $3
228 ; NORMAL-NEXT: pushl $2
229 ; NORMAL-NEXT: pushl $1
230 ; NORMAL-NEXT: calll *16(%esp)
231 ; NORMAL-NEXT: addl $16, %esp
232 define void @test10() optsize {
233   %stack_fptr = alloca void (i32, i32, i32, i32)*
234   store void (i32, i32, i32, i32)* @good, void (i32, i32, i32, i32)** %stack_fptr
235   %good_ptr = load volatile void (i32, i32, i32, i32)** %stack_fptr
236   call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di}"()
237   call void (i32, i32, i32, i32)* %good_ptr(i32 1, i32 2, i32 3, i32 4)
238   ret void
239 }
240
241 ; We can't fold the load from the global into the push because of 
242 ; interference from the store
243 ; NORMAL-LABEL: test11:
244 ; NORMAL: movl    _the_global, [[EAX:%e..]]
245 ; NORMAL-NEXT: movl    $42, _the_global
246 ; NORMAL-NEXT: pushl $4
247 ; NORMAL-NEXT: pushl $3
248 ; NORMAL-NEXT: pushl $2
249 ; NORMAL-NEXT: pushl [[EAX]]
250 ; NORMAL-NEXT: call
251 ; NORMAL-NEXT: addl $16, %esp
252 @the_global = external global i32
253 define void @test11() optsize {
254   %myload = load i32* @the_global
255   store i32 42, i32* @the_global
256   call void @good(i32 %myload, i32 2, i32 3, i32 4)
257   ret void
258 }