1 ; RUN: llc < %s -mtriple armv7-linux-gnueabihf -mattr=+neon | FileCheck %s
3 ; This test checks the @llvm.cttz.* intrinsics for vectors.
5 declare <1 x i8> @llvm.cttz.v1i8(<1 x i8>, i1)
6 declare <2 x i8> @llvm.cttz.v2i8(<2 x i8>, i1)
7 declare <4 x i8> @llvm.cttz.v4i8(<4 x i8>, i1)
8 declare <8 x i8> @llvm.cttz.v8i8(<8 x i8>, i1)
9 declare <16 x i8> @llvm.cttz.v16i8(<16 x i8>, i1)
11 declare <1 x i16> @llvm.cttz.v1i16(<1 x i16>, i1)
12 declare <2 x i16> @llvm.cttz.v2i16(<2 x i16>, i1)
13 declare <4 x i16> @llvm.cttz.v4i16(<4 x i16>, i1)
14 declare <8 x i16> @llvm.cttz.v8i16(<8 x i16>, i1)
16 declare <1 x i32> @llvm.cttz.v1i32(<1 x i32>, i1)
17 declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1)
18 declare <4 x i32> @llvm.cttz.v4i32(<4 x i32>, i1)
20 declare <1 x i64> @llvm.cttz.v1i64(<1 x i64>, i1)
21 declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)
23 ;------------------------------------------------------------------------------
25 define void @test_v1i8(<1 x i8>* %p) {
26 ; CHECK-LABEL: test_v1i8
27 %a = load <1 x i8>, <1 x i8>* %p
28 %tmp = call <1 x i8> @llvm.cttz.v1i8(<1 x i8> %a, i1 false)
29 store <1 x i8> %tmp, <1 x i8>* %p
33 define void @test_v2i8(<2 x i8>* %p) {
34 ; CHECK-LABEL: test_v2i8:
35 %a = load <2 x i8>, <2 x i8>* %p
36 %tmp = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %a, i1 false)
37 store <2 x i8> %tmp, <2 x i8>* %p
41 define void @test_v4i8(<4 x i8>* %p) {
42 ; CHECK-LABEL: test_v4i8:
43 %a = load <4 x i8>, <4 x i8>* %p
44 %tmp = call <4 x i8> @llvm.cttz.v4i8(<4 x i8> %a, i1 false)
45 store <4 x i8> %tmp, <4 x i8>* %p
49 define void @test_v8i8(<8 x i8>* %p) {
50 ; CHECK-LABEL: test_v8i8:
51 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
52 ; CHECK: vmov.i8 [[D2:d[0-9]+]], #0x1
53 ; CHECK: vneg.s8 [[D3:d[0-9]+]], [[D1]]
54 ; CHECK: vand [[D1]], [[D1]], [[D3]]
55 ; CHECK: vsub.i8 [[D1]], [[D1]], [[D2]]
56 ; CHECK: vcnt.8 [[D1]], [[D1]]
57 ; CHECK: vstr [[D1]], [r0]
58 %a = load <8 x i8>, <8 x i8>* %p
59 %tmp = call <8 x i8> @llvm.cttz.v8i8(<8 x i8> %a, i1 false)
60 store <8 x i8> %tmp, <8 x i8>* %p
64 define void @test_v16i8(<16 x i8>* %p) {
65 ; CHECK-LABEL: test_v16i8:
66 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
67 ; CHECK: vmov.i8 [[Q2:q[0-9]+]], #0x1
68 ; CHECK: vneg.s8 [[Q3:q[0-9]+]], [[Q1:q[0-9]+]]
69 ; CHECK: vand [[Q1]], [[Q1]], [[Q3]]
70 ; CHECK: vsub.i8 [[Q1]], [[Q1]], [[Q2]]
71 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
72 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
73 %a = load <16 x i8>, <16 x i8>* %p
74 %tmp = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %a, i1 false)
75 store <16 x i8> %tmp, <16 x i8>* %p
79 define void @test_v1i16(<1 x i16>* %p) {
80 ; CHECK-LABEL: test_v1i16:
81 %a = load <1 x i16>, <1 x i16>* %p
82 %tmp = call <1 x i16> @llvm.cttz.v1i16(<1 x i16> %a, i1 false)
83 store <1 x i16> %tmp, <1 x i16>* %p
87 define void @test_v2i16(<2 x i16>* %p) {
88 ; CHECK-LABEL: test_v2i16:
89 %a = load <2 x i16>, <2 x i16>* %p
90 %tmp = call <2 x i16> @llvm.cttz.v2i16(<2 x i16> %a, i1 false)
91 store <2 x i16> %tmp, <2 x i16>* %p
95 define void @test_v4i16(<4 x i16>* %p) {
96 ; CHECK-LABEL: test_v4i16:
97 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
98 ; CHECK: vmov.i16 [[D2:d[0-9]+]], #0x1
99 ; CHECK: vneg.s16 [[D3:d[0-9]+]], [[D1]]
100 ; CHECK: vand [[D1]], [[D1]], [[D3]]
101 ; CHECK: vsub.i16 [[D1]], [[D1]], [[D2]]
102 ; CHECK: vcnt.8 [[D1]], [[D1]]
103 ; CHECK: vpaddl.u8 [[D1]], [[D1]]
104 ; CHECK: vstr [[D1]], [r0]
105 %a = load <4 x i16>, <4 x i16>* %p
106 %tmp = call <4 x i16> @llvm.cttz.v4i16(<4 x i16> %a, i1 false)
107 store <4 x i16> %tmp, <4 x i16>* %p
111 define void @test_v8i16(<8 x i16>* %p) {
112 ; CHECK-LABEL: test_v8i16:
113 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
114 ; CHECK: vmov.i16 [[Q2:q[0-9]+]], #0x1
115 ; CHECK: vneg.s16 [[Q3:q[0-9]+]], [[Q1:q[0-9]+]]
116 ; CHECK: vand [[Q1]], [[Q1]], [[Q3]]
117 ; CHECK: vsub.i16 [[Q1]], [[Q1]], [[Q2]]
118 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
119 ; CHECK: vpaddl.u8 [[Q1]], [[Q1]]
120 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
121 %a = load <8 x i16>, <8 x i16>* %p
122 %tmp = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %a, i1 false)
123 store <8 x i16> %tmp, <8 x i16>* %p
127 define void @test_v1i32(<1 x i32>* %p) {
128 ; CHECK-LABEL: test_v1i32:
129 %a = load <1 x i32>, <1 x i32>* %p
130 %tmp = call <1 x i32> @llvm.cttz.v1i32(<1 x i32> %a, i1 false)
131 store <1 x i32> %tmp, <1 x i32>* %p
135 define void @test_v2i32(<2 x i32>* %p) {
136 ; CHECK-LABEL: test_v2i32:
137 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
138 ; CHECK: vmov.i32 [[D2:d[0-9]+]], #0x1
139 ; CHECK: vneg.s32 [[D3:d[0-9]+]], [[D1]]
140 ; CHECK: vand [[D1]], [[D1]], [[D3]]
141 ; CHECK: vsub.i32 [[D1]], [[D1]], [[D2]]
142 ; CHECK: vcnt.8 [[D1]], [[D1]]
143 ; CHECK: vpaddl.u8 [[D1]], [[D1]]
144 ; CHECK: vpaddl.u16 [[D1]], [[D1]]
145 ; CHECK: vstr [[D1]], [r0]
146 %a = load <2 x i32>, <2 x i32>* %p
147 %tmp = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %a, i1 false)
148 store <2 x i32> %tmp, <2 x i32>* %p
152 define void @test_v4i32(<4 x i32>* %p) {
153 ; CHECK-LABEL: test_v4i32:
154 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
155 ; CHECK: vmov.i32 [[Q2:q[0-9]+]], #0x1
156 ; CHECK: vneg.s32 [[Q3:q[0-9]+]], [[Q1:q[0-9]+]]
157 ; CHECK: vand [[Q1]], [[Q1]], [[Q3]]
158 ; CHECK: vsub.i32 [[Q1]], [[Q1]], [[Q2]]
159 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
160 ; CHECK: vpaddl.u8 [[Q1]], [[Q1]]
161 ; CHECK: vpaddl.u16 [[Q1]], [[Q1]]
162 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
163 %a = load <4 x i32>, <4 x i32>* %p
164 %tmp = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 false)
165 store <4 x i32> %tmp, <4 x i32>* %p
169 define void @test_v1i64(<1 x i64>* %p) {
170 ; CHECK-LABEL: test_v1i64:
171 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
172 ; CHECK: vmov.i32 [[D2:d[0-9]+]], #0x0
173 ; CHECK: vmov.i64 [[D3:d[0-9]+]], #0xffffffffffffffff
174 ; CHECK: vsub.i64 [[D2]], [[D2]], [[D1]]
175 ; CHECK: vand [[D1]], [[D1]], [[D2]]
176 ; CHECK: vadd.i64 [[D1]], [[D1]], [[D3]]
177 ; CHECK: vcnt.8 [[D1]], [[D1]]
178 ; CHECK: vpaddl.u8 [[D1]], [[D1]]
179 ; CHECK: vpaddl.u16 [[D1]], [[D1]]
180 ; CHECK: vpaddl.u32 [[D1]], [[D1]]
181 ; CHECK: vstr [[D1]], [r0]
182 %a = load <1 x i64>, <1 x i64>* %p
183 %tmp = call <1 x i64> @llvm.cttz.v1i64(<1 x i64> %a, i1 false)
184 store <1 x i64> %tmp, <1 x i64>* %p
188 define void @test_v2i64(<2 x i64>* %p) {
189 ; CHECK-LABEL: test_v2i64:
190 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
191 ; CHECK: vmov.i32 [[Q2:q[0-9]+]], #0x0
192 ; CHECK: vmov.i64 [[Q3:q[0-9]+]], #0xffffffffffffffff
193 ; CHECK: vsub.i64 [[Q2]], [[Q2]], [[Q1:q[0-9]+]]
194 ; CHECK: vand [[Q1]], [[Q1]], [[Q2]]
195 ; CHECK: vadd.i64 [[Q1]], [[Q1]], [[Q3]]
196 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
197 ; CHECK: vpaddl.u8 [[Q1]], [[Q1]]
198 ; CHECK: vpaddl.u16 [[Q1]], [[Q1]]
199 ; CHECK: vpaddl.u32 [[Q1]], [[Q1]]
200 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
201 %a = load <2 x i64>, <2 x i64>* %p
202 %tmp = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a, i1 false)
203 store <2 x i64> %tmp, <2 x i64>* %p
207 ;------------------------------------------------------------------------------
209 define void @test_v1i8_zero_undef(<1 x i8>* %p) {
210 ; CHECK-LABEL: test_v1i8_zero_undef
211 %a = load <1 x i8>, <1 x i8>* %p
212 %tmp = call <1 x i8> @llvm.cttz.v1i8(<1 x i8> %a, i1 true)
213 store <1 x i8> %tmp, <1 x i8>* %p
217 define void @test_v2i8_zero_undef(<2 x i8>* %p) {
218 ; CHECK-LABEL: test_v2i8_zero_undef:
219 %a = load <2 x i8>, <2 x i8>* %p
220 %tmp = call <2 x i8> @llvm.cttz.v2i8(<2 x i8> %a, i1 true)
221 store <2 x i8> %tmp, <2 x i8>* %p
225 define void @test_v4i8_zero_undef(<4 x i8>* %p) {
226 ; CHECK-LABEL: test_v4i8_zero_undef:
227 %a = load <4 x i8>, <4 x i8>* %p
228 %tmp = call <4 x i8> @llvm.cttz.v4i8(<4 x i8> %a, i1 true)
229 store <4 x i8> %tmp, <4 x i8>* %p
233 define void @test_v8i8_zero_undef(<8 x i8>* %p) {
234 ; CHECK-LABEL: test_v8i8_zero_undef:
235 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
236 ; CHECK: vmov.i8 [[D2:d[0-9]+]], #0x1
237 ; CHECK: vneg.s8 [[D3:d[0-9]+]], [[D1]]
238 ; CHECK: vand [[D1]], [[D1]], [[D3]]
239 ; CHECK: vsub.i8 [[D1]], [[D1]], [[D2]]
240 ; CHECK: vcnt.8 [[D1]], [[D1]]
241 ; CHECK: vstr [[D1]], [r0]
242 %a = load <8 x i8>, <8 x i8>* %p
243 %tmp = call <8 x i8> @llvm.cttz.v8i8(<8 x i8> %a, i1 true)
244 store <8 x i8> %tmp, <8 x i8>* %p
248 define void @test_v16i8_zero_undef(<16 x i8>* %p) {
249 ; CHECK-LABEL: test_v16i8_zero_undef:
250 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
251 ; CHECK: vmov.i8 [[Q2:q[0-9]+]], #0x1
252 ; CHECK: vneg.s8 [[Q3:q[0-9]+]], [[Q1:q[0-9]+]]
253 ; CHECK: vand [[Q1]], [[Q1]], [[Q3]]
254 ; CHECK: vsub.i8 [[Q1]], [[Q1]], [[Q2]]
255 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
256 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
257 %a = load <16 x i8>, <16 x i8>* %p
258 %tmp = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %a, i1 true)
259 store <16 x i8> %tmp, <16 x i8>* %p
263 define void @test_v1i16_zero_undef(<1 x i16>* %p) {
264 ; CHECK-LABEL: test_v1i16_zero_undef:
265 %a = load <1 x i16>, <1 x i16>* %p
266 %tmp = call <1 x i16> @llvm.cttz.v1i16(<1 x i16> %a, i1 true)
267 store <1 x i16> %tmp, <1 x i16>* %p
271 define void @test_v2i16_zero_undef(<2 x i16>* %p) {
272 ; CHECK-LABEL: test_v2i16_zero_undef:
273 %a = load <2 x i16>, <2 x i16>* %p
274 %tmp = call <2 x i16> @llvm.cttz.v2i16(<2 x i16> %a, i1 true)
275 store <2 x i16> %tmp, <2 x i16>* %p
279 define void @test_v4i16_zero_undef(<4 x i16>* %p) {
280 ; CHECK-LABEL: test_v4i16_zero_undef:
281 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
282 ; CHECK: vneg.s16 [[D2:d[0-9]+]], [[D1]]
283 ; CHECK: vand [[D1]], [[D1]], [[D2]]
284 ; CHECK: vmov.i16 [[D3:d[0-9]+]], #0xf
285 ; CHECK: vclz.i16 [[D1]], [[D1]]
286 ; CHECK: vsub.i16 [[D1]], [[D3]], [[D1]]
287 ; CHECK: vstr [[D1]], [r0]
288 %a = load <4 x i16>, <4 x i16>* %p
289 %tmp = call <4 x i16> @llvm.cttz.v4i16(<4 x i16> %a, i1 true)
290 store <4 x i16> %tmp, <4 x i16>* %p
294 define void @test_v8i16_zero_undef(<8 x i16>* %p) {
295 ; CHECK-LABEL: test_v8i16_zero_undef:
296 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
297 ; CHECK: vneg.s16 [[Q2:q[0-9]+]], [[Q1:q[0-9]+]]
298 ; CHECK: vand [[Q1]], [[Q1]], [[Q2]]
299 ; CHECK: vmov.i16 [[Q3:q[0-9]+]], #0xf
300 ; CHECK: vclz.i16 [[Q1]], [[Q1]]
301 ; CHECK: vsub.i16 [[Q1]], [[Q3]], [[Q1]]
302 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
303 %a = load <8 x i16>, <8 x i16>* %p
304 %tmp = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %a, i1 true)
305 store <8 x i16> %tmp, <8 x i16>* %p
309 define void @test_v1i32_zero_undef(<1 x i32>* %p) {
310 ; CHECK-LABEL: test_v1i32_zero_undef:
311 %a = load <1 x i32>, <1 x i32>* %p
312 %tmp = call <1 x i32> @llvm.cttz.v1i32(<1 x i32> %a, i1 true)
313 store <1 x i32> %tmp, <1 x i32>* %p
317 define void @test_v2i32_zero_undef(<2 x i32>* %p) {
318 ; CHECK-LABEL: test_v2i32_zero_undef:
319 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
320 ; CHECK: vneg.s32 [[D2:d[0-9]+]], [[D1]]
321 ; CHECK: vand [[D1]], [[D1]], [[D2]]
322 ; CHECK: vmov.i32 [[D3:d[0-9]+]], #0x1f
323 ; CHECK: vclz.i32 [[D1]], [[D1]]
324 ; CHECK: vsub.i32 [[D1]], [[D3]], [[D1]]
325 ; CHECK: vstr [[D1]], [r0]
326 %a = load <2 x i32>, <2 x i32>* %p
327 %tmp = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %a, i1 true)
328 store <2 x i32> %tmp, <2 x i32>* %p
332 define void @test_v4i32_zero_undef(<4 x i32>* %p) {
333 ; CHECK-LABEL: test_v4i32_zero_undef:
334 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
335 ; CHECK: vneg.s32 [[Q2:q[0-9]+]], [[Q1:q[0-9]+]]
336 ; CHECK: vand [[Q1]], [[Q1]], [[Q2]]
337 ; CHECK: vmov.i32 [[Q3:q[0-9]+]], #0x1f
338 ; CHECK: vclz.i32 [[Q1]], [[Q1]]
339 ; CHECK: vsub.i32 [[Q1]], [[Q3]], [[Q1]]
340 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
341 %a = load <4 x i32>, <4 x i32>* %p
342 %tmp = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 true)
343 store <4 x i32> %tmp, <4 x i32>* %p
347 define void @test_v1i64_zero_undef(<1 x i64>* %p) {
348 ; CHECK-LABEL: test_v1i64_zero_undef:
349 ; CHECK: vldr [[D1:d[0-9]+]], [r0]
350 ; CHECK: vmov.i32 [[D2:d[0-9]+]], #0x0
351 ; CHECK: vmov.i64 [[D3:d[0-9]+]], #0xffffffffffffffff
352 ; CHECK: vsub.i64 [[D2]], [[D2]], [[D1]]
353 ; CHECK: vand [[D1]], [[D1]], [[D2]]
354 ; CHECK: vadd.i64 [[D1]], [[D1]], [[D3]]
355 ; CHECK: vcnt.8 [[D1]], [[D1]]
356 ; CHECK: vpaddl.u8 [[D1]], [[D1]]
357 ; CHECK: vpaddl.u16 [[D1]], [[D1]]
358 ; CHECK: vpaddl.u32 [[D1]], [[D1]]
359 ; CHECK: vstr [[D1]], [r0]
360 %a = load <1 x i64>, <1 x i64>* %p
361 %tmp = call <1 x i64> @llvm.cttz.v1i64(<1 x i64> %a, i1 true)
362 store <1 x i64> %tmp, <1 x i64>* %p
366 define void @test_v2i64_zero_undef(<2 x i64>* %p) {
367 ; CHECK-LABEL: test_v2i64_zero_undef:
368 ; CHECK: vld1.64 {[[D1:d[0-9]+]], [[D2:d[0-9]+]]}, [r0]
369 ; CHECK: vmov.i32 [[Q2:q[0-9]+]], #0x0
370 ; CHECK: vmov.i64 [[Q3:q[0-9]+]], #0xffffffffffffffff
371 ; CHECK: vsub.i64 [[Q2]], [[Q2]], [[Q1:q[0-9]+]]
372 ; CHECK: vand [[Q1]], [[Q1]], [[Q2]]
373 ; CHECK: vadd.i64 [[Q1]], [[Q1]], [[Q3]]
374 ; CHECK: vcnt.8 [[Q1]], [[Q1]]
375 ; CHECK: vpaddl.u8 [[Q1]], [[Q1]]
376 ; CHECK: vpaddl.u16 [[Q1]], [[Q1]]
377 ; CHECK: vpaddl.u32 [[Q1]], [[Q1]]
378 ; CHECK: vst1.64 {[[D1]], [[D2]]}, [r0]
379 %a = load <2 x i64>, <2 x i64>* %p
380 %tmp = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a, i1 true)
381 store <2 x i64> %tmp, <2 x i64>* %p