[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / CodeGen / Thumb2 / mve-laneinterleaving.ll
blobaf0920475dbf4e1eeda3f24f329d873c24bd6c17
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs %s -o - | FileCheck %s
4 define arm_aapcs_vfpcc <4 x i32> @sext_trunc_i32(<4 x i32> %a) {
5 ; CHECK-LABEL: sext_trunc_i32:
6 ; CHECK:       @ %bb.0: @ %entry
7 ; CHECK-NEXT:    bx lr
8 entry:
9   %sa = sext <4 x i32> %a to <4 x i64>
10   %t = trunc <4 x i64> %sa to <4 x i32>
11   ret <4 x i32> %t
14 define arm_aapcs_vfpcc <8 x i16> @sext_trunc_i16(<8 x i16> %a) {
15 ; CHECK-LABEL: sext_trunc_i16:
16 ; CHECK:       @ %bb.0: @ %entry
17 ; CHECK-NEXT:    bx lr
18 entry:
19   %sa = sext <8 x i16> %a to <8 x i32>
20   %t = trunc <8 x i32> %sa to <8 x i16>
21   ret <8 x i16> %t
24 define arm_aapcs_vfpcc <16 x i8> @sext_trunc_i8(<16 x i8> %a) {
25 ; CHECK-LABEL: sext_trunc_i8:
26 ; CHECK:       @ %bb.0: @ %entry
27 ; CHECK-NEXT:    bx lr
28 entry:
29   %sa = sext <16 x i8> %a to <16 x i16>
30   %t = trunc <16 x i16> %sa to <16 x i8>
31   ret <16 x i8> %t
34 define arm_aapcs_vfpcc <4 x i32> @zext_trunc_i32(<4 x i32> %a) {
35 ; CHECK-LABEL: zext_trunc_i32:
36 ; CHECK:       @ %bb.0: @ %entry
37 ; CHECK-NEXT:    bx lr
38 entry:
39   %sa = zext <4 x i32> %a to <4 x i64>
40   %t = trunc <4 x i64> %sa to <4 x i32>
41   ret <4 x i32> %t
44 define arm_aapcs_vfpcc <8 x i16> @zext_trunc_i16(<8 x i16> %a) {
45 ; CHECK-LABEL: zext_trunc_i16:
46 ; CHECK:       @ %bb.0: @ %entry
47 ; CHECK-NEXT:    bx lr
48 entry:
49   %sa = zext <8 x i16> %a to <8 x i32>
50   %t = trunc <8 x i32> %sa to <8 x i16>
51   ret <8 x i16> %t
54 define arm_aapcs_vfpcc <16 x i8> @zext_trunc_i8(<16 x i8> %a) {
55 ; CHECK-LABEL: zext_trunc_i8:
56 ; CHECK:       @ %bb.0: @ %entry
57 ; CHECK-NEXT:    bx lr
58 entry:
59   %sa = zext <16 x i8> %a to <16 x i16>
60   %t = trunc <16 x i16> %sa to <16 x i8>
61   ret <16 x i8> %t
64 define arm_aapcs_vfpcc <4 x i32> @ext_add_trunc_i32(<4 x i32> %a, <4 x i32> %b) {
65 ; CHECK-LABEL: ext_add_trunc_i32:
66 ; CHECK:       @ %bb.0: @ %entry
67 ; CHECK-NEXT:    vmov.f32 s8, s6
68 ; CHECK-NEXT:    vmov.f32 s6, s7
69 ; CHECK-NEXT:    vmov r0, s8
70 ; CHECK-NEXT:    vmov.f32 s8, s2
71 ; CHECK-NEXT:    vmov.f32 s2, s3
72 ; CHECK-NEXT:    vmov r1, s8
73 ; CHECK-NEXT:    vmov r2, s2
74 ; CHECK-NEXT:    vmov.f32 s2, s5
75 ; CHECK-NEXT:    add.w r12, r1, r0
76 ; CHECK-NEXT:    vmov r1, s6
77 ; CHECK-NEXT:    vmov r0, s0
78 ; CHECK-NEXT:    add r1, r2
79 ; CHECK-NEXT:    vmov r2, s2
80 ; CHECK-NEXT:    vmov.f32 s2, s1
81 ; CHECK-NEXT:    vmov r3, s2
82 ; CHECK-NEXT:    add r2, r3
83 ; CHECK-NEXT:    vmov r3, s4
84 ; CHECK-NEXT:    add r0, r3
85 ; CHECK-NEXT:    vmov q0[2], q0[0], r0, r12
86 ; CHECK-NEXT:    vmov q0[3], q0[1], r2, r1
87 ; CHECK-NEXT:    bx lr
88 entry:
89   %sa = sext <4 x i32> %a to <4 x i64>
90   %sb = zext <4 x i32> %b to <4 x i64>
91   %add = add <4 x i64> %sa, %sb
92   %t = trunc <4 x i64> %add to <4 x i32>
93   ret <4 x i32> %t
96 define arm_aapcs_vfpcc <8 x i16> @ext_add_trunc_v8i16(<8 x i16> %a, <8 x i16> %b) {
97 ; CHECK-LABEL: ext_add_trunc_v8i16:
98 ; CHECK:       @ %bb.0: @ %entry
99 ; CHECK-NEXT:    vrev32.16 q3, q0
100 ; CHECK-NEXT:    vrev32.16 q2, q1
101 ; CHECK-NEXT:    vadd.i32 q2, q3, q2
102 ; CHECK-NEXT:    vadd.i32 q0, q0, q1
103 ; CHECK-NEXT:    vmovnt.i32 q0, q2
104 ; CHECK-NEXT:    bx lr
105 entry:
106   %sa = sext <8 x i16> %a to <8 x i32>
107   %sb = zext <8 x i16> %b to <8 x i32>
108   %add = add <8 x i32> %sa, %sb
109   %t = trunc <8 x i32> %add to <8 x i16>
110   ret <8 x i16> %t
113 define arm_aapcs_vfpcc <16 x i8> @ext_add_trunc_v16i8(<16 x i8> %a, <16 x i8> %b) {
114 ; CHECK-LABEL: ext_add_trunc_v16i8:
115 ; CHECK:       @ %bb.0: @ %entry
116 ; CHECK-NEXT:    vrev16.8 q3, q0
117 ; CHECK-NEXT:    vrev16.8 q2, q1
118 ; CHECK-NEXT:    vadd.i16 q2, q3, q2
119 ; CHECK-NEXT:    vadd.i16 q0, q0, q1
120 ; CHECK-NEXT:    vmovnt.i16 q0, q2
121 ; CHECK-NEXT:    bx lr
122 entry:
123   %sa = sext <16 x i8> %a to <16 x i16>
124   %sb = zext <16 x i8> %b to <16 x i16>
125   %add = add <16 x i16> %sa, %sb
126   %t = trunc <16 x i16> %add to <16 x i8>
127   ret <16 x i8> %t
130 define arm_aapcs_vfpcc <16 x i16> @ext_add_trunc_v16i16(<16 x i16> %a, <16 x i16> %b) {
131 ; CHECK-LABEL: ext_add_trunc_v16i16:
132 ; CHECK:       @ %bb.0: @ %entry
133 ; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
134 ; CHECK-NEXT:    vpush {d8, d9, d10, d11}
135 ; CHECK-NEXT:    vrev32.16 q5, q0
136 ; CHECK-NEXT:    vrev32.16 q4, q2
137 ; CHECK-NEXT:    vadd.i32 q0, q0, q2
138 ; CHECK-NEXT:    vadd.i32 q4, q5, q4
139 ; CHECK-NEXT:    vmovnt.i32 q0, q4
140 ; CHECK-NEXT:    vrev32.16 q4, q1
141 ; CHECK-NEXT:    vrev32.16 q2, q3
142 ; CHECK-NEXT:    vadd.i32 q1, q1, q3
143 ; CHECK-NEXT:    vadd.i32 q2, q4, q2
144 ; CHECK-NEXT:    vmovnt.i32 q1, q2
145 ; CHECK-NEXT:    vpop {d8, d9, d10, d11}
146 ; CHECK-NEXT:    bx lr
147 entry:
148   %sa = sext <16 x i16> %a to <16 x i32>
149   %sb = zext <16 x i16> %b to <16 x i32>
150   %add = add <16 x i32> %sa, %sb
151   %t = trunc <16 x i32> %add to <16 x i16>
152   ret <16 x i16> %t
155 define arm_aapcs_vfpcc <32 x i8> @ext_add_trunc_v32i8(<32 x i8> %a, <32 x i8> %b) {
156 ; CHECK-LABEL: ext_add_trunc_v32i8:
157 ; CHECK:       @ %bb.0: @ %entry
158 ; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
159 ; CHECK-NEXT:    vpush {d8, d9, d10, d11}
160 ; CHECK-NEXT:    vrev16.8 q5, q0
161 ; CHECK-NEXT:    vrev16.8 q4, q2
162 ; CHECK-NEXT:    vadd.i16 q0, q0, q2
163 ; CHECK-NEXT:    vadd.i16 q4, q5, q4
164 ; CHECK-NEXT:    vmovnt.i16 q0, q4
165 ; CHECK-NEXT:    vrev16.8 q4, q1
166 ; CHECK-NEXT:    vrev16.8 q2, q3
167 ; CHECK-NEXT:    vadd.i16 q1, q1, q3
168 ; CHECK-NEXT:    vadd.i16 q2, q4, q2
169 ; CHECK-NEXT:    vmovnt.i16 q1, q2
170 ; CHECK-NEXT:    vpop {d8, d9, d10, d11}
171 ; CHECK-NEXT:    bx lr
172 entry:
173   %sa = sext <32 x i8> %a to <32 x i16>
174   %sb = zext <32 x i8> %b to <32 x i16>
175   %add = add <32 x i16> %sa, %sb
176   %t = trunc <32 x i16> %add to <32 x i8>
177   ret <32 x i8> %t
180 define arm_aapcs_vfpcc <4 x i32> @ext_add_ashr_trunc_i32(<4 x i32> %a, <4 x i32> %b) {
181 ; CHECK-LABEL: ext_add_ashr_trunc_i32:
182 ; CHECK:       @ %bb.0: @ %entry
183 ; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}
184 ; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
185 ; CHECK-NEXT:    vmov.f32 s12, s6
186 ; CHECK-NEXT:    vmov.i64 q2, #0xffffffff
187 ; CHECK-NEXT:    vmov.f32 s6, s5
188 ; CHECK-NEXT:    vmov.f32 s14, s7
189 ; CHECK-NEXT:    vand q1, q1, q2
190 ; CHECK-NEXT:    vmov r3, r7, d2
191 ; CHECK-NEXT:    vand q3, q3, q2
192 ; CHECK-NEXT:    vmov.f32 s4, s2
193 ; CHECK-NEXT:    vmov r0, r1, d6
194 ; CHECK-NEXT:    vmov.f32 s2, s3
195 ; CHECK-NEXT:    vmov lr, r12, d7
196 ; CHECK-NEXT:    vmov r2, s4
197 ; CHECK-NEXT:    asrs r5, r2, #31
198 ; CHECK-NEXT:    adds r2, r2, r0
199 ; CHECK-NEXT:    vmov r0, s2
200 ; CHECK-NEXT:    adcs r1, r5
201 ; CHECK-NEXT:    vmov r5, s0
202 ; CHECK-NEXT:    lsrl r2, r1, #1
203 ; CHECK-NEXT:    asrs r1, r0, #31
204 ; CHECK-NEXT:    adds.w r0, r0, lr
205 ; CHECK-NEXT:    adc.w r1, r1, r12
206 ; CHECK-NEXT:    asrs r4, r5, #31
207 ; CHECK-NEXT:    adds r6, r5, r3
208 ; CHECK-NEXT:    vmov r3, r5, d3
209 ; CHECK-NEXT:    vmov.f32 s6, s1
210 ; CHECK-NEXT:    lsrl r0, r1, #1
211 ; CHECK-NEXT:    adcs r7, r4
212 ; CHECK-NEXT:    lsrl r6, r7, #1
213 ; CHECK-NEXT:    vmov q0[2], q0[0], r6, r2
214 ; CHECK-NEXT:    vmov r1, s6
215 ; CHECK-NEXT:    adds r6, r1, r3
216 ; CHECK-NEXT:    asr.w r2, r1, #31
217 ; CHECK-NEXT:    adc.w r1, r2, r5
218 ; CHECK-NEXT:    lsrl r6, r1, #1
219 ; CHECK-NEXT:    vmov q0[3], q0[1], r6, r0
220 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
221 entry:
222   %sa = sext <4 x i32> %a to <4 x i64>
223   %sb = zext <4 x i32> %b to <4 x i64>
224   %add = add <4 x i64> %sa, %sb
225   %sh = ashr <4 x i64> %add, <i64 1, i64 1, i64 1, i64 1>
226   %t = trunc <4 x i64> %sh to <4 x i32>
227   ret <4 x i32> %t
230 define arm_aapcs_vfpcc <8 x i16> @ext_add_ashr_trunc_i16(<8 x i16> %a, <8 x i16> %b) {
231 ; CHECK-LABEL: ext_add_ashr_trunc_i16:
232 ; CHECK:       @ %bb.0: @ %entry
233 ; CHECK-NEXT:    vmovlt.u16 q2, q1
234 ; CHECK-NEXT:    vmovlt.s16 q3, q0
235 ; CHECK-NEXT:    vmovlb.u16 q1, q1
236 ; CHECK-NEXT:    vmovlb.s16 q0, q0
237 ; CHECK-NEXT:    vhadd.s32 q2, q3, q2
238 ; CHECK-NEXT:    vhadd.s32 q0, q0, q1
239 ; CHECK-NEXT:    vmovnt.i32 q0, q2
240 ; CHECK-NEXT:    bx lr
241 entry:
242   %sa = sext <8 x i16> %a to <8 x i32>
243   %sb = zext <8 x i16> %b to <8 x i32>
244   %add = add <8 x i32> %sa, %sb
245   %sh = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
246   %t = trunc <8 x i32> %sh to <8 x i16>
247   ret <8 x i16> %t
250 define arm_aapcs_vfpcc <16 x i8> @ext_add_ashr_trunc_i8(<16 x i8> %a, <16 x i8> %b) {
251 ; CHECK-LABEL: ext_add_ashr_trunc_i8:
252 ; CHECK:       @ %bb.0: @ %entry
253 ; CHECK-NEXT:    vmovlb.u8 q2, q1
254 ; CHECK-NEXT:    vmovlb.s8 q3, q0
255 ; CHECK-NEXT:    vmovlt.u8 q1, q1
256 ; CHECK-NEXT:    vmovlt.s8 q0, q0
257 ; CHECK-NEXT:    vadd.i16 q0, q0, q1
258 ; CHECK-NEXT:    vadd.i16 q2, q3, q2
259 ; CHECK-NEXT:    vshr.u16 q1, q0, #1
260 ; CHECK-NEXT:    vshr.u16 q0, q2, #1
261 ; CHECK-NEXT:    vmovnt.i16 q0, q1
262 ; CHECK-NEXT:    bx lr
263 entry:
264   %sa = sext <16 x i8> %a to <16 x i16>
265   %sb = zext <16 x i8> %b to <16 x i16>
266   %add = add <16 x i16> %sa, %sb
267   %sh = ashr <16 x i16> %add, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
268   %t = trunc <16 x i16> %sh to <16 x i8>
269   ret <16 x i8> %t
272 define arm_aapcs_vfpcc <16 x i8> @ext_add_ashr_trunc_i8i32(<16 x i8> %a, <16 x i8> %b) {
273 ; CHECK-LABEL: ext_add_ashr_trunc_i8i32:
274 ; CHECK:       @ %bb.0: @ %entry
275 ; CHECK-NEXT:    .save {r4, r5, r7, lr}
276 ; CHECK-NEXT:    push {r4, r5, r7, lr}
277 ; CHECK-NEXT:    .pad #112
278 ; CHECK-NEXT:    sub sp, #112
279 ; CHECK-NEXT:    add r1, sp, #16
280 ; CHECK-NEXT:    mov r4, sp
281 ; CHECK-NEXT:    vstrw.32 q1, [r1]
282 ; CHECK-NEXT:    vstrw.32 q0, [r4]
283 ; CHECK-NEXT:    vldrb.u16 q0, [r1, #8]
284 ; CHECK-NEXT:    add r3, sp, #64
285 ; CHECK-NEXT:    add r5, sp, #32
286 ; CHECK-NEXT:    add r0, sp, #80
287 ; CHECK-NEXT:    vstrw.32 q0, [r3]
288 ; CHECK-NEXT:    add r2, sp, #48
289 ; CHECK-NEXT:    vldrb.s16 q0, [r4, #8]
290 ; CHECK-NEXT:    vstrw.32 q0, [r5]
291 ; CHECK-NEXT:    vldrb.u16 q0, [r1]
292 ; CHECK-NEXT:    add r1, sp, #96
293 ; CHECK-NEXT:    vstrw.32 q0, [r0]
294 ; CHECK-NEXT:    vldrb.s16 q0, [r4]
295 ; CHECK-NEXT:    vstrw.32 q0, [r2]
296 ; CHECK-NEXT:    vldrh.u32 q0, [r3, #8]
297 ; CHECK-NEXT:    vldrh.s32 q1, [r5, #8]
298 ; CHECK-NEXT:    vadd.i32 q0, q1, q0
299 ; CHECK-NEXT:    vshr.u32 q0, q0, #1
300 ; CHECK-NEXT:    vstrb.32 q0, [r1, #12]
301 ; CHECK-NEXT:    vldrh.u32 q0, [r3]
302 ; CHECK-NEXT:    vldrh.s32 q1, [r5]
303 ; CHECK-NEXT:    vadd.i32 q0, q1, q0
304 ; CHECK-NEXT:    vshr.u32 q0, q0, #1
305 ; CHECK-NEXT:    vstrb.32 q0, [r1, #8]
306 ; CHECK-NEXT:    vldrh.u32 q0, [r0, #8]
307 ; CHECK-NEXT:    vldrh.s32 q1, [r2, #8]
308 ; CHECK-NEXT:    vadd.i32 q0, q1, q0
309 ; CHECK-NEXT:    vshr.u32 q0, q0, #1
310 ; CHECK-NEXT:    vstrb.32 q0, [r1, #4]
311 ; CHECK-NEXT:    vldrh.u32 q0, [r0]
312 ; CHECK-NEXT:    vldrh.s32 q1, [r2]
313 ; CHECK-NEXT:    vadd.i32 q0, q1, q0
314 ; CHECK-NEXT:    vshr.u32 q0, q0, #1
315 ; CHECK-NEXT:    vstrb.32 q0, [r1]
316 ; CHECK-NEXT:    vldrw.u32 q0, [r1]
317 ; CHECK-NEXT:    add sp, #112
318 ; CHECK-NEXT:    pop {r4, r5, r7, pc}
319 entry:
320   %sa = sext <16 x i8> %a to <16 x i32>
321   %sb = zext <16 x i8> %b to <16 x i32>
322   %add = add <16 x i32> %sa, %sb
323   %sh = ashr <16 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
324   %t = trunc <16 x i32> %sh to <16 x i8>
325   ret <16 x i8> %t
328 define arm_aapcs_vfpcc <4 x i32> @ext_ops_trunc_i32(<4 x i32> %a, <4 x i32> %b) {
329 ; CHECK-LABEL: ext_ops_trunc_i32:
330 ; CHECK:       @ %bb.0: @ %entry
331 ; CHECK-NEXT:    .save {r4, r5, r6, r7, r8, r9, r10, lr}
332 ; CHECK-NEXT:    push.w {r4, r5, r6, r7, r8, r9, r10, lr}
333 ; CHECK-NEXT:    vmov.f32 s8, s2
334 ; CHECK-NEXT:    vmov.f32 s2, s3
335 ; CHECK-NEXT:    vmov.f32 s10, s7
336 ; CHECK-NEXT:    vmov r10, s8
337 ; CHECK-NEXT:    vmov.f32 s8, s6
338 ; CHECK-NEXT:    vmov r7, s2
339 ; CHECK-NEXT:    vmov.f32 s2, s1
340 ; CHECK-NEXT:    vmov.f32 s6, s5
341 ; CHECK-NEXT:    vmov r2, s8
342 ; CHECK-NEXT:    asr.w r0, r10, #31
343 ; CHECK-NEXT:    asrs r5, r7, #31
344 ; CHECK-NEXT:    adds.w r4, r10, r2
345 ; CHECK-NEXT:    eor.w r6, r10, r2
346 ; CHECK-NEXT:    adc r3, r0, #0
347 ; CHECK-NEXT:    asrl r4, r3, r2
348 ; CHECK-NEXT:    subs r0, r4, r2
349 ; CHECK-NEXT:    sbc lr, r3, #0
350 ; CHECK-NEXT:    vmov r3, s10
351 ; CHECK-NEXT:    umull r0, r8, r0, r2
352 ; CHECK-NEXT:    adds r4, r7, r3
353 ; CHECK-NEXT:    eor.w r1, r7, r3
354 ; CHECK-NEXT:    adc r5, r5, #0
355 ; CHECK-NEXT:    asrl r4, r5, r3
356 ; CHECK-NEXT:    subs r4, r4, r3
357 ; CHECK-NEXT:    sbc r5, r5, #0
358 ; CHECK-NEXT:    orrs.w r6, r6, r10, asr #31
359 ; CHECK-NEXT:    umull r4, r12, r4, r3
360 ; CHECK-NEXT:    csetm r9, eq
361 ; CHECK-NEXT:    orrs.w r1, r1, r7, asr #31
362 ; CHECK-NEXT:    mov.w r6, #0
363 ; CHECK-NEXT:    csetm r1, eq
364 ; CHECK-NEXT:    bfi r6, r9, #0, #8
365 ; CHECK-NEXT:    mla r5, r5, r3, r12
366 ; CHECK-NEXT:    bfi r6, r1, #8, #8
367 ; CHECK-NEXT:    rsbs r1, r7, #0
368 ; CHECK-NEXT:    mla r7, lr, r2, r8
369 ; CHECK-NEXT:    lsll r4, r5, r1
370 ; CHECK-NEXT:    rsb.w r1, r10, #0
371 ; CHECK-NEXT:    lsll r0, r7, r1
372 ; CHECK-NEXT:    vmov lr, s2
373 ; CHECK-NEXT:    vmov r1, s6
374 ; CHECK-NEXT:    lsll r0, r7, r2
375 ; CHECK-NEXT:    lsll r4, r5, r3
376 ; CHECK-NEXT:    vmsr p0, r6
377 ; CHECK-NEXT:    vmov q3[2], q3[0], r0, r4
378 ; CHECK-NEXT:    mov.w r12, #0
379 ; CHECK-NEXT:    vpsel q2, q3, q2
380 ; CHECK-NEXT:    adds.w r2, lr, r1
381 ; CHECK-NEXT:    asr.w r0, lr, #31
382 ; CHECK-NEXT:    adc r3, r0, #0
383 ; CHECK-NEXT:    asrl r2, r3, r1
384 ; CHECK-NEXT:    subs r0, r2, r1
385 ; CHECK-NEXT:    vmov r2, s0
386 ; CHECK-NEXT:    sbc r7, r3, #0
387 ; CHECK-NEXT:    vmov r3, s4
388 ; CHECK-NEXT:    umull r0, r6, r0, r1
389 ; CHECK-NEXT:    asrs r5, r2, #31
390 ; CHECK-NEXT:    adds r4, r2, r3
391 ; CHECK-NEXT:    adc r5, r5, #0
392 ; CHECK-NEXT:    asrl r4, r5, r3
393 ; CHECK-NEXT:    subs r4, r4, r3
394 ; CHECK-NEXT:    sbc r8, r5, #0
395 ; CHECK-NEXT:    mla r5, r7, r1, r6
396 ; CHECK-NEXT:    eor.w r6, lr, r1
397 ; CHECK-NEXT:    orrs.w r6, r6, lr, asr #31
398 ; CHECK-NEXT:    eor.w r7, r2, r3
399 ; CHECK-NEXT:    csetm r6, eq
400 ; CHECK-NEXT:    orrs.w r7, r7, r2, asr #31
401 ; CHECK-NEXT:    csetm r7, eq
402 ; CHECK-NEXT:    rsb.w lr, lr, #0
403 ; CHECK-NEXT:    bfi r12, r7, #0, #8
404 ; CHECK-NEXT:    lsll r0, r5, lr
405 ; CHECK-NEXT:    bfi r12, r6, #8, #8
406 ; CHECK-NEXT:    umull r4, r6, r4, r3
407 ; CHECK-NEXT:    lsll r0, r5, r1
408 ; CHECK-NEXT:    rsbs r1, r2, #0
409 ; CHECK-NEXT:    vmsr p0, r12
410 ; CHECK-NEXT:    mla r7, r8, r3, r6
411 ; CHECK-NEXT:    lsll r4, r7, r1
412 ; CHECK-NEXT:    lsll r4, r7, r3
413 ; CHECK-NEXT:    vmov q0[2], q0[0], r4, r0
414 ; CHECK-NEXT:    vpsel q0, q0, q1
415 ; CHECK-NEXT:    vmov.f32 s1, s2
416 ; CHECK-NEXT:    vmov.f32 s2, s8
417 ; CHECK-NEXT:    vmov.f32 s3, s10
418 ; CHECK-NEXT:    pop.w {r4, r5, r6, r7, r8, r9, r10, pc}
419 entry:
420   %sa = sext <4 x i32> %a to <4 x i64>
421   %sb = zext <4 x i32> %b to <4 x i64>
422   %add = add <4 x i64> %sa, %sb
423   %ashr = ashr <4 x i64> %add, %sb
424   %sub = sub <4 x i64> %ashr, %sb
425   %mul = mul <4 x i64> %sub, %sb
426   %lshr = lshr <4 x i64> %mul, %sa
427   %shl = shl <4 x i64> %lshr, %sb
428   %cmp = icmp eq <4 x i64> %sa, %sb
429   %sel = select <4 x i1> %cmp, <4 x i64> %shl, <4 x i64> %sb
430   %t = trunc <4 x i64> %sel to <4 x i32>
431   ret <4 x i32> %t
434 define arm_aapcs_vfpcc <8 x i16> @ext_ops_trunc_i16(<8 x i16> %a, <8 x i16> %b) {
435 ; CHECK-LABEL: ext_ops_trunc_i16:
436 ; CHECK:       @ %bb.0: @ %entry
437 ; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
438 ; CHECK-NEXT:    vpush {d8, d9, d10, d11}
439 ; CHECK-NEXT:    vmovlt.u16 q2, q1
440 ; CHECK-NEXT:    vmovlt.s16 q3, q0
441 ; CHECK-NEXT:    vadd.i32 q4, q3, q2
442 ; CHECK-NEXT:    vneg.s32 q5, q2
443 ; CHECK-NEXT:    vshl.s32 q4, q4, q5
444 ; CHECK-NEXT:    vneg.s32 q5, q3
445 ; CHECK-NEXT:    vsub.i32 q4, q4, q2
446 ; CHECK-NEXT:    vmul.i32 q4, q4, q2
447 ; CHECK-NEXT:    vmovlb.u16 q1, q1
448 ; CHECK-NEXT:    vshl.u32 q4, q4, q5
449 ; CHECK-NEXT:    vmovlb.s16 q0, q0
450 ; CHECK-NEXT:    vpt.i32 eq, q3, q2
451 ; CHECK-NEXT:    vshlt.u32 q2, q4, q2
452 ; CHECK-NEXT:    vadd.i32 q3, q0, q1
453 ; CHECK-NEXT:    vneg.s32 q4, q1
454 ; CHECK-NEXT:    vshl.s32 q3, q3, q4
455 ; CHECK-NEXT:    vneg.s32 q4, q0
456 ; CHECK-NEXT:    vsub.i32 q3, q3, q1
457 ; CHECK-NEXT:    vmul.i32 q3, q3, q1
458 ; CHECK-NEXT:    vshl.u32 q3, q3, q4
459 ; CHECK-NEXT:    vpt.i32 eq, q0, q1
460 ; CHECK-NEXT:    vshlt.u32 q1, q3, q1
461 ; CHECK-NEXT:    vmovnt.i32 q1, q2
462 ; CHECK-NEXT:    vmov q0, q1
463 ; CHECK-NEXT:    vpop {d8, d9, d10, d11}
464 ; CHECK-NEXT:    bx lr
465 entry:
466   %sa = sext <8 x i16> %a to <8 x i32>
467   %sb = zext <8 x i16> %b to <8 x i32>
468   %add = add <8 x i32> %sa, %sb
469   %ashr = ashr <8 x i32> %add, %sb
470   %sub = sub <8 x i32> %ashr, %sb
471   %mul = mul <8 x i32> %sub, %sb
472   %lshr = lshr <8 x i32> %mul, %sa
473   %shl = shl <8 x i32> %lshr, %sb
474   %cmp = icmp eq <8 x i32> %sa, %sb
475   %sel = select <8 x i1> %cmp, <8 x i32> %shl, <8 x i32> %sb
476   %t = trunc <8 x i32> %sel to <8 x i16>
477   ret <8 x i16> %t
480 define arm_aapcs_vfpcc <16 x i8> @ext_ops_trunc_i8(<16 x i8> %a, <16 x i8> %b) {
481 ; CHECK-LABEL: ext_ops_trunc_i8:
482 ; CHECK:       @ %bb.0: @ %entry
483 ; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
484 ; CHECK-NEXT:    vpush {d8, d9, d10, d11}
485 ; CHECK-NEXT:    vmovlt.u8 q2, q1
486 ; CHECK-NEXT:    vmovlt.s8 q3, q0
487 ; CHECK-NEXT:    vadd.i16 q4, q3, q2
488 ; CHECK-NEXT:    vneg.s16 q5, q2
489 ; CHECK-NEXT:    vshl.s16 q4, q4, q5
490 ; CHECK-NEXT:    vneg.s16 q5, q3
491 ; CHECK-NEXT:    vsub.i16 q4, q4, q2
492 ; CHECK-NEXT:    vmul.i16 q4, q4, q2
493 ; CHECK-NEXT:    vmovlb.u8 q1, q1
494 ; CHECK-NEXT:    vshl.u16 q4, q4, q5
495 ; CHECK-NEXT:    vmovlb.s8 q0, q0
496 ; CHECK-NEXT:    vpt.i16 eq, q3, q2
497 ; CHECK-NEXT:    vshlt.u16 q2, q4, q2
498 ; CHECK-NEXT:    vadd.i16 q3, q0, q1
499 ; CHECK-NEXT:    vneg.s16 q4, q1
500 ; CHECK-NEXT:    vshl.s16 q3, q3, q4
501 ; CHECK-NEXT:    vneg.s16 q4, q0
502 ; CHECK-NEXT:    vsub.i16 q3, q3, q1
503 ; CHECK-NEXT:    vmul.i16 q3, q3, q1
504 ; CHECK-NEXT:    vshl.u16 q3, q3, q4
505 ; CHECK-NEXT:    vpt.i16 eq, q0, q1
506 ; CHECK-NEXT:    vshlt.u16 q1, q3, q1
507 ; CHECK-NEXT:    vmovnt.i16 q1, q2
508 ; CHECK-NEXT:    vmov q0, q1
509 ; CHECK-NEXT:    vpop {d8, d9, d10, d11}
510 ; CHECK-NEXT:    bx lr
511 entry:
512   %sa = sext <16 x i8> %a to <16 x i16>
513   %sb = zext <16 x i8> %b to <16 x i16>
514   %add = add <16 x i16> %sa, %sb
515   %ashr = ashr <16 x i16> %add, %sb
516   %sub = sub <16 x i16> %ashr, %sb
517   %mul = mul <16 x i16> %sub, %sb
518   %lshr = lshr <16 x i16> %mul, %sa
519   %shl = shl <16 x i16> %lshr, %sb
520   %cmp = icmp eq <16 x i16> %sa, %sb
521   %sel = select <16 x i1> %cmp, <16 x i16> %shl, <16 x i16> %sb
522   %t = trunc <16 x i16> %sel to <16 x i8>
523   ret <16 x i8> %t
526 define arm_aapcs_vfpcc <8 x i16> @ext_intrinsics_trunc_i16(<8 x i16> %a, <8 x i16> %b) {
527 ; CHECK-LABEL: ext_intrinsics_trunc_i16:
528 ; CHECK:       @ %bb.0: @ %entry
529 ; CHECK-NEXT:    .vsave {d8, d9}
530 ; CHECK-NEXT:    vpush {d8, d9}
531 ; CHECK-NEXT:    vmovlb.u16 q2, q1
532 ; CHECK-NEXT:    vmovlb.s16 q3, q0
533 ; CHECK-NEXT:    vadd.i32 q4, q3, q2
534 ; CHECK-NEXT:    vmovlt.u16 q1, q1
535 ; CHECK-NEXT:    vqadd.u32 q4, q4, q2
536 ; CHECK-NEXT:    vmovlt.s16 q0, q0
537 ; CHECK-NEXT:    vqsub.s32 q4, q4, q3
538 ; CHECK-NEXT:    vqsub.u32 q4, q4, q2
539 ; CHECK-NEXT:    vabs.s32 q4, q4
540 ; CHECK-NEXT:    vmin.s32 q4, q4, q3
541 ; CHECK-NEXT:    vmax.s32 q4, q4, q2
542 ; CHECK-NEXT:    vmin.u32 q3, q4, q3
543 ; CHECK-NEXT:    vadd.i32 q4, q0, q1
544 ; CHECK-NEXT:    vqadd.u32 q4, q4, q1
545 ; CHECK-NEXT:    vqsub.s32 q4, q4, q0
546 ; CHECK-NEXT:    vqsub.u32 q4, q4, q1
547 ; CHECK-NEXT:    vabs.s32 q4, q4
548 ; CHECK-NEXT:    vmin.s32 q4, q4, q0
549 ; CHECK-NEXT:    vmax.s32 q4, q4, q1
550 ; CHECK-NEXT:    vmin.u32 q0, q4, q0
551 ; CHECK-NEXT:    vmax.u32 q1, q0, q1
552 ; CHECK-NEXT:    vmax.u32 q0, q3, q2
553 ; CHECK-NEXT:    vmovnt.i32 q0, q1
554 ; CHECK-NEXT:    vpop {d8, d9}
555 ; CHECK-NEXT:    bx lr
556 entry:
557   %sa = sext <8 x i16> %a to <8 x i32>
558   %sb = zext <8 x i16> %b to <8 x i32>
559   %sadd = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %sa, <8 x i32> %sb)
560   %uadd = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %sadd, <8 x i32> %sb)
561   %ssub = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %uadd, <8 x i32> %sa)
562   %usub = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %ssub, <8 x i32> %sb)
563   %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %usub, i1 true)
564   %smin = call <8 x i32> @llvm.smin.v8i32(<8 x i32> %abs, <8 x i32> %sa)
565   %smax = call <8 x i32> @llvm.smax.v8i32(<8 x i32> %smin, <8 x i32> %sb)
566   %umin = call <8 x i32> @llvm.umin.v8i32(<8 x i32> %smax, <8 x i32> %sa)
567   %umax = call <8 x i32> @llvm.umax.v8i32(<8 x i32> %umin, <8 x i32> %sb)
568   %t = trunc <8 x i32> %umax to <8 x i16>
569   ret <8 x i16> %t
572 define arm_aapcs_vfpcc <8 x half> @ext_fpintrinsics_trunc_half(<8 x half> %a, <8 x half> %b) {
573 ; CHECK-LABEL: ext_fpintrinsics_trunc_half:
574 ; CHECK:       @ %bb.0: @ %entry
575 ; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
576 ; CHECK-NEXT:    vpush {d8, d9, d10, d11}
577 ; CHECK-NEXT:    vcvtb.f32.f16 q2, q0
578 ; CHECK-NEXT:    vcvtb.f32.f16 q4, q1
579 ; CHECK-NEXT:    vrintm.f32 q3, q2
580 ; CHECK-NEXT:    vrintx.f32 q5, q4
581 ; CHECK-NEXT:    vabs.f32 q3, q3
582 ; CHECK-NEXT:    vrinta.f32 q4, q4
583 ; CHECK-NEXT:    vminnm.f32 q3, q3, q2
584 ; CHECK-NEXT:    vrintp.f32 q2, q2
585 ; CHECK-NEXT:    vmaxnm.f32 q3, q3, q5
586 ; CHECK-NEXT:    vcvtt.f32.f16 q0, q0
587 ; CHECK-NEXT:    vfma.f32 q2, q3, q4
588 ; CHECK-NEXT:    vrintm.f32 q3, q0
589 ; CHECK-NEXT:    vabs.f32 q3, q3
590 ; CHECK-NEXT:    vcvtt.f32.f16 q1, q1
591 ; CHECK-NEXT:    vminnm.f32 q3, q3, q0
592 ; CHECK-NEXT:    vrintx.f32 q4, q1
593 ; CHECK-NEXT:    vmaxnm.f32 q3, q3, q4
594 ; CHECK-NEXT:    vrinta.f32 q1, q1
595 ; CHECK-NEXT:    vrintp.f32 q0, q0
596 ; CHECK-NEXT:    vrintz.f32 q2, q2
597 ; CHECK-NEXT:    vfma.f32 q0, q3, q1
598 ; CHECK-NEXT:    vrintz.f32 q1, q0
599 ; CHECK-NEXT:    vcvtb.f16.f32 q0, q2
600 ; CHECK-NEXT:    vcvtt.f16.f32 q0, q1
601 ; CHECK-NEXT:    vpop {d8, d9, d10, d11}
602 ; CHECK-NEXT:    bx lr
603 entry:
604   %sa = fpext <8 x half> %a to <8 x float>
605   %sb = fpext <8 x half> %b to <8 x float>
606   %floor = call <8 x float> @llvm.floor.v8f32(<8 x float> %sa)
607   %rint = call <8 x float> @llvm.rint.v8f32(<8 x float> %sb)
608   %ceil = call <8 x float> @llvm.ceil.v8f32(<8 x float> %sa)
609   %round = call <8 x float> @llvm.round.v8f32(<8 x float> %sb)
610   %abs = call <8 x float> @llvm.fabs.v8f32(<8 x float> %floor)
611   %min = call <8 x float> @llvm.minnum.v8f32(<8 x float> %abs, <8 x float> %sa)
612   %max = call <8 x float> @llvm.maxnum.v8f32(<8 x float> %min, <8 x float> %rint)
613   %fma = call <8 x float> @llvm.fma.v8f32(<8 x float> %max, <8 x float> %round, <8 x float> %ceil)
614   %trunc = call <8 x float> @llvm.trunc.v8f32(<8 x float> %fma)
615   %t = fptrunc <8 x float> %trunc to <8 x half>
616   ret <8 x half> %t
619 declare <8 x i32> @llvm.abs.v8i32(<8 x i32>, i1)
620 declare <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32>, <8 x i32>)
621 declare <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32>, <8 x i32>)
622 declare <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32>, <8 x i32>)
623 declare <8 x i32> @llvm.usub.sat.v8i32(<8 x i32>, <8 x i32>)
624 declare <8 x i32> @llvm.smin.v8i32(<8 x i32>, <8 x i32>)
625 declare <8 x i32> @llvm.smax.v8i32(<8 x i32>, <8 x i32>)
626 declare <8 x i32> @llvm.umin.v8i32(<8 x i32>, <8 x i32>)
627 declare <8 x i32> @llvm.umax.v8i32(<8 x i32>, <8 x i32>)
628 declare <8 x float> @llvm.fabs.v8f32(<8 x float>)
629 declare <8 x float> @llvm.minnum.v8f32(<8 x float>, <8 x float>)
630 declare <8 x float> @llvm.maxnum.v8f32(<8 x float>, <8 x float>)
631 declare <8 x float> @llvm.fma.v8f32(<8 x float>, <8 x float>, <8 x float>)
632 declare <8 x float> @llvm.ceil.v8f32(<8 x float>)
633 declare <8 x float> @llvm.floor.v8f32(<8 x float>)
634 declare <8 x float> @llvm.rint.v8f32(<8 x float>)
635 declare <8 x float> @llvm.round.v8f32(<8 x float>)
636 declare <8 x float> @llvm.trunc.v8f32(<8 x float>)