[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / CodeGen / ARM / shift-combine.ll
blobdbd9a4183039aeb39ccb9f5a9c29cd8f5d105484
1 ; RUN: llc -mtriple=armv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-ARM --check-prefix=CHECK-COMMON
2 ; RUN: llc -mtriple=armv7eb-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-BE
3 ; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON
4 ; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s --check-prefix=CHECK-THUMB --check-prefix=CHECK-COMMON
5 ; RUN: llc -mtriple=thumbv7m -mattr=+strict-align %s -o - | FileCheck %s --check-prefix=CHECK-ALIGN --check-prefix=CHECK-COMMON
6 ; RUN: llc -mtriple=thumbv6m %s -o - | FileCheck %s --check-prefix=CHECK-V6M
8 @array = weak global [4 x i32] zeroinitializer
10 define i32 @test_lshr_and1(i32 %x) {
11 entry:
12 ;CHECK-LABEL: test_lshr_and1:
13 ;CHECK-COMMON:      movw r1, :lower16:array
14 ;CHECK-COMMON-NEXT: and  r0, r0, #12
15 ;CHECK-COMMON-NEXT: movt r1, :upper16:array
16 ;CHECK-COMMON-NEXT: ldr  r0, [r1, r0]
17 ;CHECK-COMMON-NEXT: bx   lr
18   %tmp2 = lshr i32 %x, 2
19   %tmp3 = and i32 %tmp2, 3
20   %tmp4 = getelementptr [4 x i32], [4 x i32]* @array, i32 0, i32 %tmp3
21   %tmp5 = load i32, i32* %tmp4, align 4
22   ret i32 %tmp5
24 define i32 @test_lshr_and2(i32 %x) {
25 entry:
26 ;CHECK-LABEL: test_lshr_and2:
27 ;CHECK-COMMON:  ubfx r0, r0, #1, #15
28 ;CHECK-ARM:     add  r0, r0, r0
29 ;CHECK-THUMB:   add  r0, r0
30 ;CHECK-COMMON:  bx   lr
31   %a = and i32 %x, 65534
32   %b = lshr i32 %a, 1
33   %c = and i32 %x, 65535
34   %d = lshr i32 %c, 1
35   %e = add i32 %b, %d
36   ret i32 %e
39 ; CHECK-LABEL: test_lshr_load1
40 ; CHECK-BE:         ldrb r0, [r0]
41 ; CHECK-COMMON:     ldrb r0, [r0, #1]
42 ; CHECK-COMMON-NEXT: bx
43 define arm_aapcscc i32 @test_lshr_load1(i16* %a) {
44 entry:
45   %0 = load i16, i16* %a, align 2
46   %conv1 = zext i16 %0 to i32
47   %1 = lshr i32 %conv1, 8
48   ret i32 %1
51 ; CHECK-LABEL: test_lshr_load1_sext
52 ; CHECK-ARM:        ldrsh r0, [r0]
53 ; CHECK-ARM-NEXT:   lsr r0, r0, #8
54 ; CHECK-THUMB:      ldrsh.w r0, [r0]
55 ; CHECK-THUMB-NEXT: lsrs r0, r0, #8
56 ; CHECK-COMMON:     bx
57 define arm_aapcscc i32 @test_lshr_load1_sext(i16* %a) {
58 entry:
59   %0 = load i16, i16* %a, align 2
60   %conv1 = sext i16 %0 to i32
61   %1 = lshr i32 %conv1, 8
62   ret i32 %1
65 ; CHECK-LABEL: test_lshr_load1_fail
66 ; CHECK-COMMON: ldrh r0, [r0]
67 ; CHECK-ARM:    lsr r0, r0, #9
68 ; CHECK-THUMB:  lsrs r0, r0, #9
69 ; CHECK-COMMON: bx
70 define arm_aapcscc i32 @test_lshr_load1_fail(i16* %a) {
71 entry:
72   %0 = load i16, i16* %a, align 2
73   %conv1 = zext i16 %0 to i32
74   %1 = lshr i32 %conv1, 9
75   ret i32 %1
78 ; CHECK-LABEL: test_lshr_load32
79 ; CHECK-COMMON: ldr r0, [r0]
80 ; CHECK-ARM:    lsr r0, r0, #8
81 ; CHECK-THUMB:  lsrs r0, r0, #8
82 ; CHECK-COMMON: bx
83 define arm_aapcscc i32 @test_lshr_load32(i32* %a) {
84 entry:
85   %0 = load i32, i32* %a, align 4
86   %1 = lshr i32 %0, 8
87   ret i32 %1
90 ; CHECK-LABEL: test_lshr_load32_2
91 ; CHECK-BE:         ldrh r0, [r0]
92 ; CHECK-COMMON:     ldrh r0, [r0, #2]
93 ; CHECK-COMMON-NEXT: bx
94 define arm_aapcscc i32 @test_lshr_load32_2(i32* %a) {
95 entry:
96   %0 = load i32, i32* %a, align 4
97   %1 = lshr i32 %0, 16
98   ret i32 %1
101 ; CHECK-LABEL: test_lshr_load32_1
102 ; CHECK-BE:         ldrb r0, [r0]
103 ; CHECK-COMMON:     ldrb r0, [r0, #3]
104 ; CHECK-COMMON-NEXT: bx
105 define arm_aapcscc i32 @test_lshr_load32_1(i32* %a) {
106 entry:
107   %0 = load i32, i32* %a, align 4
108   %1 = lshr i32 %0, 24
109   ret i32 %1
112 ; CHECK-LABEL: test_lshr_load32_fail
113 ; CHECK-BE:     ldr r0, [r0]
114 ; CHECK-BE-NEXT: lsr r0, r0, #15
115 ; CHECK-COMMON: ldr r0, [r0]
116 ; CHECK-ARM:    lsr r0, r0, #15
117 ; CHECK-THUMB:  lsrs r0, r0, #15
118 ; CHECK-COMMON: bx
119 define arm_aapcscc i32 @test_lshr_load32_fail(i32* %a) {
120 entry:
121   %0 = load i32, i32* %a, align 4
122   %1 = lshr i32 %0, 15
123   ret i32 %1
126 ; CHECK-LABEL: test_lshr_load64_4_unaligned
127 ; CHECK-BE:         ldr [[HIGH:r[0-9]+]], [r0]
128 ; CHECK-BE-NEXT:    ldrh [[LOW:r[0-9]+]], [r0, #4]
129 ; CHECK-BE-NEXT:    orr r0, [[LOW]], [[HIGH]], lsl #16
130 ; CHECK-V6M:        ldrh [[LOW:r[0-9]+]], [r0, #2]
131 ; CHECK-V6M:        ldr [[HIGH:r[0-9]+]], [r0, #4]
132 ; CHECK-V6M-NEXT:   lsls [[HIGH]], [[HIGH]], #16
133 ; CHECK-V6M-NEXT:   adds r0, r1, r0
134 ; CHECK-ALIGN:      ldr [[HIGH:r[0-9]+]], [r0, #4]
135 ; CHECK-ALIGN-NEXT: ldrh [[LOW:r[0-9]+]], [r0, #2]
136 ; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #16
137 ; CHECK-ARM:        ldr r0, [r0, #2]
138 ; CHECK-THUMB:      ldr.w r0, [r0, #2]
139 ; CHECK-COMMON:     bx
140 define arm_aapcscc i32 @test_lshr_load64_4_unaligned(i64* %a) {
141 entry:
142   %0 = load i64, i64* %a, align 8
143   %1 = lshr i64 %0, 16
144   %conv = trunc i64 %1 to i32
145   ret i32 %conv
148 ; CHECK-LABEL: test_lshr_load64_1_lsb
149 ; CHECK-BE:         ldr r1, [r0]
150 ; CHECK-BE-NEXT:    ldrb r0, [r0, #4]
151 ; CHECK-BE-NEXT:    orr r0, r0, r1, lsl #8
152 ; CHECK-ARM:        ldr r0, [r0, #3]
153 ; CHECK-THUMB:      ldr.w r0, [r0, #3]
154 ; CHECK-ALIGN:      ldr [[HIGH:r[0-9]+]], [r0, #4]
155 ; CHECK-ALIGN-NEXT: ldrb [[LOW:r[0-9]+]], [r0, #3]
156 ; CHECK-ALIGN-NEXT: orr.w r0, [[LOW]], [[HIGH]], lsl #8
157 ; CHECK-COMMON: bx
158 define arm_aapcscc i32 @test_lshr_load64_1_lsb(i64* %a) {
159 entry:
160   %0 = load i64, i64* %a, align 8
161   %1 = lshr i64 %0, 24
162   %conv = trunc i64 %1 to i32
163   ret i32 %conv
166 ; CHECK-LABEL: test_lshr_load64_1_msb
167 ; CHECK-BE:         ldrb r0, [r0]
168 ; CHECK-BE-NEXT:    bx
169 ; CHECK-COMMON:     ldrb r0, [r0, #7]
170 ; CHECK-COMMON-NEXT: bx
171 define arm_aapcscc i32 @test_lshr_load64_1_msb(i64* %a) {
172 entry:
173   %0 = load i64, i64* %a, align 8
174   %1 = lshr i64 %0, 56
175   %conv = trunc i64 %1 to i32
176   ret i32 %conv
179 ; CHECK-LABEL: test_lshr_load64_4
180 ; CHECK-BE:         ldr r0, [r0]
181 ; CHECK-BE-NEXT:    bx
182 ; CHECK-COMMON:     ldr r0, [r0, #4]
183 ; CHECK-COMMON-NEXT: bx
184 define arm_aapcscc i32 @test_lshr_load64_4(i64* %a) {
185 entry:
186   %0 = load i64, i64* %a, align 8
187   %1 = lshr i64 %0, 32
188   %conv = trunc i64 %1 to i32
189   ret i32 %conv
192 ; CHECK-LABEL: test_lshr_load64_2
193 ; CHECK-BE:         ldrh r0, [r0]
194 ; CHECK-BE-NEXT:    bx
195 ; CHECK-COMMON:     ldrh r0, [r0, #6]
196 ; CHECK-COMMON-NEXT:bx
197 define arm_aapcscc i32 @test_lshr_load64_2(i64* %a) {
198 entry:
199   %0 = load i64, i64* %a, align 8
200   %1 = lshr i64 %0, 48
201   %conv = trunc i64 %1 to i32
202   ret i32 %conv
205 ; CHECK-LABEL: test_lshr_load4_fail
206 ; CHECK-COMMON:     ldrd r0, r1, [r0]
207 ; CHECK-ARM:        lsr r0, r0, #8
208 ; CHECK-ARM-NEXT:   orr r0, r0, r1, lsl #24
209 ; CHECK-THUMB:      lsrs r0, r0, #8
210 ; CHECK-THUMB-NEXT: orr.w r0, r0, r1, lsl #24
211 ; CHECK-COMMON:     bx
212 define arm_aapcscc i32 @test_lshr_load4_fail(i64* %a) {
213 entry:
214   %0 = load i64, i64* %a, align 8
215   %1 = lshr i64 %0, 8
216   %conv = trunc i64 %1 to i32
217   ret i32 %conv
220 ; CHECK-LABEL: test_shift7_mask8
221 ; CHECK-BE:         ldr r1, [r0]
222 ; CHECK-COMMON:     ldr r1, [r0]
223 ; CHECK-COMMON:     ubfx r1, r1, #7, #8
224 ; CHECK-COMMON:     str r1, [r0]
225 define arm_aapcscc void @test_shift7_mask8(i32* nocapture %p) {
226 entry:
227   %0 = load i32, i32* %p, align 4
228   %shl = lshr i32 %0, 7
229   %and = and i32 %shl, 255
230   store i32 %and, i32* %p, align 4
231   ret void
234 ; CHECK-LABEL: test_shift8_mask8
235 ; CHECK-BE:         ldrb r1, [r0, #2]
236 ; CHECK-COMMON:     ldrb r1, [r0, #1]
237 ; CHECK-COMMON:     str r1, [r0]
238 define arm_aapcscc void @test_shift8_mask8(i32* nocapture %p) {
239 entry:
240   %0 = load i32, i32* %p, align 4
241   %shl = lshr i32 %0, 8
242   %and = and i32 %shl, 255
243   store i32 %and, i32* %p, align 4
244   ret void
247 ; CHECK-LABEL: test_shift8_mask7
248 ; CHECK-BE:         ldr r1, [r0]
249 ; CHECK-COMMON:     ldr r1, [r0]
250 ; CHECK-COMMON:     ubfx r1, r1, #8, #7
251 ; CHECK-COMMON:     str r1, [r0]
252 define arm_aapcscc void @test_shift8_mask7(i32* nocapture %p) {
253 entry:
254   %0 = load i32, i32* %p, align 4
255   %shl = lshr i32 %0, 8
256   %and = and i32 %shl, 127
257   store i32 %and, i32* %p, align 4
258   ret void
261 ; CHECK-LABEL: test_shift9_mask8
262 ; CHECK-BE:         ldr r1, [r0]
263 ; CHECK-COMMON:     ldr r1, [r0]
264 ; CHECK-COMMON:     ubfx r1, r1, #9, #8
265 ; CHECK-COMMON:     str r1, [r0]
266 define arm_aapcscc void @test_shift9_mask8(i32* nocapture %p) {
267 entry:
268   %0 = load i32, i32* %p, align 4
269   %shl = lshr i32 %0, 9
270   %and = and i32 %shl, 255
271   store i32 %and, i32* %p, align 4
272   ret void
275 ; CHECK-LABEL: test_shift8_mask16
276 ; CHECK-ALIGN:      ldr r1, [r0]
277 ; CHECK-ALIGN:      ubfx r1, r1, #8, #16
278 ; CHECK-BE:         ldrh r1, [r0, #1]
279 ; CHECK-ARM:        ldrh r1, [r0, #1]
280 ; CHECK-THUMB:      ldrh.w r1, [r0, #1]
281 ; CHECK-COMMON:     str r1, [r0]
282 define arm_aapcscc void @test_shift8_mask16(i32* nocapture %p) {
283 entry:
284   %0 = load i32, i32* %p, align 4
285   %shl = lshr i32 %0, 8
286   %and = and i32 %shl, 65535
287   store i32 %and, i32* %p, align 4
288   ret void
291 ; CHECK-LABEL: test_shift15_mask16
292 ; CHECK-COMMON:     ldr r1, [r0]
293 ; CHECK-COMMON:     ubfx r1, r1, #15, #16
294 ; CHECK-COMMON:     str r1, [r0]
295 define arm_aapcscc void @test_shift15_mask16(i32* nocapture %p) {
296 entry:
297   %0 = load i32, i32* %p, align 4
298   %shl = lshr i32 %0, 15
299   %and = and i32 %shl, 65535
300   store i32 %and, i32* %p, align 4
301   ret void
304 ; CHECK-LABEL: test_shift16_mask15
305 ; CHECK-BE:         ldrh r1, [r0]
306 ; CHECK-COMMON:     ldrh r1, [r0, #2]
307 ; CHECK-COMMON:     bfc r1, #15, #17
308 ; CHECK-COMMON:     str r1, [r0]
309 define arm_aapcscc void @test_shift16_mask15(i32* nocapture %p) {
310 entry:
311   %0 = load i32, i32* %p, align 4
312   %shl = lshr i32 %0, 16
313   %and = and i32 %shl, 32767
314   store i32 %and, i32* %p, align 4
315   ret void
318 ; CHECK-LABEL: test_shift8_mask24
319 ; CHECK-BE:         ldr r1, [r0]
320 ; CHECK-COMMON:     ldr r1, [r0]
321 ; CHECK-ARM:        lsr r1, r1, #8
322 ; CHECK-THUMB:      lsrs r1, r1, #8
323 ; CHECK-COMMON:     str r1, [r0]
324 define arm_aapcscc void @test_shift8_mask24(i32* nocapture %p) {
325 entry:
326   %0 = load i32, i32* %p, align 4
327   %shl = lshr i32 %0, 8
328   %and = and i32 %shl, 16777215
329   store i32 %and, i32* %p, align 4
330   ret void
333 ; CHECK-LABEL: test_shift24_mask16
334 ; CHECK-BE:         ldrb r1, [r0]
335 ; CHECK-COMMON:     ldrb r1, [r0, #3]
336 ; CHECK-COMMON:     str r1, [r0]
337 define arm_aapcscc void @test_shift24_mask16(i32* nocapture %p) {
338 entry:
339   %0 = load i32, i32* %p, align 4
340   %shl = lshr i32 %0, 24
341   %and = and i32 %shl, 65535
342   store i32 %and, i32* %p, align 4
343   ret void
346 ; CHECK-LABEL: test_sext_shift8_mask8
347 ; CHECK-BE:         ldrb r0, [r0]
348 ; CHECK-COMMON:     ldrb r0, [r0, #1]
349 ; CHECK-COMMON:     str r0, [r1]
350 define arm_aapcscc void @test_sext_shift8_mask8(i16* %p, i32* %q) {
351 entry:
352   %0 = load i16, i16* %p, align 4
353   %1 = sext i16 %0 to i32
354   %shl = lshr i32 %1, 8
355   %and = and i32 %shl, 255
356   store i32 %and, i32* %q, align 4
357   ret void
360 ; CHECK-LABEL: test_sext_shift8_mask16
361 ; CHECK-ARM:        ldrsh r0, [r0]
362 ; CHECK-BE:         ldrsh r0, [r0]
363 ; CHECK-THUMB:      ldrsh.w r0, [r0]
364 ; CHECK-COMMON:     ubfx r0, r0, #8, #16
365 ; CHECK-COMMON:     str r0, [r1]
366 define arm_aapcscc void @test_sext_shift8_mask16(i16* %p, i32* %q) {
367 entry:
368   %0 = load i16, i16* %p, align 4
369   %1 = sext i16 %0 to i32
370   %shl = lshr i32 %1, 8
371   %and = and i32 %shl, 65535
372   store i32 %and, i32* %q, align 4
373   ret void
376 ; CHECK-LABEL: trunc_i64_mask_srl
377 ; CHECK-ARM: ldrh r2, [r1, #4]
378 ; CHECK-BE: ldrh r2, [r1, #2]
379 define i1 @trunc_i64_mask_srl(i32 zeroext %AttrArgNo, i64* %ptr) {
380 entry:
381   %bf.load.i = load i64, i64* %ptr, align 8
382   %bf.lshr.i = lshr i64 %bf.load.i, 32
383   %0 = trunc i64 %bf.lshr.i to i32
384   %bf.cast.i = and i32 %0, 65535
385   %cmp.i = icmp ugt i32 %bf.cast.i, %AttrArgNo
386   ret i1 %cmp.i