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
7
8@array = weak global [4 x i32] zeroinitializer
9
10define i32 @test_lshr_and1(i32 %x) {
11entry:
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
23}
24define i32 @test_lshr_and2(i32 %x) {
25entry:
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
37}
38
39; CHECK-LABEL: test_lshr_load1
40; CHECK-BE:         ldrb r0, [r0]
41; CHECK-COMMON:     ldrb r0, [r0, #1]
42; CHECK-COMMON-NEXT: bx
43define arm_aapcscc i32 @test_lshr_load1(i16* %a) {
44entry:
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
49}
50
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
57define arm_aapcscc i32 @test_lshr_load1_sext(i16* %a) {
58entry:
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
63}
64
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
70define arm_aapcscc i32 @test_lshr_load1_fail(i16* %a) {
71entry:
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
76}
77
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
83define arm_aapcscc i32 @test_lshr_load32(i32* %a) {
84entry:
85  %0 = load i32, i32* %a, align 4
86  %1 = lshr i32 %0, 8
87  ret i32 %1
88}
89
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
94define arm_aapcscc i32 @test_lshr_load32_2(i32* %a) {
95entry:
96  %0 = load i32, i32* %a, align 4
97  %1 = lshr i32 %0, 16
98  ret i32 %1
99}
100
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
105define arm_aapcscc i32 @test_lshr_load32_1(i32* %a) {
106entry:
107  %0 = load i32, i32* %a, align 4
108  %1 = lshr i32 %0, 24
109  ret i32 %1
110}
111
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
119define arm_aapcscc i32 @test_lshr_load32_fail(i32* %a) {
120entry:
121  %0 = load i32, i32* %a, align 4
122  %1 = lshr i32 %0, 15
123  ret i32 %1
124}
125
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
140define arm_aapcscc i32 @test_lshr_load64_4_unaligned(i64* %a) {
141entry:
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
146}
147
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
158define arm_aapcscc i32 @test_lshr_load64_1_lsb(i64* %a) {
159entry:
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
164}
165
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
171define arm_aapcscc i32 @test_lshr_load64_1_msb(i64* %a) {
172entry:
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
177}
178
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
184define arm_aapcscc i32 @test_lshr_load64_4(i64* %a) {
185entry:
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
190}
191
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
197define arm_aapcscc i32 @test_lshr_load64_2(i64* %a) {
198entry:
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
203}
204
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
212define arm_aapcscc i32 @test_lshr_load4_fail(i64* %a) {
213entry:
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
218}
219
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]
225define arm_aapcscc void @test_shift7_mask8(i32* nocapture %p) {
226entry:
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
232}
233
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]
238define arm_aapcscc void @test_shift8_mask8(i32* nocapture %p) {
239entry:
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
245}
246
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]
252define arm_aapcscc void @test_shift8_mask7(i32* nocapture %p) {
253entry:
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
259}
260
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]
266define arm_aapcscc void @test_shift9_mask8(i32* nocapture %p) {
267entry:
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
273}
274
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]
282define arm_aapcscc void @test_shift8_mask16(i32* nocapture %p) {
283entry:
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
289}
290
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]
295define arm_aapcscc void @test_shift15_mask16(i32* nocapture %p) {
296entry:
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
302}
303
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]
309define arm_aapcscc void @test_shift16_mask15(i32* nocapture %p) {
310entry:
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
316}
317
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]
324define arm_aapcscc void @test_shift8_mask24(i32* nocapture %p) {
325entry:
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
331}
332
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]
337define arm_aapcscc void @test_shift24_mask16(i32* nocapture %p) {
338entry:
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
344}
345
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]
350define arm_aapcscc void @test_sext_shift8_mask8(i16* %p, i32* %q) {
351entry:
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
358}
359
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]
366define arm_aapcscc void @test_sext_shift8_mask16(i16* %p, i32* %q) {
367entry:
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
374}
375
376; CHECK-LABEL: trunc_i64_mask_srl
377; CHECK-ARM: ldrh r2, [r1, #4]
378; CHECK-BE: ldrh r2, [r1, #2]
379define i1 @trunc_i64_mask_srl(i32 zeroext %AttrArgNo, i64* %ptr) {
380entry:
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
387}
388