[InstCombine] Signed saturation patterns
[llvm-core.git] / test / CodeGen / ARM / load-combine.ll
blob4206aad1d9e24cda81af7ee0f9693700f14369dc
1 ; RUN: llc < %s -mtriple=arm-unknown | FileCheck %s
2 ; RUN: llc < %s -mtriple=armv6-unknown | FileCheck %s --check-prefix=CHECK-ARMv6
4 ; i8* p; // p is 1 byte aligned
5 ; (i32) p[0] | ((i32) p[1] << 8) | ((i32) p[2] << 16) | ((i32) p[3] << 24)
6 define i32 @load_i32_by_i8_unaligned(i32* %arg) {
7 ; CHECK-LABEL: load_i32_by_i8_unaligned:
8 ; CHECK: ldrb{{.*}}r0
9 ; CHECK: ldrb{{.*}}r0
10 ; CHECK: ldrb{{.*}}r0
11 ; CHECK: ldrb{{.*}}r0
12 ; CHECK: orr
13 ; CHECK: mov pc, lr
15 ; CHECK-ARMv6-LABEL: load_i32_by_i8_unaligned:
16 ; CHECK-ARMv6: ldrb{{.*}}r0
17 ; CHECK-ARMv6: ldrb{{.*}}r0
18 ; CHECK-ARMv6: ldrb{{.*}}r0
19 ; CHECK-ARMv6: ldrb{{.*}}r0
20 ; CHECK-ARMv6: orr
21 ; CHECK-ARMv6: bx lr
22   %tmp = bitcast i32* %arg to i8*
23   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0
24   %tmp2 = load i8, i8* %tmp1, align 1
25   %tmp3 = zext i8 %tmp2 to i32
26   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
27   %tmp5 = load i8, i8* %tmp4, align 1
28   %tmp6 = zext i8 %tmp5 to i32
29   %tmp7 = shl nuw nsw i32 %tmp6, 8
30   %tmp8 = or i32 %tmp7, %tmp3
31   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2
32   %tmp10 = load i8, i8* %tmp9, align 1
33   %tmp11 = zext i8 %tmp10 to i32
34   %tmp12 = shl nuw nsw i32 %tmp11, 16
35   %tmp13 = or i32 %tmp8, %tmp12
36   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3
37   %tmp15 = load i8, i8* %tmp14, align 1
38   %tmp16 = zext i8 %tmp15 to i32
39   %tmp17 = shl nuw nsw i32 %tmp16, 24
40   %tmp18 = or i32 %tmp13, %tmp17
41   ret i32 %tmp18
44 ; i8* p; // p is 4 byte aligned
45 ; (i32) p[0] | ((i32) p[1] << 8) | ((i32) p[2] << 16) | ((i32) p[3] << 24)
46 define i32 @load_i32_by_i8_aligned(i32* %arg) {
47 ; CHECK-LABEL: load_i32_by_i8_aligned:
48 ; CHECK: ldr  r0, [r0]
49 ; CHECK-NEXT: mov pc, lr
51 ; CHECK-ARMv6-LABEL: load_i32_by_i8_aligned:
52 ; CHECK-ARMv6: ldr  r0, [r0]
53 ; CHECK-ARMv6-NEXT: bx lr
54   %tmp = bitcast i32* %arg to i8*
55   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0
56   %tmp2 = load i8, i8* %tmp1, align 4
57   %tmp3 = zext i8 %tmp2 to i32
58   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
59   %tmp5 = load i8, i8* %tmp4, align 1
60   %tmp6 = zext i8 %tmp5 to i32
61   %tmp7 = shl nuw nsw i32 %tmp6, 8
62   %tmp8 = or i32 %tmp7, %tmp3
63   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2
64   %tmp10 = load i8, i8* %tmp9, align 1
65   %tmp11 = zext i8 %tmp10 to i32
66   %tmp12 = shl nuw nsw i32 %tmp11, 16
67   %tmp13 = or i32 %tmp8, %tmp12
68   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3
69   %tmp15 = load i8, i8* %tmp14, align 1
70   %tmp16 = zext i8 %tmp15 to i32
71   %tmp17 = shl nuw nsw i32 %tmp16, 24
72   %tmp18 = or i32 %tmp13, %tmp17
73   ret i32 %tmp18
76 ; i8* p; // p is 4 byte aligned
77 ; ((i32) p[0] << 24) | ((i32) p[1] << 16) | ((i32) p[2] << 8) | (i32) p[3]
78 define i32 @load_i32_by_i8_bswap(i32* %arg) {
79 ; BSWAP is not supported by 32 bit target
80 ; CHECK-LABEL: load_i32_by_i8_bswap:
81 ; CHECK: ldr r0, [r0]
82 ; CHECK: and
83 ; CHECK-NEXT: and
84 ; CHECK-NEXT: orr
85 ; CHECK-NEXT: orr
86 ; CHECK-NEXT: orr
87 ; CHECK: mov pc, lr
89 ; CHECK-ARMv6-LABEL: load_i32_by_i8_bswap:
90 ; CHECK-ARMv6: ldr  r0, [r0]
91 ; CHECK-ARMv6-NEXT: rev  r0, r0
92 ; CHECK-ARMv6-NEXT: bx lr
93   %tmp = bitcast i32* %arg to i8*
94   %tmp1 = load i8, i8* %tmp, align 4
95   %tmp2 = zext i8 %tmp1 to i32
96   %tmp3 = shl nuw nsw i32 %tmp2, 24
97   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
98   %tmp5 = load i8, i8* %tmp4, align 1
99   %tmp6 = zext i8 %tmp5 to i32
100   %tmp7 = shl nuw nsw i32 %tmp6, 16
101   %tmp8 = or i32 %tmp7, %tmp3
102   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2
103   %tmp10 = load i8, i8* %tmp9, align 1
104   %tmp11 = zext i8 %tmp10 to i32
105   %tmp12 = shl nuw nsw i32 %tmp11, 8
106   %tmp13 = or i32 %tmp8, %tmp12
107   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 3
108   %tmp15 = load i8, i8* %tmp14, align 1
109   %tmp16 = zext i8 %tmp15 to i32
110   %tmp17 = or i32 %tmp13, %tmp16
111   ret i32 %tmp17
114 ; i8* p; // p is 8 byte aligned
115 ; (i64) p[0] | ((i64) p[1] << 8) | ((i64) p[2] << 16) | ((i64) p[3] << 24) | ((i64) p[4] << 32) | ((i64) p[5] << 40) | ((i64) p[6] << 48) | ((i64) p[7] << 56)
116 define i64 @load_i64_by_i8(i64* %arg) {
117 ; CHECK-LABEL: load_i64_by_i8:
118 ; CHECK: ldr r2, [r0]
119 ; CHECK-NEXT: ldr r1, [r0, #4]
120 ; CHECK-NEXT: mov r0, r2
121 ; CHECK-NEXT: mov pc, lr
123 ; CHECK-ARMv6-LABEL: load_i64_by_i8:
124 ; CHECK-ARMv6: ldrd  r0, r1, [r0]
125 ; CHECK-ARMv6: bx  lr
126   %tmp = bitcast i64* %arg to i8*
127   %tmp1 = load i8, i8* %tmp, align 8
128   %tmp2 = zext i8 %tmp1 to i64
129   %tmp3 = getelementptr inbounds i8, i8* %tmp, i64 1
130   %tmp4 = load i8, i8* %tmp3, align 1
131   %tmp5 = zext i8 %tmp4 to i64
132   %tmp6 = shl nuw nsw i64 %tmp5, 8
133   %tmp7 = or i64 %tmp6, %tmp2
134   %tmp8 = getelementptr inbounds i8, i8* %tmp, i64 2
135   %tmp9 = load i8, i8* %tmp8, align 1
136   %tmp10 = zext i8 %tmp9 to i64
137   %tmp11 = shl nuw nsw i64 %tmp10, 16
138   %tmp12 = or i64 %tmp7, %tmp11
139   %tmp13 = getelementptr inbounds i8, i8* %tmp, i64 3
140   %tmp14 = load i8, i8* %tmp13, align 1
141   %tmp15 = zext i8 %tmp14 to i64
142   %tmp16 = shl nuw nsw i64 %tmp15, 24
143   %tmp17 = or i64 %tmp12, %tmp16
144   %tmp18 = getelementptr inbounds i8, i8* %tmp, i64 4
145   %tmp19 = load i8, i8* %tmp18, align 1
146   %tmp20 = zext i8 %tmp19 to i64
147   %tmp21 = shl nuw nsw i64 %tmp20, 32
148   %tmp22 = or i64 %tmp17, %tmp21
149   %tmp23 = getelementptr inbounds i8, i8* %tmp, i64 5
150   %tmp24 = load i8, i8* %tmp23, align 1
151   %tmp25 = zext i8 %tmp24 to i64
152   %tmp26 = shl nuw nsw i64 %tmp25, 40
153   %tmp27 = or i64 %tmp22, %tmp26
154   %tmp28 = getelementptr inbounds i8, i8* %tmp, i64 6
155   %tmp29 = load i8, i8* %tmp28, align 1
156   %tmp30 = zext i8 %tmp29 to i64
157   %tmp31 = shl nuw nsw i64 %tmp30, 48
158   %tmp32 = or i64 %tmp27, %tmp31
159   %tmp33 = getelementptr inbounds i8, i8* %tmp, i64 7
160   %tmp34 = load i8, i8* %tmp33, align 1
161   %tmp35 = zext i8 %tmp34 to i64
162   %tmp36 = shl nuw i64 %tmp35, 56
163   %tmp37 = or i64 %tmp32, %tmp36
164   ret i64 %tmp37
167 ; i8* p; // p is 8 byte aligned
168 ; ((i64) p[0] << 56) | ((i64) p[1] << 48) | ((i64) p[2] << 40) | ((i64) p[3] << 32) | ((i64) p[4] << 24) | ((i64) p[5] << 16) | ((i64) p[6] << 8) | (i64) p[7]
169 define i64 @load_i64_by_i8_bswap(i64* %arg) {
170 ; CHECK-LABEL: load_i64_by_i8_bswap:
171 ; CHECK: ldr{{.*}}r0
172 ; CHECK: ldr{{.*}}r0
173 ; CHECK: and
174 ; CHECK-NEXT: and
175 ; CHECK-NEXT: orr
176 ; CHECK-NEXT: orr
177 ; CHECK-NEXT: and
178 ; CHECK-NEXT: orr
179 ; CHECK-NEXT: and
180 ; CHECK-NEXT: orr
181 ; CHECK-NEXT: orr
182 ; CHECK-NEXT: orr
183 ; CHECK: mov pc, lr
185 ; CHECK-ARMv6-LABEL: load_i64_by_i8_bswap:
186 ; CHECK-ARMv6: ldrd  r2, r3, [r0]
187 ; CHECK-ARMv6: rev r0, r3
188 ; CHECK-ARMv6: rev r1, r2
189 ; CHECK-ARMv6: bx  lr
190   %tmp = bitcast i64* %arg to i8*
191   %tmp1 = load i8, i8* %tmp, align 8
192   %tmp2 = zext i8 %tmp1 to i64
193   %tmp3 = shl nuw i64 %tmp2, 56
194   %tmp4 = getelementptr inbounds i8, i8* %tmp, i64 1
195   %tmp5 = load i8, i8* %tmp4, align 1
196   %tmp6 = zext i8 %tmp5 to i64
197   %tmp7 = shl nuw nsw i64 %tmp6, 48
198   %tmp8 = or i64 %tmp7, %tmp3
199   %tmp9 = getelementptr inbounds i8, i8* %tmp, i64 2
200   %tmp10 = load i8, i8* %tmp9, align 1
201   %tmp11 = zext i8 %tmp10 to i64
202   %tmp12 = shl nuw nsw i64 %tmp11, 40
203   %tmp13 = or i64 %tmp8, %tmp12
204   %tmp14 = getelementptr inbounds i8, i8* %tmp, i64 3
205   %tmp15 = load i8, i8* %tmp14, align 1
206   %tmp16 = zext i8 %tmp15 to i64
207   %tmp17 = shl nuw nsw i64 %tmp16, 32
208   %tmp18 = or i64 %tmp13, %tmp17
209   %tmp19 = getelementptr inbounds i8, i8* %tmp, i64 4
210   %tmp20 = load i8, i8* %tmp19, align 1
211   %tmp21 = zext i8 %tmp20 to i64
212   %tmp22 = shl nuw nsw i64 %tmp21, 24
213   %tmp23 = or i64 %tmp18, %tmp22
214   %tmp24 = getelementptr inbounds i8, i8* %tmp, i64 5
215   %tmp25 = load i8, i8* %tmp24, align 1
216   %tmp26 = zext i8 %tmp25 to i64
217   %tmp27 = shl nuw nsw i64 %tmp26, 16
218   %tmp28 = or i64 %tmp23, %tmp27
219   %tmp29 = getelementptr inbounds i8, i8* %tmp, i64 6
220   %tmp30 = load i8, i8* %tmp29, align 1
221   %tmp31 = zext i8 %tmp30 to i64
222   %tmp32 = shl nuw nsw i64 %tmp31, 8
223   %tmp33 = or i64 %tmp28, %tmp32
224   %tmp34 = getelementptr inbounds i8, i8* %tmp, i64 7
225   %tmp35 = load i8, i8* %tmp34, align 1
226   %tmp36 = zext i8 %tmp35 to i64
227   %tmp37 = or i64 %tmp33, %tmp36
228   ret i64 %tmp37
231 ; i8* p; // p[1] is 4 byte aligned
232 ; (i32) p[1] | ((i32) p[2] << 8) | ((i32) p[3] << 16) | ((i32) p[4] << 24)
233 define i32 @load_i32_by_i8_nonzero_offset(i32* %arg) {
234 ; CHECK-LABEL: load_i32_by_i8_nonzero_offset:
235 ; CHECK: ldr r0, [r0, #1]
236 ; CHECK-NEXT: mov pc, lr
238 ; CHECK-ARMv6-LABEL: load_i32_by_i8_nonzero_offset:
239 ; CHECK-ARMv6: ldr r0, [r0, #1]
240 ; CHECK-ARMv6-NEXT: bx  lr
242   %tmp = bitcast i32* %arg to i8*
243   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1
244   %tmp2 = load i8, i8* %tmp1, align 4
245   %tmp3 = zext i8 %tmp2 to i32
246   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 2
247   %tmp5 = load i8, i8* %tmp4, align 1
248   %tmp6 = zext i8 %tmp5 to i32
249   %tmp7 = shl nuw nsw i32 %tmp6, 8
250   %tmp8 = or i32 %tmp7, %tmp3
251   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 3
252   %tmp10 = load i8, i8* %tmp9, align 1
253   %tmp11 = zext i8 %tmp10 to i32
254   %tmp12 = shl nuw nsw i32 %tmp11, 16
255   %tmp13 = or i32 %tmp8, %tmp12
256   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 4
257   %tmp15 = load i8, i8* %tmp14, align 1
258   %tmp16 = zext i8 %tmp15 to i32
259   %tmp17 = shl nuw nsw i32 %tmp16, 24
260   %tmp18 = or i32 %tmp13, %tmp17
261   ret i32 %tmp18
264 ; i8* p; // p[-4] is 4 byte aligned
265 ; (i32) p[-4] | ((i32) p[-3] << 8) | ((i32) p[-2] << 16) | ((i32) p[-1] << 24)
266 define i32 @load_i32_by_i8_neg_offset(i32* %arg) {
267 ; CHECK-LABEL: load_i32_by_i8_neg_offset:
268 ; CHECK: ldr r0, [r0, #-4]
269 ; CHECK-NEXT: mov pc, lr
271 ; CHECK-ARMv6-LABEL: load_i32_by_i8_neg_offset:
272 ; CHECK-ARMv6: ldr r0, [r0, #-4]
273 ; CHECK-ARMv6-NEXT: bx  lr
275   %tmp = bitcast i32* %arg to i8*
276   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -4
277   %tmp2 = load i8, i8* %tmp1, align 4
278   %tmp3 = zext i8 %tmp2 to i32
279   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -3
280   %tmp5 = load i8, i8* %tmp4, align 1
281   %tmp6 = zext i8 %tmp5 to i32
282   %tmp7 = shl nuw nsw i32 %tmp6, 8
283   %tmp8 = or i32 %tmp7, %tmp3
284   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -2
285   %tmp10 = load i8, i8* %tmp9, align 1
286   %tmp11 = zext i8 %tmp10 to i32
287   %tmp12 = shl nuw nsw i32 %tmp11, 16
288   %tmp13 = or i32 %tmp8, %tmp12
289   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -1
290   %tmp15 = load i8, i8* %tmp14, align 1
291   %tmp16 = zext i8 %tmp15 to i32
292   %tmp17 = shl nuw nsw i32 %tmp16, 24
293   %tmp18 = or i32 %tmp13, %tmp17
294   ret i32 %tmp18
297 ; i8* p; // p[1] is 4 byte aligned
298 ; (i32) p[4] | ((i32) p[3] << 8) | ((i32) p[2] << 16) | ((i32) p[1] << 24)
299 define i32 @load_i32_by_i8_nonzero_offset_bswap(i32* %arg) {
300 ; CHECK-LABEL: load_i32_by_i8_nonzero_offset_bswap:
301 ; CHECK: ldr r0, [r0, #1]
302 ; CHECK-NEXT: mov r1, #65280
303 ; CHECK-NEXT: mov r2, #16711680
304 ; CHECK-NEXT: and r1, r1, r0, lsr #8
305 ; CHECK-NEXT: and r2, r2, r0, lsl #8
306 ; CHECK-NEXT: orr r1, r1, r0, lsr #24
307 ; CHECK-NEXT: orr r0, r2, r0, lsl #24
308 ; CHECK-NEXT: orr r0, r0, r1
309 ; CHECK-NEXT: mov pc, lr
311 ; CHECK-ARMv6-LABEL: load_i32_by_i8_nonzero_offset_bswap:
312 ; CHECK-ARMv6: ldr r0, [r0, #1]
313 ; CHECK-ARMv6-NEXT: rev r0, r0
314 ; CHECK-ARMv6-NEXT: bx  lr
316   %tmp = bitcast i32* %arg to i8*
317   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 4
318   %tmp2 = load i8, i8* %tmp1, align 1
319   %tmp3 = zext i8 %tmp2 to i32
320   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 3
321   %tmp5 = load i8, i8* %tmp4, align 1
322   %tmp6 = zext i8 %tmp5 to i32
323   %tmp7 = shl nuw nsw i32 %tmp6, 8
324   %tmp8 = or i32 %tmp7, %tmp3
325   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 2
326   %tmp10 = load i8, i8* %tmp9, align 1
327   %tmp11 = zext i8 %tmp10 to i32
328   %tmp12 = shl nuw nsw i32 %tmp11, 16
329   %tmp13 = or i32 %tmp8, %tmp12
330   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 1
331   %tmp15 = load i8, i8* %tmp14, align 4
332   %tmp16 = zext i8 %tmp15 to i32
333   %tmp17 = shl nuw nsw i32 %tmp16, 24
334   %tmp18 = or i32 %tmp13, %tmp17
335   ret i32 %tmp18
338 ; i8* p; // p[-4] is 4 byte aligned
339 ; (i32) p[-1] | ((i32) p[-2] << 8) | ((i32) p[-3] << 16) | ((i32) p[-4] << 24)
340 define i32 @load_i32_by_i8_neg_offset_bswap(i32* %arg) {
341 ; CHECK-LABEL: load_i32_by_i8_neg_offset_bswap:
342 ; CHECK: ldr r0, [r0, #-4]
343 ; CHECK-NEXT: mov r1, #65280
344 ; CHECK-NEXT: mov r2, #16711680
345 ; CHECK-NEXT: and r1, r1, r0, lsr #8
346 ; CHECK-NEXT: and r2, r2, r0, lsl #8
347 ; CHECK-NEXT: orr r1, r1, r0, lsr #24
348 ; CHECK-NEXT: orr r0, r2, r0, lsl #24
349 ; CHECK-NEXT: orr r0, r0, r1
350 ; CHECK-NEXT: mov pc, lr
352 ; CHECK-ARMv6-LABEL: load_i32_by_i8_neg_offset_bswap:
353 ; CHECK-ARMv6: ldr r0, [r0, #-4]
354 ; CHECK-ARMv6-NEXT: rev r0, r0
355 ; CHECK-ARMv6-NEXT: bx  lr
357   %tmp = bitcast i32* %arg to i8*
358   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 -1
359   %tmp2 = load i8, i8* %tmp1, align 1
360   %tmp3 = zext i8 %tmp2 to i32
361   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 -2
362   %tmp5 = load i8, i8* %tmp4, align 1
363   %tmp6 = zext i8 %tmp5 to i32
364   %tmp7 = shl nuw nsw i32 %tmp6, 8
365   %tmp8 = or i32 %tmp7, %tmp3
366   %tmp9 = getelementptr inbounds i8, i8* %tmp, i32 -3
367   %tmp10 = load i8, i8* %tmp9, align 1
368   %tmp11 = zext i8 %tmp10 to i32
369   %tmp12 = shl nuw nsw i32 %tmp11, 16
370   %tmp13 = or i32 %tmp8, %tmp12
371   %tmp14 = getelementptr inbounds i8, i8* %tmp, i32 -4
372   %tmp15 = load i8, i8* %tmp14, align 4
373   %tmp16 = zext i8 %tmp15 to i32
374   %tmp17 = shl nuw nsw i32 %tmp16, 24
375   %tmp18 = or i32 %tmp13, %tmp17
376   ret i32 %tmp18
379 declare i16 @llvm.bswap.i16(i16)
381 ; i16* p; // p is 4 byte aligned
382 ; (i32) bswap(p[1]) | (i32) bswap(p[0] << 16)
383 define i32 @load_i32_by_bswap_i16(i32* %arg) {
384 ; CHECK-LABEL: load_i32_by_bswap_i16:
385 ; CHECK: ldr  r0, [r0]
386 ; CHECK-NEXT: mov r1, #65280
387 ; CHECK-NEXT: mov r2, #16711680
388 ; CHECK-NEXT: and r1, r1, r0, lsr #8
389 ; CHECK-NEXT: and r2, r2, r0, lsl #8
390 ; CHECK-NEXT: orr r1, r1, r0, lsr #24
391 ; CHECK-NEXT: orr r0, r2, r0, lsl #24
392 ; CHECK-NEXT: orr r0, r0, r1
393 ; CHECK-NEXT: mov pc, lr
395 ; CHECK-ARMv6-LABEL: load_i32_by_bswap_i16:
396 ; CHECK-ARMv6: ldr r0, [r0]
397 ; CHECK-ARMv6-NEXT: rev r0, r0
398 ; CHECK-ARMv6-NEXT: bx  lr
400   %tmp = bitcast i32* %arg to i16*
401   %tmp1 = load i16, i16* %tmp, align 4
402   %tmp11 = call i16 @llvm.bswap.i16(i16 %tmp1)
403   %tmp2 = zext i16 %tmp11 to i32
404   %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1
405   %tmp4 = load i16, i16* %tmp3, align 1
406   %tmp41 = call i16 @llvm.bswap.i16(i16 %tmp4)
407   %tmp5 = zext i16 %tmp41 to i32
408   %tmp6 = shl nuw nsw i32 %tmp2, 16
409   %tmp7 = or i32 %tmp6, %tmp5
410   ret i32 %tmp7
413 ; i16* p;
414 ; (i32) p[0] | (sext(p[1] << 16) to i32)
415 define i32 @load_i32_by_sext_i16(i32* %arg) {
416 ; CHECK-LABEL: load_i32_by_sext_i16:
417 ; CHECK: ldr  r0, [r0]
418 ; CHECK-NEXT: mov pc, lr
420 ; CHECK-ARMv6-LABEL: load_i32_by_sext_i16:
421 ; CHECK-ARMv6: ldr  r0, [r0]
422 ; CHECK-ARMv6-NEXT: bx lr
423   %tmp = bitcast i32* %arg to i16*
424   %tmp1 = load i16, i16* %tmp, align 4
425   %tmp2 = zext i16 %tmp1 to i32
426   %tmp3 = getelementptr inbounds i16, i16* %tmp, i32 1
427   %tmp4 = load i16, i16* %tmp3, align 1
428   %tmp5 = sext i16 %tmp4 to i32
429   %tmp6 = shl nuw nsw i32 %tmp5, 16
430   %tmp7 = or i32 %tmp6, %tmp2
431   ret i32 %tmp7
434 ; i8* arg; i32 i;
435 ; p = arg + 12;
436 ; (i32) p[i] | ((i32) p[i + 1] << 8) | ((i32) p[i + 2] << 16) | ((i32) p[i + 3] << 24)
437 define i32 @load_i32_by_i8_base_offset_index(i8* %arg, i32 %i) {
438 ; CHECK-LABEL: load_i32_by_i8_base_offset_index:
439 ; CHECK: add r0, r0, r1
440 ; CHECK-NEXT: ldr r0, [r0, #12]
441 ; CHECK-NEXT: mov pc, lr
443 ; CHECK-ARMv6-LABEL: load_i32_by_i8_base_offset_index:
444 ; CHECK-ARMv6: add r0, r0, r1
445 ; CHECK-ARMv6-NEXT: ldr r0, [r0, #12]
446 ; CHECK-ARMv6-NEXT: bx  lr
448   %tmp = add nuw nsw i32 %i, 3
449   %tmp2 = add nuw nsw i32 %i, 2
450   %tmp3 = add nuw nsw i32 %i, 1
451   %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12
452   %tmp5 = zext i32 %i to i64
453   %tmp6 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp5
454   %tmp7 = load i8, i8* %tmp6, align 4
455   %tmp8 = zext i8 %tmp7 to i32
456   %tmp9 = zext i32 %tmp3 to i64
457   %tmp10 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp9
458   %tmp11 = load i8, i8* %tmp10, align 1
459   %tmp12 = zext i8 %tmp11 to i32
460   %tmp13 = shl nuw nsw i32 %tmp12, 8
461   %tmp14 = or i32 %tmp13, %tmp8
462   %tmp15 = zext i32 %tmp2 to i64
463   %tmp16 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp15
464   %tmp17 = load i8, i8* %tmp16, align 1
465   %tmp18 = zext i8 %tmp17 to i32
466   %tmp19 = shl nuw nsw i32 %tmp18, 16
467   %tmp20 = or i32 %tmp14, %tmp19
468   %tmp21 = zext i32 %tmp to i64
469   %tmp22 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp21
470   %tmp23 = load i8, i8* %tmp22, align 1
471   %tmp24 = zext i8 %tmp23 to i32
472   %tmp25 = shl nuw i32 %tmp24, 24
473   %tmp26 = or i32 %tmp20, %tmp25
474   ret i32 %tmp26
477 ; i8* arg; i32 i;
478 ; p = arg + 12;
479 ; (i32) p[i + 1] | ((i32) p[i + 2] << 8) | ((i32) p[i + 3] << 16) | ((i32) p[i + 4] << 24)
480 define i32 @load_i32_by_i8_base_offset_index_2(i8* %arg, i32 %i) {
481 ; CHECK-LABEL: load_i32_by_i8_base_offset_index_2:
482 ; CHECK: add r0, r1, r0
483 ; CHECK-NEXT: ldr r0, [r0, #13]
484 ; CHECK-NEXT: mov pc, lr
486 ; CHECK-ARMv6-LABEL: load_i32_by_i8_base_offset_index_2:
487 ; CHECK-ARMv6: add r0, r1, r0
488 ; CHECK-ARMv6-NEXT: ldr r0, [r0, #13]
489 ; CHECK-ARMv6-NEXT: bx  lr
490   %tmp = add nuw nsw i32 %i, 4
491   %tmp2 = add nuw nsw i32 %i, 3
492   %tmp3 = add nuw nsw i32 %i, 2
493   %tmp4 = getelementptr inbounds i8, i8* %arg, i64 12
494   %tmp5 = add nuw nsw i32 %i, 1
495   %tmp27 = zext i32 %tmp5 to i64
496   %tmp28 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp27
497   %tmp29 = load i8, i8* %tmp28, align 4
498   %tmp30 = zext i8 %tmp29 to i32
499   %tmp31 = zext i32 %tmp3 to i64
500   %tmp32 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp31
501   %tmp33 = load i8, i8* %tmp32, align 1
502   %tmp34 = zext i8 %tmp33 to i32
503   %tmp35 = shl nuw nsw i32 %tmp34, 8
504   %tmp36 = or i32 %tmp35, %tmp30
505   %tmp37 = zext i32 %tmp2 to i64
506   %tmp38 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp37
507   %tmp39 = load i8, i8* %tmp38, align 1
508   %tmp40 = zext i8 %tmp39 to i32
509   %tmp41 = shl nuw nsw i32 %tmp40, 16
510   %tmp42 = or i32 %tmp36, %tmp41
511   %tmp43 = zext i32 %tmp to i64
512   %tmp44 = getelementptr inbounds i8, i8* %tmp4, i64 %tmp43
513   %tmp45 = load i8, i8* %tmp44, align 1
514   %tmp46 = zext i8 %tmp45 to i32
515   %tmp47 = shl nuw i32 %tmp46, 24
516   %tmp48 = or i32 %tmp42, %tmp47
517   ret i32 %tmp48
520 ; i8* p; // p is 2 byte aligned
521 ; (i32) p[0] | ((i32) p[1] << 8)
522 define i32 @zext_load_i32_by_i8(i32* %arg) {
523 ; CHECK-LABEL: zext_load_i32_by_i8:
524 ; CHECK: ldrb  r1, [r0]
525 ; CHECK-NEXT: ldrb  r0, [r0, #1]
526 ; CHECK-NEXT: orr r0, r1, r0, lsl #8
527 ; CHECK-NEXT: mov pc, lr
529 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8:
530 ; CHECK-ARMv6: ldrb  r1, [r0]
531 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
532 ; CHECK-ARMv6-NEXT: orr r0, r1, r0, lsl #8
533 ; CHECK-ARMv6-NEXT: bx  lr
535   %tmp = bitcast i32* %arg to i8*
536   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0
537   %tmp2 = load i8, i8* %tmp1, align 2
538   %tmp3 = zext i8 %tmp2 to i32
539   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
540   %tmp5 = load i8, i8* %tmp4, align 1
541   %tmp6 = zext i8 %tmp5 to i32
542   %tmp7 = shl nuw nsw i32 %tmp6, 8
543   %tmp8 = or i32 %tmp7, %tmp3
544   ret i32 %tmp8
547 ; i8* p; // p is 2 byte aligned
548 ; ((i32) p[0] << 8) | ((i32) p[1] << 16)
549 define i32 @zext_load_i32_by_i8_shl_8(i32* %arg) {
550 ; CHECK-LABEL: zext_load_i32_by_i8_shl_8:
551 ; CHECK: ldrb  r1, [r0]
552 ; CHECK-NEXT: ldrb  r0, [r0, #1]
553 ; CHECK-NEXT: lsl r0, r0, #16
554 ; CHECK-NEXT: orr r0, r0, r1, lsl #8
555 ; CHECK-NEXT: mov pc, lr
557 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8_shl_8:
558 ; CHECK-ARMv6: ldrb  r1, [r0]
559 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
560 ; CHECK-ARMv6-NEXT: lsl r0, r0, #16
561 ; CHECK-ARMv6-NEXT: orr r0, r0, r1, lsl #8
562 ; CHECK-ARMv6-NEXT: bx  lr
564   %tmp = bitcast i32* %arg to i8*
565   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0
566   %tmp2 = load i8, i8* %tmp1, align 2
567   %tmp3 = zext i8 %tmp2 to i32
568   %tmp30 = shl nuw nsw i32 %tmp3, 8
569   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
570   %tmp5 = load i8, i8* %tmp4, align 1
571   %tmp6 = zext i8 %tmp5 to i32
572   %tmp7 = shl nuw nsw i32 %tmp6, 16
573   %tmp8 = or i32 %tmp7, %tmp30
574   ret i32 %tmp8
577 ; i8* p; // p is 2 byte aligned
578 ; ((i32) p[0] << 16) | ((i32) p[1] << 24)
579 define i32 @zext_load_i32_by_i8_shl_16(i32* %arg) {
580 ; CHECK-LABEL: zext_load_i32_by_i8_shl_16:
581 ; CHECK: ldrb  r1, [r0]
582 ; CHECK-NEXT: ldrb  r0, [r0, #1]
583 ; CHECK-NEXT: lsl r0, r0, #24
584 ; CHECK-NEXT: orr r0, r0, r1, lsl #16
585 ; CHECK-NEXT: mov pc, lr
587 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8_shl_16:
588 ; CHECK-ARMv6: ldrb  r1, [r0]
589 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
590 ; CHECK-ARMv6-NEXT: lsl r0, r0, #24
591 ; CHECK-ARMv6-NEXT: orr r0, r0, r1, lsl #16
592 ; CHECK-ARMv6-NEXT: bx  lr
594   %tmp = bitcast i32* %arg to i8*
595   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 0
596   %tmp2 = load i8, i8* %tmp1, align 2
597   %tmp3 = zext i8 %tmp2 to i32
598   %tmp30 = shl nuw nsw i32 %tmp3, 16
599   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 1
600   %tmp5 = load i8, i8* %tmp4, align 1
601   %tmp6 = zext i8 %tmp5 to i32
602   %tmp7 = shl nuw nsw i32 %tmp6, 24
603   %tmp8 = or i32 %tmp7, %tmp30
604   ret i32 %tmp8
607 ; i8* p; // p is 2 byte aligned
608 ; (i32) p[1] | ((i32) p[0] << 8)
609 define i32 @zext_load_i32_by_i8_bswap(i32* %arg) {
610 ; CHECK-LABEL: zext_load_i32_by_i8_bswap:
611 ; CHECK: ldrb  r1, [r0]
612 ; CHECK-NEXT: ldrb  r0, [r0, #1]
613 ; CHECK-NEXT: orr r0, r0, r1, lsl #8
614 ; CHECK-NEXT: mov pc, lr
616 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8_bswap:
617 ; CHECK-ARMv6: ldrb  r1, [r0]
618 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
619 ; CHECK-ARMv6-NEXT: orr r0, r0, r1, lsl #8
620 ; CHECK-ARMv6-NEXT: bx  lr
622   %tmp = bitcast i32* %arg to i8*
623   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1
624   %tmp2 = load i8, i8* %tmp1, align 1
625   %tmp3 = zext i8 %tmp2 to i32
626   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0
627   %tmp5 = load i8, i8* %tmp4, align 2
628   %tmp6 = zext i8 %tmp5 to i32
629   %tmp7 = shl nuw nsw i32 %tmp6, 8
630   %tmp8 = or i32 %tmp7, %tmp3
631   ret i32 %tmp8
634 ; i8* p; // p is 2 byte aligned
635 ; ((i32) p[1] << 8) | ((i32) p[0] << 16)
636 define i32 @zext_load_i32_by_i8_bswap_shl_8(i32* %arg) {
637 ; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_8:
638 ; CHECK: ldrb  r1, [r0]
639 ; CHECK-NEXT: ldrb  r0, [r0, #1]
640 ; CHECK-NEXT: lsl r1, r1, #16
641 ; CHECK-NEXT: orr r0, r1, r0, lsl #8
642 ; CHECK-NEXT: mov pc, lr
644 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8_bswap_shl_8:
645 ; CHECK-ARMv6: ldrb  r1, [r0]
646 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
647 ; CHECK-ARMv6-NEXT: lsl r1, r1, #16
648 ; CHECK-ARMv6-NEXT: orr r0, r1, r0, lsl #8
649 ; CHECK-ARMv6-NEXT: bx  lr
651   %tmp = bitcast i32* %arg to i8*
652   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1
653   %tmp2 = load i8, i8* %tmp1, align 1
654   %tmp3 = zext i8 %tmp2 to i32
655   %tmp30 = shl nuw nsw i32 %tmp3, 8
656   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0
657   %tmp5 = load i8, i8* %tmp4, align 2
658   %tmp6 = zext i8 %tmp5 to i32
659   %tmp7 = shl nuw nsw i32 %tmp6, 16
660   %tmp8 = or i32 %tmp7, %tmp30
661   ret i32 %tmp8
664 ; i8* p; // p is 2 byte aligned
665 ; ((i32) p[1] << 16) | ((i32) p[0] << 24)
666 define i32 @zext_load_i32_by_i8_bswap_shl_16(i32* %arg) {
667 ; CHECK-LABEL: zext_load_i32_by_i8_bswap_shl_16:
668 ; CHECK: ldrb  r1, [r0]
669 ; CHECK-NEXT: ldrb  r0, [r0, #1]
670 ; CHECK-NEXT: lsl r1, r1, #24
671 ; CHECK-NEXT: orr r0, r1, r0, lsl #16
672 ; CHECK-NEXT: mov pc, lr
674 ; CHECK-ARMv6-LABEL: zext_load_i32_by_i8_bswap_shl_16:
675 ; CHECK-ARMv6: ldrb  r1, [r0]
676 ; CHECK-ARMv6-NEXT: ldrb  r0, [r0, #1]
677 ; CHECK-ARMv6-NEXT: lsl r1, r1, #24
678 ; CHECK-ARMv6-NEXT: orr r0, r1, r0, lsl #16
679 ; CHECK-ARMv6-NEXT: bx  lr
681   %tmp = bitcast i32* %arg to i8*
682   %tmp1 = getelementptr inbounds i8, i8* %tmp, i32 1
683   %tmp2 = load i8, i8* %tmp1, align 1
684   %tmp3 = zext i8 %tmp2 to i32
685   %tmp30 = shl nuw nsw i32 %tmp3, 16
686   %tmp4 = getelementptr inbounds i8, i8* %tmp, i32 0
687   %tmp5 = load i8, i8* %tmp4, align 2
688   %tmp6 = zext i8 %tmp5 to i32
689   %tmp7 = shl nuw nsw i32 %tmp6, 24
690   %tmp8 = or i32 %tmp7, %tmp30
691   ret i32 %tmp8