[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / ARM / fast-isel-intrinsic.ll
blobb308c4482d27568f51d9b48e337b58160d717c95
1 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-MACHO
2 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -verify-machineinstrs | FileCheck %s --check-prefix=ARM --check-prefix=ARM-ELF
3 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -verify-machineinstrs | FileCheck %s --check-prefix=THUMB
4 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG --check-prefix=ARM-LONG-MACHO
5 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=ARM-LONG --check-prefix=ARM-LONG-ELF
6 ; RUN: llc -fast-isel-sink-local-values < %s -O0 -fast-isel-abort=1 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=+long-calls -verify-machineinstrs | FileCheck %s --check-prefix=THUMB-LONG
8 ; Note that some of these tests assume that relocations are either
9 ; movw/movt or constant pool loads. Different platforms will select
10 ; different approaches.
12 @message1 = global [60 x i8] c"The LLVM Compiler Infrastructure\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 1
13 @temp = common global [60 x i8] zeroinitializer, align 1
15 define void @t1() nounwind ssp {
16 ; ARM-LABEL: t1:
17 ; ARM: {{(movw r0, :lower16:_?message1)|(ldr r0, .LCPI)}}
18 ; ARM: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}}
19 ; ARM-DAG: add r0, r0, #5
20 ; ARM-DAG: movw r1, #64
21 ; ARM-DAG: movw r2, #10
22 ; ARM-DAG: and r1, r1, #255
23 ; ARM: bl {{_?}}memset
24 ; ARM-LONG-LABEL: t1:
26 ; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memset\$non_lazy_ptr)|(ldr r3, .LCPI)}}
27 ; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memset\$non_lazy_ptr)?}}
28 ; ARM-LONG-MACHO: ldr r3, [r3]
30 ; ARM-LONG-ELF: movw r3, :lower16:memset
31 ; ARM-LONG-ELF: movt r3, :upper16:memset
33 ; ARM-LONG: blx r3
34 ; THUMB-LABEL: t1:
35 ; THUMB: {{(movw r0, :lower16:_?message1)|(ldr.n r0, .LCPI)}}
36 ; THUMB: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}}
37 ; THUMB: adds r0, #5
38 ; THUMB: movs r1, #64
39 ; THUMB: and r1, r1, #255
40 ; THUMB: movs r2, #10
41 ; THUMB: bl {{_?}}memset
42 ; THUMB-LONG-LABEL: t1:
43 ; THUMB-LONG: movw r3, :lower16:L_memset$non_lazy_ptr
44 ; THUMB-LONG: movt r3, :upper16:L_memset$non_lazy_ptr
45 ; THUMB-LONG: ldr r3, [r3]
46 ; THUMB-LONG: blx r3
47   call void @llvm.memset.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @message1, i32 0, i32 5), i8 64, i32 10, i1 false)
48   ret void
51 declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) nounwind
53 define void @t2() nounwind ssp {
54 ; ARM-LABEL: t2:
56 ; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
57 ; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
58 ; ARM-MACHO: ldr r0, [r0]
60 ; ARM-ELF: movw r0, :lower16:temp
61 ; ARM-ELF: movt r0, :upper16:temp
63 ; ARM: add r1, r0, #4
64 ; ARM: add r0, r0, #16
65 ; ARM: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill
66 ; ARM: mov r0, r1
67 ; ARM: ldr r1, [sp[[SLOT]]] @ 4-byte Reload
68 ; ARM: movw r2, #17
69 ; ARM: bl {{_?}}memcpy
70 ; ARM-LONG-LABEL: t2:
72 ; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memcpy\$non_lazy_ptr)|(ldr r3, .LCPI)}}
73 ; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memcpy\$non_lazy_ptr)?}}
74 ; ARM-LONG-MACHO: ldr r3, [r3]
76 ; ARM-LONG-ELF: movw r3, :lower16:memcpy
77 ; ARM-LONG-ELF: movt r3, :upper16:memcpy
79 ; ARM-LONG: blx r3
80 ; THUMB-LABEL: t2:
81 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
82 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
83 ; THUMB: ldr r0, [r0]
84 ; THUMB: adds r1, r0, #4
85 ; THUMB: adds r0, #16
86 ; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill
87 ; THUMB: mov r0, r1
88 ; THUMB: ldr r1,  [sp[[SLOT]]] @ 4-byte Reload
89 ; THUMB: movs r2, #17
90 ; THUMB: bl {{_?}}memcpy
91 ; THUMB-LONG-LABEL: t2:
92 ; THUMB-LONG: movw r3, :lower16:L_memcpy$non_lazy_ptr
93 ; THUMB-LONG: movt r3, :upper16:L_memcpy$non_lazy_ptr
94 ; THUMB-LONG: ldr r3, [r3]
95 ; THUMB-LONG: blx r3
96   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 17, i1 false)
97   ret void
100 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
102 define void @t3() nounwind ssp {
103 ; ARM-LABEL: t3:
105 ; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
106 ; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
107 ; ARM-MACHO: ldr r0, [r0]
109 ; ARM-ELF: movw r0, :lower16:temp
110 ; ARM-ELF: movt r0, :upper16:temp
113 ; ARM: add r1, r0, #4
114 ; ARM: add r0, r0, #16
115 ; ARM: mov r0, r1
116 ; ARM: movw r2, #10
117 ; ARM: bl {{_?}}memmove
118 ; ARM-LONG-LABEL: t3:
120 ; ARM-LONG-MACHO: {{(movw r3, :lower16:L_memmove\$non_lazy_ptr)|(ldr r3, .LCPI)}}
121 ; ARM-LONG-MACHO: {{(movt r3, :upper16:L_memmove\$non_lazy_ptr)?}}
122 ; ARM-LONG-MACHO: ldr r3, [r3]
124 ; ARM-LONG-ELF: movw r3, :lower16:memmove
125 ; ARM-LONG-ELF: movt r3, :upper16:memmove
127 ; ARM-LONG: blx r3
128 ; THUMB-LABEL: t3:
129 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
130 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
131 ; THUMB: ldr r0, [r0]
132 ; THUMB: adds r1, r0, #4
133 ; THUMB: adds r0, #16
134 ; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill
135 ; THUMB: mov r0, r1
136 ; THUMB: ldr r1,  [sp[[SLOT]]] @ 4-byte Reload
137 ; THUMB: movs r2, #10
138 ; THUMB: bl {{_?}}memmove
139 ; THUMB-LONG-LABEL: t3:
140 ; THUMB-LONG: movw r3, :lower16:L_memmove$non_lazy_ptr
141 ; THUMB-LONG: movt r3, :upper16:L_memmove$non_lazy_ptr
142 ; THUMB-LONG: ldr r3, [r3]
143 ; THUMB-LONG: blx r3
144   call void @llvm.memmove.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
145   ret void
148 define void @t4() nounwind ssp {
149 ; ARM-LABEL: t4:
151 ; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
152 ; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
153 ; ARM-MACHO: ldr r0, [r0]
155 ; ARM-ELF: movw r0, :lower16:temp
156 ; ARM-ELF: movt r0, :upper16:temp
158 ; ARM: ldr r1, [r0, #16]
159 ; ARM: str r1, [r0, #4]
160 ; ARM: ldr r1, [r0, #20]
161 ; ARM: str r1, [r0, #8]
162 ; ARM: ldrh r1, [r0, #24]
163 ; ARM: strh r1, [r0, #12]
164 ; ARM: bx lr
165 ; THUMB-LABEL: t4:
166 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
167 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
168 ; THUMB: ldr r0, [r0]
169 ; THUMB: ldr r1, [r0, #16]
170 ; THUMB: str r1, [r0, #4]
171 ; THUMB: ldr r1, [r0, #20]
172 ; THUMB: str r1, [r0, #8]
173 ; THUMB: ldrh r1, [r0, #24]
174 ; THUMB: strh r1, [r0, #12]
175 ; THUMB: bx lr
176   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 4 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
177   ret void
180 declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i1) nounwind
182 define void @t5() nounwind ssp {
183 ; ARM-LABEL: t5:
185 ; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
186 ; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
187 ; ARM-MACHO: ldr r0, [r0]
189 ; ARM-ELF: movw r0, :lower16:temp
190 ; ARM-ELF: movt r0, :upper16:temp
192 ; ARM: ldrh r1, [r0, #16]
193 ; ARM: strh r1, [r0, #4]
194 ; ARM: ldrh r1, [r0, #18]
195 ; ARM: strh r1, [r0, #6]
196 ; ARM: ldrh r1, [r0, #20]
197 ; ARM: strh r1, [r0, #8]
198 ; ARM: ldrh r1, [r0, #22]
199 ; ARM: strh r1, [r0, #10]
200 ; ARM: ldrh r1, [r0, #24]
201 ; ARM: strh r1, [r0, #12]
202 ; ARM: bx lr
203 ; THUMB-LABEL: t5:
204 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
205 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
206 ; THUMB: ldr r0, [r0]
207 ; THUMB: ldrh r1, [r0, #16]
208 ; THUMB: strh r1, [r0, #4]
209 ; THUMB: ldrh r1, [r0, #18]
210 ; THUMB: strh r1, [r0, #6]
211 ; THUMB: ldrh r1, [r0, #20]
212 ; THUMB: strh r1, [r0, #8]
213 ; THUMB: ldrh r1, [r0, #22]
214 ; THUMB: strh r1, [r0, #10]
215 ; THUMB: ldrh r1, [r0, #24]
216 ; THUMB: strh r1, [r0, #12]
217 ; THUMB: bx lr
218   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
219   ret void
222 define void @t6() nounwind ssp {
223 ; ARM-LABEL: t6:
225 ; ARM-MACHO: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}}
226 ; ARM-MACHO: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
227 ; ARM-MACHO: ldr r0, [r0]
229 ; ARM-ELF: movw r0, :lower16:temp
230 ; ARM-ELF: movt r0, :upper16:temp
232 ; ARM: ldrb r1, [r0, #16]
233 ; ARM: strb r1, [r0, #4]
234 ; ARM: ldrb r1, [r0, #17]
235 ; ARM: strb r1, [r0, #5]
236 ; ARM: ldrb r1, [r0, #18]
237 ; ARM: strb r1, [r0, #6]
238 ; ARM: ldrb r1, [r0, #19]
239 ; ARM: strb r1, [r0, #7]
240 ; ARM: ldrb r1, [r0, #20]
241 ; ARM: strb r1, [r0, #8]
242 ; ARM: ldrb r1, [r0, #21]
243 ; ARM: strb r1, [r0, #9]
244 ; ARM: ldrb r1, [r0, #22]
245 ; ARM: strb r1, [r0, #10]
246 ; ARM: ldrb r1, [r0, #23]
247 ; ARM: strb r1, [r0, #11]
248 ; ARM: ldrb r1, [r0, #24]
249 ; ARM: strb r1, [r0, #12]
250 ; ARM: ldrb r1, [r0, #25]
251 ; ARM: strb r1, [r0, #13]
252 ; ARM: bx lr
253 ; THUMB-LABEL: t6:
254 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}}
255 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}}
256 ; THUMB: ldr r0, [r0]
257 ; THUMB: ldrb r1, [r0, #16]
258 ; THUMB: strb r1, [r0, #4]
259 ; THUMB: ldrb r1, [r0, #17]
260 ; THUMB: strb r1, [r0, #5]
261 ; THUMB: ldrb r1, [r0, #18]
262 ; THUMB: strb r1, [r0, #6]
263 ; THUMB: ldrb r1, [r0, #19]
264 ; THUMB: strb r1, [r0, #7]
265 ; THUMB: ldrb r1, [r0, #20]
266 ; THUMB: strb r1, [r0, #8]
267 ; THUMB: ldrb r1, [r0, #21]
268 ; THUMB: strb r1, [r0, #9]
269 ; THUMB: ldrb r1, [r0, #22]
270 ; THUMB: strb r1, [r0, #10]
271 ; THUMB: ldrb r1, [r0, #23]
272 ; THUMB: strb r1, [r0, #11]
273 ; THUMB: ldrb r1, [r0, #24]
274 ; THUMB: strb r1, [r0, #12]
275 ; THUMB: ldrb r1, [r0, #25]
276 ; THUMB: strb r1, [r0, #13]
277 ; THUMB: bx lr
278   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 10, i1 false)
279   ret void
282 ; rdar://13202135
283 define void @t7() nounwind ssp {
284 ; Just make sure this doesn't assert when we have an odd length and an alignment of 2.
285   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 4), i8* align 2 getelementptr inbounds ([60 x i8], [60 x i8]* @temp, i32 0, i32 16), i32 3, i1 false)
286   ret void
289 define i32 @t8(i32 %x) nounwind {
290 entry:
291 ; ARM-LABEL: t8:
292 ; ARM-NOT: FastISel missed call:   %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
293 ; THUMB-LABEL: t8:
294 ; THUMB-NOT: FastISel missed call:   %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
295   %expval = call i32 @llvm.expect.i32(i32 %x, i32 1)
296   ret i32 %expval
299 declare i32 @llvm.expect.i32(i32, i32) nounwind readnone