[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / ARM / load.ll
blobf33294267f518b3658de716d1d6fb516140116e6
1 ; RUN: llc -mtriple=thumbv6m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T1
2 ; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-T2
5 ; Register offset
7 ; CHECK-LABEL: ldrsb_rr
8 ; CHECK:    ldrsb   r0, [r0, r1]
9 define i32 @ldrsb_rr(i8* %p, i32 %n) {
10 entry:
11   %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
12   %0 = load i8, i8* %arrayidx, align 1
13   %conv = sext i8 %0 to i32
14   ret i32 %conv
17 ; CHECK-LABEL: ldrsh_rr
18 ; CHECK-T1: lsls    r1, r1, #1
19 ; CHECK-T1: ldrsh   r0, [r0, r1]
20 ; CHECK-T2: ldrsh.w r0, [r0, r1, lsl #1]
21 define i32 @ldrsh_rr(i16* %p, i32 %n) {
22 entry:
23   %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
24   %0 = load i16, i16* %arrayidx, align 2
25   %conv = sext i16 %0 to i32
26   ret i32 %conv
29 ; CHECK-LABEL: ldrb_rr
30 ; CHECK:    ldrb r0, [r0, r1]
31 define i32 @ldrb_rr(i8* %p, i32 %n) {
32 entry:
33   %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
34   %0 = load i8, i8* %arrayidx, align 1
35   %conv = zext i8 %0 to i32
36   ret i32 %conv
39 ; CHECK-LABEL: ldrh_rr
40 ; CHECK-T1: lsls    r1, r1, #1
41 ; CHECK-T1: ldrh    r0, [r0, r1]
42 ; CHECK-T2: ldrh.w  r0, [r0, r1, lsl #1]
43 define i32 @ldrh_rr(i16* %p, i32 %n) {
44 entry:
45   %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
46   %0 = load i16, i16* %arrayidx, align 2
47   %conv = zext i16 %0 to i32
48   ret i32 %conv
51 ; CHECK-LABEL: ldr_rr
52 ; CHECK-T1: lsls    r1, r1, #2
53 ; CHECK-T1: ldr     r0, [r0, r1]
54 ; CHECK-T2: ldr.w   r0, [r0, r1, lsl #2]
55 define i32 @ldr_rr(i32* %p, i32 %n) {
56 entry:
57   %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
58   %0 = load i32, i32* %arrayidx, align 4
59   ret i32 %0
62 ; CHECK-LABEL: strb_rr
63 ; CHECK:    strb    r2, [r0, r1]
64 define void @strb_rr(i8* %p, i32 %n, i32 %x) {
65 entry:
66   %conv = trunc i32 %x to i8
67   %arrayidx = getelementptr inbounds i8, i8* %p, i32 %n
68   store i8 %conv, i8* %arrayidx, align 1
69   ret void
72 ; CHECK-LABEL: strh_rr
73 ; CHECK-T1: lsls    r1, r1, #1
74 ; CHECK-T1: strh    r2, [r0, r1]
75 ; CHECK-T2: strh.w  r2, [r0, r1, lsl #1]
76 define void @strh_rr(i16* %p, i32 %n, i32 %x) {
77 entry:
78   %conv = trunc i32 %x to i16
79   %arrayidx = getelementptr inbounds i16, i16* %p, i32 %n
80   store i16 %conv, i16* %arrayidx, align 2
81   ret void
84 ; CHECK-LABEL: str_rr
85 ; CHECK-T1: lsls    r1, r1, #2
86 ; CHECK-T1: str     r2, [r0, r1]
87 ; CHECK-T2: str.w   r2, [r0, r1, lsl #2]
88 define void @str_rr(i32* %p, i32 %n, i32 %x) {
89 entry:
90   %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
91   store i32 %x, i32* %arrayidx, align 4
92   ret void
96 ; Immediate offset of zero
98 ; CHECK-LABEL: ldrsb_ri_zero
99 ; CHECK-T1: ldrb    r0, [r0]
100 ; CHECK-T1: sxtb    r0, r0
101 ; CHECK-T2: ldrsb.w r0, [r0]
102 define i32 @ldrsb_ri_zero(i8* %p) {
103 entry:
104   %0 = load i8, i8* %p, align 1
105   %conv = sext i8 %0 to i32
106   ret i32 %conv
109 ; CHECK-LABEL: ldrsh_ri_zero
110 ; CHECK-T1: ldrh    r0, [r0]
111 ; CHECK-T1: sxth    r0, r0
112 ; CHECK-T2: ldrsh.w r0, [r0]
113 define i32 @ldrsh_ri_zero(i16* %p) {
114 entry:
115   %0 = load i16, i16* %p, align 2
116   %conv = sext i16 %0 to i32
117   ret i32 %conv
120 ; CHECK-LABEL: ldrb_ri_zero
121 ; CHECK:    ldrb    r0, [r0]
122 define i32 @ldrb_ri_zero(i8* %p) {
123 entry:
124   %0 = load i8, i8* %p, align 1
125   %conv = zext i8 %0 to i32
126   ret i32 %conv
129 ; CHECK-LABEL: ldrh_ri_zero
130 ; CHECK:    ldrh    r0, [r0]
131 define i32 @ldrh_ri_zero(i16* %p) {
132 entry:
133   %0 = load i16, i16* %p, align 2
134   %conv = zext i16 %0 to i32
135   ret i32 %conv
138 ; CHECK-LABEL: ldr_ri_zero
139 ; CHECK:    ldr     r0, [r0]
140 define i32 @ldr_ri_zero(i32* %p) {
141 entry:
142   %0 = load i32, i32* %p, align 4
143   ret i32 %0
146 ; CHECK-LABEL: strb_ri_zero
147 ; CHECK:    strb    r1, [r0]
148 define void @strb_ri_zero(i8* %p, i32 %x) {
149 entry:
150   %conv = trunc i32 %x to i8
151   store i8 %conv, i8* %p, align 1
152   ret void
155 ; CHECK-LABEL: strh_ri_zero
156 ; CHECK:    strh    r1, [r0]
157 define void @strh_ri_zero(i16* %p, i32 %x) {
158 entry:
159   %conv = trunc i32 %x to i16
160   store i16 %conv, i16* %p, align 2
161   ret void
164 ; CHECK-LABEL: str_ri_zero
165 ; CHECK:    str     r1, [r0]
166 define void @str_ri_zero(i32* %p, i32 %x) {
167 entry:
168   store i32 %x, i32* %p, align 4
169   ret void
173 ; Maximum Thumb-1 immediate offset
175 ; CHECK-LABEL: ldrsb_ri_t1_max
176 ; CHECK-T1: movs    r1, #31
177 ; CHECK-T1: ldrsb   r0, [r0, r1]
178 ; CHECK-T2: ldrsb.w r0, [r0, #31]
179 define i32 @ldrsb_ri_t1_max(i8* %p) {
180 entry:
181   %arrayidx = getelementptr inbounds i8, i8* %p, i32 31
182   %0 = load i8, i8* %arrayidx, align 1
183   %conv = sext i8 %0 to i32
184   ret i32 %conv
187 ; CHECK-LABEL: ldrsh_ri_t1_max
188 ; CHECK-T1: movs    r1, #62
189 ; CHECK-T1: ldrsh   r0, [r0, r1]
190 ; CHECK-T2: ldrsh.w r0, [r0, #62]
191 define i32 @ldrsh_ri_t1_max(i16* %p) {
192 entry:
193   %arrayidx = getelementptr inbounds i16, i16* %p, i32 31
194   %0 = load i16, i16* %arrayidx, align 2
195   %conv = sext i16 %0 to i32
196   ret i32 %conv
199 ; CHECK-LABEL: ldrb_ri_t1_max
200 ; CHECK:    ldrb    r0, [r0, #31]
201 define i32 @ldrb_ri_t1_max(i8* %p) {
202 entry:
203   %arrayidx = getelementptr inbounds i8, i8* %p, i32 31
204   %0 = load i8, i8* %arrayidx, align 1
205   %conv = zext i8 %0 to i32
206   ret i32 %conv
209 ; CHECK-LABEL: ldrh_ri_t1_max
210 ; CHECK:    ldrh    r0, [r0, #62]
211 define i32 @ldrh_ri_t1_max(i16* %p) {
212 entry:
213   %arrayidx = getelementptr inbounds i16, i16* %p, i32 31
214   %0 = load i16, i16* %arrayidx, align 2
215   %conv = zext i16 %0 to i32
216   ret i32 %conv
219 ; CHECK-LABEL: ldr_ri_t1_max
220 ; CHECK:    ldr     r0, [r0, #124]
221 define i32 @ldr_ri_t1_max(i32* %p) {
222 entry:
223   %arrayidx = getelementptr inbounds i32, i32* %p, i32 31
224   %0 = load i32, i32* %arrayidx, align 4
225   ret i32 %0
228 ; CHECK-LABEL: strb_ri_t1_max
229 ; CHECK:    strb    r1, [r0, #31]
230 define void @strb_ri_t1_max(i8* %p, i32 %x) {
231 entry:
232   %conv = trunc i32 %x to i8
233   %arrayidx = getelementptr inbounds i8, i8* %p, i32 31
234   store i8 %conv, i8* %arrayidx, align 1
235   ret void
238 ; CHECK-LABEL: strh_ri_t1_max
239 ; CHECK:    strh    r1, [r0, #62]
240 define void @strh_ri_t1_max(i16* %p, i32 %x) {
241 entry:
242   %conv = trunc i32 %x to i16
243   %arrayidx = getelementptr inbounds i16, i16* %p, i32 31
244   store i16 %conv, i16* %arrayidx, align 2
245   ret void
248 ; CHECK-LABEL: str_ri_t1_max
249 ; CHECK:    str     r1, [r0, #124]
250 define void @str_ri_t1_max(i32* %p, i32 %x) {
251 entry:
252   %arrayidx = getelementptr inbounds i32, i32* %p, i32 31
253   store i32 %x, i32* %arrayidx, align 4
254   ret void
258 ; One past maximum Thumb-1 immediate offset
260 ; CHECK-LABEL: ldrsb_ri_t1_too_big
261 ; CHECK-T1: movs    r1, #32
262 ; CHECK-T1: ldrsb   r0, [r0, r1]
263 ; CHECK-T2: ldrsb.w r0, [r0, #32]
264 define i32 @ldrsb_ri_t1_too_big(i8* %p) {
265 entry:
266   %arrayidx = getelementptr inbounds i8, i8* %p, i32 32
267   %0 = load i8, i8* %arrayidx, align 1
268   %conv = sext i8 %0 to i32
269   ret i32 %conv
272 ; CHECK-LABEL: ldrsh_ri_t1_too_big
273 ; CHECK-T1: movs    r1, #64
274 ; CHECK-T1: ldrsh   r0, [r0, r1]
275 ; CHECK-T2: ldrsh.w r0, [r0, #64]
276 define i32 @ldrsh_ri_t1_too_big(i16* %p) {
277 entry:
278   %arrayidx = getelementptr inbounds i16, i16* %p, i32 32
279   %0 = load i16, i16* %arrayidx, align 2
280   %conv = sext i16 %0 to i32
281   ret i32 %conv
284 ; CHECK-LABEL: ldrb_ri_t1_too_big
285 ; CHECK-T1: movs    r1, #32
286 ; CHECK-T1: ldrb    r0, [r0, r1]
287 ; CHECK-T2: ldrb.w  r0, [r0, #32]
288 define i32 @ldrb_ri_t1_too_big(i8* %p) {
289 entry:
290   %arrayidx = getelementptr inbounds i8, i8* %p, i32 32
291   %0 = load i8, i8* %arrayidx, align 1
292   %conv = zext i8 %0 to i32
293   ret i32 %conv
296 ; CHECK-LABEL: ldrh_ri_t1_too_big
297 ; CHECK-T1: movs    r1, #64
298 ; CHECK-T1: ldrh    r0, [r0, r1]
299 ; CHECK-T2: ldrh.w  r0, [r0, #64]
300 define i32 @ldrh_ri_t1_too_big(i16* %p) {
301 entry:
302   %arrayidx = getelementptr inbounds i16, i16* %p, i32 32
303   %0 = load i16, i16* %arrayidx, align 2
304   %conv = zext i16 %0 to i32
305   ret i32 %conv
308 ; CHECK-LABEL: ldr_ri_t1_too_big
309 ; CHECK-T1: movs    r1, #128
310 ; CHECK-T1: ldr     r0, [r0, r1]
311 ; CHECK-T2: ldr.w   r0, [r0, #128]
312 define i32 @ldr_ri_t1_too_big(i32* %p) {
313 entry:
314   %arrayidx = getelementptr inbounds i32, i32* %p, i32 32
315   %0 = load i32, i32* %arrayidx, align 4
316   ret i32 %0
319 ; CHECK-LABEL: strb_ri_t1_too_big
320 ; CHECK-T1: movs    r2, #32
321 ; CHECK-T1: strb    r1, [r0, r2]
322 ; CHECK-T2: strb.w  r1, [r0, #32]
323 define void @strb_ri_t1_too_big(i8* %p, i32 %x) {
324 entry:
325   %conv = trunc i32 %x to i8
326   %arrayidx = getelementptr inbounds i8, i8* %p, i32 32
327   store i8 %conv, i8* %arrayidx, align 1
328   ret void
331 ; CHECK-LABEL: strh_ri_t1_too_big
332 ; CHECK-T1: movs    r2, #64
333 ; CHECK-T1: strh    r1, [r0, r2]
334 ; CHECK-T2: strh.w  r1, [r0, #64]
335 define void @strh_ri_t1_too_big(i16* %p, i32 %x) {
336 entry:
337   %conv = trunc i32 %x to i16
338   %arrayidx = getelementptr inbounds i16, i16* %p, i32 32
339   store i16 %conv, i16* %arrayidx, align 2
340   ret void
343 ; CHECK-LABEL: str_ri_t1_too_big
344 ; CHECK-T1: movs    r2, #128
345 ; CHECK-T1: str     r1, [r0, r2]
346 ; CHECK-T2: str.w   r1, [r0, #128]
347 define void @str_ri_t1_too_big(i32* %p, i32 %x) {
348 entry:
349   %arrayidx = getelementptr inbounds i32, i32* %p, i32 32
350   store i32 %x, i32* %arrayidx, align 4
351   ret void
355 ; Maximum Thumb-2 immediate offset
357 ; CHECK-LABEL: ldrsb_ri_t2_max
358 ; CHECK-T1: ldr     r1, .LCP
359 ; CHECK-T1: ldrsb   r0, [r0, r1]
360 ; CHECK-T2: ldrsb.w r0, [r0, #4095]
361 define i32 @ldrsb_ri_t2_max(i8* %p) {
362 entry:
363   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
364   %0 = load i8, i8* %add.ptr, align 1
365   %conv = sext i8 %0 to i32
366   ret i32 %conv
369 ; CHECK-LABEL: ldrsh_ri_t2_max
370 ; CHECK-T1: ldr     r1, .LCP
371 ; CHECK-T1: ldrsh   r0, [r0, r1]
372 ; CHECK-T2: ldrsh.w r0, [r0, #4095]
373 define i32 @ldrsh_ri_t2_max(i8* %p) {
374 entry:
375   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
376   %0 = bitcast i8* %add.ptr to i16*
377   %1 = load i16, i16* %0, align 2
378   %conv = sext i16 %1 to i32
379   ret i32 %conv
382 ; CHECK-LABEL: ldrb_ri_t2_max
383 ; CHECK-T1: ldr     r1, .LCP
384 ; CHECK-T1: ldrb    r0, [r0, r1]
385 ; CHECK-T2: ldrb.w  r0, [r0, #4095]
386 define i32 @ldrb_ri_t2_max(i8* %p) {
387 entry:
388   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
389   %0 = load i8, i8* %add.ptr, align 1
390   %conv = zext i8 %0 to i32
391   ret i32 %conv
394 ; CHECK-LABEL: ldrh_ri_t2_max
395 ; CHECK-T1: ldr     r1, .LCP
396 ; CHECK-T1: ldrh    r0, [r0, r1]
397 ; CHECK-T2: ldrh.w  r0, [r0, #4095]
398 define i32 @ldrh_ri_t2_max(i8* %p) {
399 entry:
400   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
401   %0 = bitcast i8* %add.ptr to i16*
402   %1 = load i16, i16* %0, align 2
403   %conv = zext i16 %1 to i32
404   ret i32 %conv
407 ; CHECK-LABEL: ldr_ri_t2_max
408 ; CHECK-T1: ldr     r1, .LCP
409 ; CHECK-T1: ldr     r0, [r0, r1]
410 ; CHECK-T2: ldr.w   r0, [r0, #4095]
411 define i32 @ldr_ri_t2_max(i8* %p) {
412 entry:
413   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
414   %0 = bitcast i8* %add.ptr to i32*
415   %1 = load i32, i32* %0, align 4
416   ret i32 %1
419 ; CHECK-LABEL: strb_ri_t2_max
420 ; CHECK-T1: ldr     r2, .LCP
421 ; CHECK-T1: strb    r1, [r0, r2]
422 ; CHECK-T2: strb.w  r1, [r0, #4095]
423 define void @strb_ri_t2_max(i8* %p, i32 %x) {
424 entry:
425   %conv = trunc i32 %x to i8
426   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
427   store i8 %conv, i8* %add.ptr, align 1
428   ret void
431 ; CHECK-LABEL: strh_ri_t2_max
432 ; CHECK-T1: ldr     r2, .LCP
433 ; CHECK-T1: strh    r1, [r0, r2]
434 ; CHECK-T2: strh.w  r1, [r0, #4095]
435 define void @strh_ri_t2_max(i8* %p, i32 %x) {
436 entry:
437   %conv = trunc i32 %x to i16
438   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
439   %0 = bitcast i8* %add.ptr to i16*
440   store i16 %conv, i16* %0, align 2
441   ret void
444 ; CHECK-LABEL: str_ri_t2_max
445 ; CHECK-T1: ldr     r2, .LCP
446 ; CHECK-T1: str     r1, [r0, r2]
447 ; CHECK-T2: str.w   r1, [r0, #4095]
448 define void @str_ri_t2_max(i8* %p, i32 %x) {
449 entry:
450   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4095
451   %0 = bitcast i8* %add.ptr to i32*
452   store i32 %x, i32* %0, align 4
453   ret void
457 ; One past maximum Thumb-2 immediate offset
459 ; CHECK-LABEL: ldrsb_ri_t2_too_big
460 ; CHECK-T1: movs    r1, #1
461 ; CHECK-T1: lsls    r1, r1, #12
462 ; CHECK-T2: mov.w   r1, #4096
463 ; CHECK:    ldrsb   r0, [r0, r1]
464 define i32 @ldrsb_ri_t2_too_big(i8* %p) {
465 entry:
466   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
467   %0 = load i8, i8* %add.ptr, align 1
468   %conv = sext i8 %0 to i32
469   ret i32 %conv
472 ; CHECK-LABEL: ldrsh_ri_t2_too_big
473 ; CHECK-T1: movs    r1, #1
474 ; CHECK-T1: lsls    r1, r1, #12
475 ; CHECK-T2: mov.w   r1, #4096
476 ; CHECK:    ldrsh   r0, [r0, r1]
477 define i32 @ldrsh_ri_t2_too_big(i8* %p) {
478 entry:
479   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
480   %0 = bitcast i8* %add.ptr to i16*
481   %1 = load i16, i16* %0, align 2
482   %conv = sext i16 %1 to i32
483   ret i32 %conv
486 ; CHECK-LABEL: ldrb_ri_t2_too_big
487 ; CHECK-T1: movs    r1, #1
488 ; CHECK-T1: lsls    r1, r1, #12
489 ; CHECK-T2: mov.w   r1, #4096
490 ; CHECK:    ldrb    r0, [r0, r1]
491 define i32 @ldrb_ri_t2_too_big(i8* %p) {
492 entry:
493   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
494   %0 = load i8, i8* %add.ptr, align 1
495   %conv = zext i8 %0 to i32
496   ret i32 %conv
499 ; CHECK-LABEL: ldrh_ri_t2_too_big
500 ; CHECK-T1: movs    r1, #1
501 ; CHECK-T1: lsls    r1, r1, #12
502 ; CHECK-T2: mov.w   r1, #4096
503 ; CHECK:    ldrh    r0, [r0, r1]
504 define i32 @ldrh_ri_t2_too_big(i8* %p) {
505 entry:
506   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
507   %0 = bitcast i8* %add.ptr to i16*
508   %1 = load i16, i16* %0, align 2
509   %conv = zext i16 %1 to i32
510   ret i32 %conv
513 ; CHECK-LABEL: ldr_ri_t2_too_big
514 ; CHECK-T1: movs    r1, #1
515 ; CHECK-T1: lsls    r1, r1, #12
516 ; CHECK-T2: mov.w   r1, #4096
517 ; CHECK:    ldr     r0, [r0, r1]
518 define i32 @ldr_ri_t2_too_big(i8* %p) {
519 entry:
520   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
521   %0 = bitcast i8* %add.ptr to i32*
522   %1 = load i32, i32* %0, align 4
523   ret i32 %1
526 ; CHECK-LABEL: strb_ri_t2_too_big
527 ; CHECK-T1: movs    r2, #1
528 ; CHECK-T1: lsls    r2, r2, #12
529 ; CHECK-T2: mov.w   r2, #4096
530 ; CHECK:    strb    r1, [r0, r2]
531 define void @strb_ri_t2_too_big(i8* %p, i32 %x) {
532 entry:
533   %conv = trunc i32 %x to i8
534   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
535   store i8 %conv, i8* %add.ptr, align 1
536   ret void
539 ; CHECK-LABEL: strh_ri_t2_too_big
540 ; CHECK-T1: movs    r2, #1
541 ; CHECK-T1: lsls    r2, r2, #12
542 ; CHECK-T2: mov.w   r2, #4096
543 ; CHECK:    strh    r1, [r0, r2]
544 define void @strh_ri_t2_too_big(i8* %p, i32 %x) {
545 entry:
546   %conv = trunc i32 %x to i16
547   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
548   %0 = bitcast i8* %add.ptr to i16*
549   store i16 %conv, i16* %0, align 2
550   ret void
553 ; CHECK-LABEL: str_ri_t2_too_big
554 ; CHECK-T1: movs    r2, #1
555 ; CHECK-T1: lsls    r2, r2, #12
556 ; CHECK-T2: mov.w   r2, #4096
557 ; CHECK:    str     r1, [r0, r2]
558 define void @str_ri_t2_too_big(i8* %p, i32 %x) {
559 entry:
560   %add.ptr = getelementptr inbounds i8, i8* %p, i32 4096
561   %0 = bitcast i8* %add.ptr to i32*
562   store i32 %x, i32* %0, align 4
563   ret void
567 ; Negative offset
569 define i32 @ldrsb_ri_negative(i8* %p) {
570 ; CHECK-T1-LABEL: ldrsb_ri_negative:
571 ; CHECK-T1:       @ %bb.0: @ %entry
572 ; CHECK-T1-NEXT:    movs r1, #0
573 ; CHECK-T1-NEXT:    mvns r1, r1
574 ; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
575 ; CHECK-T1-NEXT:    bx lr
577 ; CHECK-T2-LABEL: ldrsb_ri_negative:
578 ; CHECK-T2:       @ %bb.0: @ %entry
579 ; CHECK-T2-NEXT:    ldrsb r0, [r0, #-1]
580 ; CHECK-T2-NEXT:    bx lr
581 entry:
582   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
583   %0 = load i8, i8* %add.ptr, align 1
584   %conv = sext i8 %0 to i32
585   ret i32 %conv
588 define i32 @ldrsh_ri_negative(i8* %p) {
589 ; CHECK-T1-LABEL: ldrsh_ri_negative:
590 ; CHECK-T1:       @ %bb.0: @ %entry
591 ; CHECK-T1-NEXT:    movs r1, #0
592 ; CHECK-T1-NEXT:    mvns r1, r1
593 ; CHECK-T1-NEXT:    ldrsh r0, [r0, r1]
594 ; CHECK-T1-NEXT:    bx lr
596 ; CHECK-T2-LABEL: ldrsh_ri_negative:
597 ; CHECK-T2:       @ %bb.0: @ %entry
598 ; CHECK-T2-NEXT:    ldrsh r0, [r0, #-1]
599 ; CHECK-T2-NEXT:    bx lr
600 entry:
601   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
602   %0 = bitcast i8* %add.ptr to i16*
603   %1 = load i16, i16* %0, align 2
604   %conv = sext i16 %1 to i32
605   ret i32 %conv
608 define i32 @ldrb_ri_negative(i8* %p) {
609 ; CHECK-T1-LABEL: ldrb_ri_negative:
610 ; CHECK-T1:       @ %bb.0: @ %entry
611 ; CHECK-T1-NEXT:    subs r0, r0, #1
612 ; CHECK-T1-NEXT:    ldrb r0, [r0]
613 ; CHECK-T1-NEXT:    bx lr
615 ; CHECK-T2-LABEL: ldrb_ri_negative:
616 ; CHECK-T2:       @ %bb.0: @ %entry
617 ; CHECK-T2-NEXT:    ldrb r0, [r0, #-1]
618 ; CHECK-T2-NEXT:    bx lr
619 entry:
620   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
621   %0 = load i8, i8* %add.ptr, align 1
622   %conv = zext i8 %0 to i32
623   ret i32 %conv
626 define i32 @ldrh_ri_negative(i8* %p) {
627 ; CHECK-T1-LABEL: ldrh_ri_negative:
628 ; CHECK-T1:       @ %bb.0: @ %entry
629 ; CHECK-T1-NEXT:    subs r0, r0, #1
630 ; CHECK-T1-NEXT:    ldrh r0, [r0]
631 ; CHECK-T1-NEXT:    bx lr
633 ; CHECK-T2-LABEL: ldrh_ri_negative:
634 ; CHECK-T2:       @ %bb.0: @ %entry
635 ; CHECK-T2-NEXT:    ldrh r0, [r0, #-1]
636 ; CHECK-T2-NEXT:    bx lr
637 entry:
638   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
639   %0 = bitcast i8* %add.ptr to i16*
640   %1 = load i16, i16* %0, align 2
641   %conv = zext i16 %1 to i32
642   ret i32 %conv
645 define i32 @ldr_ri_negative(i8* %p) {
646 ; CHECK-T1-LABEL: ldr_ri_negative:
647 ; CHECK-T1:       @ %bb.0: @ %entry
648 ; CHECK-T1-NEXT:    subs r0, r0, #1
649 ; CHECK-T1-NEXT:    ldr r0, [r0]
650 ; CHECK-T1-NEXT:    bx lr
652 ; CHECK-T2-LABEL: ldr_ri_negative:
653 ; CHECK-T2:       @ %bb.0: @ %entry
654 ; CHECK-T2-NEXT:    ldr r0, [r0, #-1]
655 ; CHECK-T2-NEXT:    bx lr
656 entry:
657   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
658   %0 = bitcast i8* %add.ptr to i32*
659   %1 = load i32, i32* %0, align 4
660   ret i32 %1
663 define void @strb_ri_negative(i8* %p, i32 %x) {
664 ; CHECK-T1-LABEL: strb_ri_negative:
665 ; CHECK-T1:       @ %bb.0: @ %entry
666 ; CHECK-T1-NEXT:    subs r0, r0, #1
667 ; CHECK-T1-NEXT:    strb r1, [r0]
668 ; CHECK-T1-NEXT:    bx lr
670 ; CHECK-T2-LABEL: strb_ri_negative:
671 ; CHECK-T2:       @ %bb.0: @ %entry
672 ; CHECK-T2-NEXT:    strb r1, [r0, #-1]
673 ; CHECK-T2-NEXT:    bx lr
674 entry:
675   %conv = trunc i32 %x to i8
676   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
677   store i8 %conv, i8* %add.ptr, align 1
678   ret void
681 define void @strh_ri_negative(i8* %p, i32 %x) {
682 ; CHECK-T1-LABEL: strh_ri_negative:
683 ; CHECK-T1:       @ %bb.0: @ %entry
684 ; CHECK-T1-NEXT:    subs r0, r0, #1
685 ; CHECK-T1-NEXT:    strh r1, [r0]
686 ; CHECK-T1-NEXT:    bx lr
688 ; CHECK-T2-LABEL: strh_ri_negative:
689 ; CHECK-T2:       @ %bb.0: @ %entry
690 ; CHECK-T2-NEXT:    strh r1, [r0, #-1]
691 ; CHECK-T2-NEXT:    bx lr
692 entry:
693   %conv = trunc i32 %x to i16
694   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
695   %0 = bitcast i8* %add.ptr to i16*
696   store i16 %conv, i16* %0, align 2
697   ret void
700 define void @str_ri_negative(i8* %p, i32 %x) {
701 ; CHECK-T1-LABEL: str_ri_negative:
702 ; CHECK-T1:       @ %bb.0: @ %entry
703 ; CHECK-T1-NEXT:    subs r0, r0, #1
704 ; CHECK-T1-NEXT:    str r1, [r0]
705 ; CHECK-T1-NEXT:    bx lr
707 ; CHECK-T2-LABEL: str_ri_negative:
708 ; CHECK-T2:       @ %bb.0: @ %entry
709 ; CHECK-T2-NEXT:    str r1, [r0, #-1]
710 ; CHECK-T2-NEXT:    bx lr
711 entry:
712   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -1
713   %0 = bitcast i8* %add.ptr to i32*
714   store i32 %x, i32* %0, align 4
715   ret void
719 ; Negative 255 offset
721 define i32 @ldrsb_ri_negative255(i8* %p) {
722 ; CHECK-T1-LABEL: ldrsb_ri_negative255:
723 ; CHECK-T1:       @ %bb.0: @ %entry
724 ; CHECK-T1-NEXT:    movs r1, #254
725 ; CHECK-T1-NEXT:    mvns r1, r1
726 ; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
727 ; CHECK-T1-NEXT:    bx lr
729 ; CHECK-T2-LABEL: ldrsb_ri_negative255:
730 ; CHECK-T2:       @ %bb.0: @ %entry
731 ; CHECK-T2-NEXT:    ldrsb r0, [r0, #-255]
732 ; CHECK-T2-NEXT:    bx lr
733 entry:
734   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
735   %0 = load i8, i8* %add.ptr, align 1
736   %conv = sext i8 %0 to i32
737   ret i32 %conv
740 define i32 @ldrsh_ri_negative255(i8* %p) {
741 ; CHECK-T1-LABEL: ldrsh_ri_negative255:
742 ; CHECK-T1:       @ %bb.0: @ %entry
743 ; CHECK-T1-NEXT:    movs r1, #254
744 ; CHECK-T1-NEXT:    mvns r1, r1
745 ; CHECK-T1-NEXT:    ldrsh r0, [r0, r1]
746 ; CHECK-T1-NEXT:    bx lr
748 ; CHECK-T2-LABEL: ldrsh_ri_negative255:
749 ; CHECK-T2:       @ %bb.0: @ %entry
750 ; CHECK-T2-NEXT:    ldrsh r0, [r0, #-255]
751 ; CHECK-T2-NEXT:    bx lr
752 entry:
753   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
754   %0 = bitcast i8* %add.ptr to i16*
755   %1 = load i16, i16* %0, align 2
756   %conv = sext i16 %1 to i32
757   ret i32 %conv
760 define i32 @ldrb_ri_negative255(i8* %p) {
761 ; CHECK-T1-LABEL: ldrb_ri_negative255:
762 ; CHECK-T1:       @ %bb.0: @ %entry
763 ; CHECK-T1-NEXT:    subs r0, #255
764 ; CHECK-T1-NEXT:    ldrb r0, [r0]
765 ; CHECK-T1-NEXT:    bx lr
767 ; CHECK-T2-LABEL: ldrb_ri_negative255:
768 ; CHECK-T2:       @ %bb.0: @ %entry
769 ; CHECK-T2-NEXT:    ldrb r0, [r0, #-255]
770 ; CHECK-T2-NEXT:    bx lr
771 entry:
772   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
773   %0 = load i8, i8* %add.ptr, align 1
774   %conv = zext i8 %0 to i32
775   ret i32 %conv
778 define i32 @ldrh_ri_negative255(i8* %p) {
779 ; CHECK-T1-LABEL: ldrh_ri_negative255:
780 ; CHECK-T1:       @ %bb.0: @ %entry
781 ; CHECK-T1-NEXT:    subs r0, #255
782 ; CHECK-T1-NEXT:    ldrh r0, [r0]
783 ; CHECK-T1-NEXT:    bx lr
785 ; CHECK-T2-LABEL: ldrh_ri_negative255:
786 ; CHECK-T2:       @ %bb.0: @ %entry
787 ; CHECK-T2-NEXT:    ldrh r0, [r0, #-255]
788 ; CHECK-T2-NEXT:    bx lr
789 entry:
790   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
791   %0 = bitcast i8* %add.ptr to i16*
792   %1 = load i16, i16* %0, align 2
793   %conv = zext i16 %1 to i32
794   ret i32 %conv
797 define i32 @ldr_ri_negative255(i8* %p) {
798 ; CHECK-T1-LABEL: ldr_ri_negative255:
799 ; CHECK-T1:       @ %bb.0: @ %entry
800 ; CHECK-T1-NEXT:    subs r0, #255
801 ; CHECK-T1-NEXT:    ldr r0, [r0]
802 ; CHECK-T1-NEXT:    bx lr
804 ; CHECK-T2-LABEL: ldr_ri_negative255:
805 ; CHECK-T2:       @ %bb.0: @ %entry
806 ; CHECK-T2-NEXT:    ldr r0, [r0, #-255]
807 ; CHECK-T2-NEXT:    bx lr
808 entry:
809   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
810   %0 = bitcast i8* %add.ptr to i32*
811   %1 = load i32, i32* %0, align 4
812   ret i32 %1
815 define void @strb_ri_negative255(i8* %p, i32 %x) {
816 ; CHECK-T1-LABEL: strb_ri_negative255:
817 ; CHECK-T1:       @ %bb.0: @ %entry
818 ; CHECK-T1-NEXT:    subs r0, #255
819 ; CHECK-T1-NEXT:    strb r1, [r0]
820 ; CHECK-T1-NEXT:    bx lr
822 ; CHECK-T2-LABEL: strb_ri_negative255:
823 ; CHECK-T2:       @ %bb.0: @ %entry
824 ; CHECK-T2-NEXT:    strb r1, [r0, #-255]
825 ; CHECK-T2-NEXT:    bx lr
826 entry:
827   %conv = trunc i32 %x to i8
828   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
829   store i8 %conv, i8* %add.ptr, align 1
830   ret void
833 define void @strh_ri_negative255(i8* %p, i32 %x) {
834 ; CHECK-T1-LABEL: strh_ri_negative255:
835 ; CHECK-T1:       @ %bb.0: @ %entry
836 ; CHECK-T1-NEXT:    subs r0, #255
837 ; CHECK-T1-NEXT:    strh r1, [r0]
838 ; CHECK-T1-NEXT:    bx lr
840 ; CHECK-T2-LABEL: strh_ri_negative255:
841 ; CHECK-T2:       @ %bb.0: @ %entry
842 ; CHECK-T2-NEXT:    strh r1, [r0, #-255]
843 ; CHECK-T2-NEXT:    bx lr
844 entry:
845   %conv = trunc i32 %x to i16
846   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
847   %0 = bitcast i8* %add.ptr to i16*
848   store i16 %conv, i16* %0, align 2
849   ret void
852 define void @str_ri_negative255(i8* %p, i32 %x) {
853 ; CHECK-T1-LABEL: str_ri_negative255:
854 ; CHECK-T1:       @ %bb.0: @ %entry
855 ; CHECK-T1-NEXT:    subs r0, #255
856 ; CHECK-T1-NEXT:    str r1, [r0]
857 ; CHECK-T1-NEXT:    bx lr
859 ; CHECK-T2-LABEL: str_ri_negative255:
860 ; CHECK-T2:       @ %bb.0: @ %entry
861 ; CHECK-T2-NEXT:    str r1, [r0, #-255]
862 ; CHECK-T2-NEXT:    bx lr
863 entry:
864   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -255
865   %0 = bitcast i8* %add.ptr to i32*
866   store i32 %x, i32* %0, align 4
867   ret void
871 ; Negative 256 offset
873 define i32 @ldrsb_ri_negative256(i8* %p) {
874 ; CHECK-T1-LABEL: ldrsb_ri_negative256:
875 ; CHECK-T1:       @ %bb.0: @ %entry
876 ; CHECK-T1-NEXT:    movs r1, #255
877 ; CHECK-T1-NEXT:    mvns r1, r1
878 ; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
879 ; CHECK-T1-NEXT:    bx lr
881 ; CHECK-T2-LABEL: ldrsb_ri_negative256:
882 ; CHECK-T2:       @ %bb.0: @ %entry
883 ; CHECK-T2-NEXT:    mvn r1, #255
884 ; CHECK-T2-NEXT:    ldrsb r0, [r0, r1]
885 ; CHECK-T2-NEXT:    bx lr
886 entry:
887   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
888   %0 = load i8, i8* %add.ptr, align 1
889   %conv = sext i8 %0 to i32
890   ret i32 %conv
893 define i32 @ldrsh_ri_negative256(i8* %p) {
894 ; CHECK-T1-LABEL: ldrsh_ri_negative256:
895 ; CHECK-T1:       @ %bb.0: @ %entry
896 ; CHECK-T1-NEXT:    movs r1, #255
897 ; CHECK-T1-NEXT:    mvns r1, r1
898 ; CHECK-T1-NEXT:    ldrsh r0, [r0, r1]
899 ; CHECK-T1-NEXT:    bx lr
901 ; CHECK-T2-LABEL: ldrsh_ri_negative256:
902 ; CHECK-T2:       @ %bb.0: @ %entry
903 ; CHECK-T2-NEXT:    mvn r1, #255
904 ; CHECK-T2-NEXT:    ldrsh r0, [r0, r1]
905 ; CHECK-T2-NEXT:    bx lr
906 entry:
907   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
908   %0 = bitcast i8* %add.ptr to i16*
909   %1 = load i16, i16* %0, align 2
910   %conv = sext i16 %1 to i32
911   ret i32 %conv
914 define i32 @ldrb_ri_negative256(i8* %p) {
915 ; CHECK-T1-LABEL: ldrb_ri_negative256:
916 ; CHECK-T1:       @ %bb.0: @ %entry
917 ; CHECK-T1-NEXT:    movs r1, #255
918 ; CHECK-T1-NEXT:    mvns r1, r1
919 ; CHECK-T1-NEXT:    ldrb r0, [r0, r1]
920 ; CHECK-T1-NEXT:    bx lr
922 ; CHECK-T2-LABEL: ldrb_ri_negative256:
923 ; CHECK-T2:       @ %bb.0: @ %entry
924 ; CHECK-T2-NEXT:    mvn r1, #255
925 ; CHECK-T2-NEXT:    ldrb r0, [r0, r1]
926 ; CHECK-T2-NEXT:    bx lr
927 entry:
928   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
929   %0 = load i8, i8* %add.ptr, align 1
930   %conv = zext i8 %0 to i32
931   ret i32 %conv
934 define i32 @ldrh_ri_negative256(i8* %p) {
935 ; CHECK-T1-LABEL: ldrh_ri_negative256:
936 ; CHECK-T1:       @ %bb.0: @ %entry
937 ; CHECK-T1-NEXT:    movs r1, #255
938 ; CHECK-T1-NEXT:    mvns r1, r1
939 ; CHECK-T1-NEXT:    ldrh r0, [r0, r1]
940 ; CHECK-T1-NEXT:    bx lr
942 ; CHECK-T2-LABEL: ldrh_ri_negative256:
943 ; CHECK-T2:       @ %bb.0: @ %entry
944 ; CHECK-T2-NEXT:    mvn r1, #255
945 ; CHECK-T2-NEXT:    ldrh r0, [r0, r1]
946 ; CHECK-T2-NEXT:    bx lr
947 entry:
948   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
949   %0 = bitcast i8* %add.ptr to i16*
950   %1 = load i16, i16* %0, align 2
951   %conv = zext i16 %1 to i32
952   ret i32 %conv
955 define i32 @ldr_ri_negative256(i8* %p) {
956 ; CHECK-T1-LABEL: ldr_ri_negative256:
957 ; CHECK-T1:       @ %bb.0: @ %entry
958 ; CHECK-T1-NEXT:    movs r1, #255
959 ; CHECK-T1-NEXT:    mvns r1, r1
960 ; CHECK-T1-NEXT:    ldr r0, [r0, r1]
961 ; CHECK-T1-NEXT:    bx lr
963 ; CHECK-T2-LABEL: ldr_ri_negative256:
964 ; CHECK-T2:       @ %bb.0: @ %entry
965 ; CHECK-T2-NEXT:    mvn r1, #255
966 ; CHECK-T2-NEXT:    ldr r0, [r0, r1]
967 ; CHECK-T2-NEXT:    bx lr
968 entry:
969   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
970   %0 = bitcast i8* %add.ptr to i32*
971   %1 = load i32, i32* %0, align 4
972   ret i32 %1
975 define void @strb_ri_negative256(i8* %p, i32 %x) {
976 ; CHECK-T1-LABEL: strb_ri_negative256:
977 ; CHECK-T1:       @ %bb.0: @ %entry
978 ; CHECK-T1-NEXT:    movs r2, #255
979 ; CHECK-T1-NEXT:    mvns r2, r2
980 ; CHECK-T1-NEXT:    strb r1, [r0, r2]
981 ; CHECK-T1-NEXT:    bx lr
983 ; CHECK-T2-LABEL: strb_ri_negative256:
984 ; CHECK-T2:       @ %bb.0: @ %entry
985 ; CHECK-T2-NEXT:    mvn r2, #255
986 ; CHECK-T2-NEXT:    strb r1, [r0, r2]
987 ; CHECK-T2-NEXT:    bx lr
988 entry:
989   %conv = trunc i32 %x to i8
990   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
991   store i8 %conv, i8* %add.ptr, align 1
992   ret void
995 define void @strh_ri_negative256(i8* %p, i32 %x) {
996 ; CHECK-T1-LABEL: strh_ri_negative256:
997 ; CHECK-T1:       @ %bb.0: @ %entry
998 ; CHECK-T1-NEXT:    movs r2, #255
999 ; CHECK-T1-NEXT:    mvns r2, r2
1000 ; CHECK-T1-NEXT:    strh r1, [r0, r2]
1001 ; CHECK-T1-NEXT:    bx lr
1003 ; CHECK-T2-LABEL: strh_ri_negative256:
1004 ; CHECK-T2:       @ %bb.0: @ %entry
1005 ; CHECK-T2-NEXT:    mvn r2, #255
1006 ; CHECK-T2-NEXT:    strh r1, [r0, r2]
1007 ; CHECK-T2-NEXT:    bx lr
1008 entry:
1009   %conv = trunc i32 %x to i16
1010   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
1011   %0 = bitcast i8* %add.ptr to i16*
1012   store i16 %conv, i16* %0, align 2
1013   ret void
1016 define void @str_ri_negative256(i8* %p, i32 %x) {
1017 ; CHECK-T1-LABEL: str_ri_negative256:
1018 ; CHECK-T1:       @ %bb.0: @ %entry
1019 ; CHECK-T1-NEXT:    movs r2, #255
1020 ; CHECK-T1-NEXT:    mvns r2, r2
1021 ; CHECK-T1-NEXT:    str r1, [r0, r2]
1022 ; CHECK-T1-NEXT:    bx lr
1024 ; CHECK-T2-LABEL: str_ri_negative256:
1025 ; CHECK-T2:       @ %bb.0: @ %entry
1026 ; CHECK-T2-NEXT:    mvn r2, #255
1027 ; CHECK-T2-NEXT:    str r1, [r0, r2]
1028 ; CHECK-T2-NEXT:    bx lr
1029 entry:
1030   %add.ptr = getelementptr inbounds i8, i8* %p, i32 -256
1031   %0 = bitcast i8* %add.ptr to i32*
1032   store i32 %x, i32* %0, align 4
1033   ret void