xref: /llvm-project/llvm/test/CodeGen/ARM/load.ll (revision bed1c7f061aa12417aa081e334afdba45767b938)
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
3
4
5; Register offset
6
7; CHECK-LABEL: ldrsb_rr
8; CHECK:    ldrsb   r0, [r0, r1]
9define i32 @ldrsb_rr(ptr %p, i32 %n) {
10entry:
11  %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n
12  %0 = load i8, ptr %arrayidx, align 1
13  %conv = sext i8 %0 to i32
14  ret i32 %conv
15}
16
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]
21define i32 @ldrsh_rr(ptr %p, i32 %n) {
22entry:
23  %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n
24  %0 = load i16, ptr %arrayidx, align 2
25  %conv = sext i16 %0 to i32
26  ret i32 %conv
27}
28
29; CHECK-LABEL: ldrb_rr
30; CHECK:    ldrb r0, [r0, r1]
31define i32 @ldrb_rr(ptr %p, i32 %n) {
32entry:
33  %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n
34  %0 = load i8, ptr %arrayidx, align 1
35  %conv = zext i8 %0 to i32
36  ret i32 %conv
37}
38
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]
43define i32 @ldrh_rr(ptr %p, i32 %n) {
44entry:
45  %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n
46  %0 = load i16, ptr %arrayidx, align 2
47  %conv = zext i16 %0 to i32
48  ret i32 %conv
49}
50
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]
55define i32 @ldr_rr(ptr %p, i32 %n) {
56entry:
57  %arrayidx = getelementptr inbounds i32, ptr %p, i32 %n
58  %0 = load i32, ptr %arrayidx, align 4
59  ret i32 %0
60}
61
62; CHECK-LABEL: strb_rr
63; CHECK:    strb    r2, [r0, r1]
64define void @strb_rr(ptr %p, i32 %n, i32 %x) {
65entry:
66  %conv = trunc i32 %x to i8
67  %arrayidx = getelementptr inbounds i8, ptr %p, i32 %n
68  store i8 %conv, ptr %arrayidx, align 1
69  ret void
70}
71
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]
76define void @strh_rr(ptr %p, i32 %n, i32 %x) {
77entry:
78  %conv = trunc i32 %x to i16
79  %arrayidx = getelementptr inbounds i16, ptr %p, i32 %n
80  store i16 %conv, ptr %arrayidx, align 2
81  ret void
82}
83
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]
88define void @str_rr(ptr %p, i32 %n, i32 %x) {
89entry:
90  %arrayidx = getelementptr inbounds i32, ptr %p, i32 %n
91  store i32 %x, ptr %arrayidx, align 4
92  ret void
93}
94
95
96; Immediate offset of zero
97
98; CHECK-LABEL: ldrsb_ri_zero
99; CHECK-T1: movs    r1, #0
100; CHECK-T1: ldrsb   r0, [r0, r1]
101; CHECK-T2: ldrsb.w r0, [r0]
102define i32 @ldrsb_ri_zero(ptr %p) {
103entry:
104  %0 = load i8, ptr %p, align 1
105  %conv = sext i8 %0 to i32
106  ret i32 %conv
107}
108
109; CHECK-LABEL: ldrsh_ri_zero
110; CHECK-T1: movs    r1, #0
111; CHECK-T1: ldrsh   r0, [r0, r1]
112; CHECK-T2: ldrsh.w r0, [r0]
113define i32 @ldrsh_ri_zero(ptr %p) {
114entry:
115  %0 = load i16, ptr %p, align 2
116  %conv = sext i16 %0 to i32
117  ret i32 %conv
118}
119
120; CHECK-LABEL: ldrb_ri_zero
121; CHECK:    ldrb    r0, [r0]
122define i32 @ldrb_ri_zero(ptr %p) {
123entry:
124  %0 = load i8, ptr %p, align 1
125  %conv = zext i8 %0 to i32
126  ret i32 %conv
127}
128
129; CHECK-LABEL: ldrh_ri_zero
130; CHECK:    ldrh    r0, [r0]
131define i32 @ldrh_ri_zero(ptr %p) {
132entry:
133  %0 = load i16, ptr %p, align 2
134  %conv = zext i16 %0 to i32
135  ret i32 %conv
136}
137
138; CHECK-LABEL: ldr_ri_zero
139; CHECK:    ldr     r0, [r0]
140define i32 @ldr_ri_zero(ptr %p) {
141entry:
142  %0 = load i32, ptr %p, align 4
143  ret i32 %0
144}
145
146; CHECK-LABEL: strb_ri_zero
147; CHECK:    strb    r1, [r0]
148define void @strb_ri_zero(ptr %p, i32 %x) {
149entry:
150  %conv = trunc i32 %x to i8
151  store i8 %conv, ptr %p, align 1
152  ret void
153}
154
155; CHECK-LABEL: strh_ri_zero
156; CHECK:    strh    r1, [r0]
157define void @strh_ri_zero(ptr %p, i32 %x) {
158entry:
159  %conv = trunc i32 %x to i16
160  store i16 %conv, ptr %p, align 2
161  ret void
162}
163
164; CHECK-LABEL: str_ri_zero
165; CHECK:    str     r1, [r0]
166define void @str_ri_zero(ptr %p, i32 %x) {
167entry:
168  store i32 %x, ptr %p, align 4
169  ret void
170}
171
172
173; Maximum Thumb-1 immediate offset
174
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]
179define i32 @ldrsb_ri_t1_max(ptr %p) {
180entry:
181  %arrayidx = getelementptr inbounds i8, ptr %p, i32 31
182  %0 = load i8, ptr %arrayidx, align 1
183  %conv = sext i8 %0 to i32
184  ret i32 %conv
185}
186
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]
191define i32 @ldrsh_ri_t1_max(ptr %p) {
192entry:
193  %arrayidx = getelementptr inbounds i16, ptr %p, i32 31
194  %0 = load i16, ptr %arrayidx, align 2
195  %conv = sext i16 %0 to i32
196  ret i32 %conv
197}
198
199; CHECK-LABEL: ldrb_ri_t1_max
200; CHECK:    ldrb    r0, [r0, #31]
201define i32 @ldrb_ri_t1_max(ptr %p) {
202entry:
203  %arrayidx = getelementptr inbounds i8, ptr %p, i32 31
204  %0 = load i8, ptr %arrayidx, align 1
205  %conv = zext i8 %0 to i32
206  ret i32 %conv
207}
208
209; CHECK-LABEL: ldrh_ri_t1_max
210; CHECK:    ldrh    r0, [r0, #62]
211define i32 @ldrh_ri_t1_max(ptr %p) {
212entry:
213  %arrayidx = getelementptr inbounds i16, ptr %p, i32 31
214  %0 = load i16, ptr %arrayidx, align 2
215  %conv = zext i16 %0 to i32
216  ret i32 %conv
217}
218
219; CHECK-LABEL: ldr_ri_t1_max
220; CHECK:    ldr     r0, [r0, #124]
221define i32 @ldr_ri_t1_max(ptr %p) {
222entry:
223  %arrayidx = getelementptr inbounds i32, ptr %p, i32 31
224  %0 = load i32, ptr %arrayidx, align 4
225  ret i32 %0
226}
227
228; CHECK-LABEL: strb_ri_t1_max
229; CHECK:    strb    r1, [r0, #31]
230define void @strb_ri_t1_max(ptr %p, i32 %x) {
231entry:
232  %conv = trunc i32 %x to i8
233  %arrayidx = getelementptr inbounds i8, ptr %p, i32 31
234  store i8 %conv, ptr %arrayidx, align 1
235  ret void
236}
237
238; CHECK-LABEL: strh_ri_t1_max
239; CHECK:    strh    r1, [r0, #62]
240define void @strh_ri_t1_max(ptr %p, i32 %x) {
241entry:
242  %conv = trunc i32 %x to i16
243  %arrayidx = getelementptr inbounds i16, ptr %p, i32 31
244  store i16 %conv, ptr %arrayidx, align 2
245  ret void
246}
247
248; CHECK-LABEL: str_ri_t1_max
249; CHECK:    str     r1, [r0, #124]
250define void @str_ri_t1_max(ptr %p, i32 %x) {
251entry:
252  %arrayidx = getelementptr inbounds i32, ptr %p, i32 31
253  store i32 %x, ptr %arrayidx, align 4
254  ret void
255}
256
257
258; One past maximum Thumb-1 immediate offset
259
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]
264define i32 @ldrsb_ri_t1_too_big(ptr %p) {
265entry:
266  %arrayidx = getelementptr inbounds i8, ptr %p, i32 32
267  %0 = load i8, ptr %arrayidx, align 1
268  %conv = sext i8 %0 to i32
269  ret i32 %conv
270}
271
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]
276define i32 @ldrsh_ri_t1_too_big(ptr %p) {
277entry:
278  %arrayidx = getelementptr inbounds i16, ptr %p, i32 32
279  %0 = load i16, ptr %arrayidx, align 2
280  %conv = sext i16 %0 to i32
281  ret i32 %conv
282}
283
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]
288define i32 @ldrb_ri_t1_too_big(ptr %p) {
289entry:
290  %arrayidx = getelementptr inbounds i8, ptr %p, i32 32
291  %0 = load i8, ptr %arrayidx, align 1
292  %conv = zext i8 %0 to i32
293  ret i32 %conv
294}
295
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]
300define i32 @ldrh_ri_t1_too_big(ptr %p) {
301entry:
302  %arrayidx = getelementptr inbounds i16, ptr %p, i32 32
303  %0 = load i16, ptr %arrayidx, align 2
304  %conv = zext i16 %0 to i32
305  ret i32 %conv
306}
307
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]
312define i32 @ldr_ri_t1_too_big(ptr %p) {
313entry:
314  %arrayidx = getelementptr inbounds i32, ptr %p, i32 32
315  %0 = load i32, ptr %arrayidx, align 4
316  ret i32 %0
317}
318
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]
323define void @strb_ri_t1_too_big(ptr %p, i32 %x) {
324entry:
325  %conv = trunc i32 %x to i8
326  %arrayidx = getelementptr inbounds i8, ptr %p, i32 32
327  store i8 %conv, ptr %arrayidx, align 1
328  ret void
329}
330
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]
335define void @strh_ri_t1_too_big(ptr %p, i32 %x) {
336entry:
337  %conv = trunc i32 %x to i16
338  %arrayidx = getelementptr inbounds i16, ptr %p, i32 32
339  store i16 %conv, ptr %arrayidx, align 2
340  ret void
341}
342
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]
347define void @str_ri_t1_too_big(ptr %p, i32 %x) {
348entry:
349  %arrayidx = getelementptr inbounds i32, ptr %p, i32 32
350  store i32 %x, ptr %arrayidx, align 4
351  ret void
352}
353
354
355; Maximum Thumb-2 immediate offset
356
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]
361define i32 @ldrsb_ri_t2_max(ptr %p) {
362entry:
363  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
364  %0 = load i8, ptr %add.ptr, align 1
365  %conv = sext i8 %0 to i32
366  ret i32 %conv
367}
368
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]
373define i32 @ldrsh_ri_t2_max(ptr %p) {
374entry:
375  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
376  %0 = load i16, ptr %add.ptr, align 2
377  %conv = sext i16 %0 to i32
378  ret i32 %conv
379}
380
381; CHECK-LABEL: ldrb_ri_t2_max
382; CHECK-T1: ldr     r1, .LCP
383; CHECK-T1: ldrb    r0, [r0, r1]
384; CHECK-T2: ldrb.w  r0, [r0, #4095]
385define i32 @ldrb_ri_t2_max(ptr %p) {
386entry:
387  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
388  %0 = load i8, ptr %add.ptr, align 1
389  %conv = zext i8 %0 to i32
390  ret i32 %conv
391}
392
393; CHECK-LABEL: ldrh_ri_t2_max
394; CHECK-T1: ldr     r1, .LCP
395; CHECK-T1: ldrh    r0, [r0, r1]
396; CHECK-T2: ldrh.w  r0, [r0, #4095]
397define i32 @ldrh_ri_t2_max(ptr %p) {
398entry:
399  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
400  %0 = load i16, ptr %add.ptr, align 2
401  %conv = zext i16 %0 to i32
402  ret i32 %conv
403}
404
405; CHECK-LABEL: ldr_ri_t2_max
406; CHECK-T1: ldr     r1, .LCP
407; CHECK-T1: ldr     r0, [r0, r1]
408; CHECK-T2: ldr.w   r0, [r0, #4095]
409define i32 @ldr_ri_t2_max(ptr %p) {
410entry:
411  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
412  %0 = load i32, ptr %add.ptr, align 4
413  ret i32 %0
414}
415
416; CHECK-LABEL: strb_ri_t2_max
417; CHECK-T1: ldr     r2, .LCP
418; CHECK-T1: strb    r1, [r0, r2]
419; CHECK-T2: strb.w  r1, [r0, #4095]
420define void @strb_ri_t2_max(ptr %p, i32 %x) {
421entry:
422  %conv = trunc i32 %x to i8
423  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
424  store i8 %conv, ptr %add.ptr, align 1
425  ret void
426}
427
428; CHECK-LABEL: strh_ri_t2_max
429; CHECK-T1: ldr     r2, .LCP
430; CHECK-T1: strh    r1, [r0, r2]
431; CHECK-T2: strh.w  r1, [r0, #4095]
432define void @strh_ri_t2_max(ptr %p, i32 %x) {
433entry:
434  %conv = trunc i32 %x to i16
435  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
436  store i16 %conv, ptr %add.ptr, align 2
437  ret void
438}
439
440; CHECK-LABEL: str_ri_t2_max
441; CHECK-T1: ldr     r2, .LCP
442; CHECK-T1: str     r1, [r0, r2]
443; CHECK-T2: str.w   r1, [r0, #4095]
444define void @str_ri_t2_max(ptr %p, i32 %x) {
445entry:
446  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4095
447  store i32 %x, ptr %add.ptr, align 4
448  ret void
449}
450
451
452; One past maximum Thumb-2 immediate offset
453
454; CHECK-LABEL: ldrsb_ri_t2_too_big
455; CHECK-T1: movs    r1, #1
456; CHECK-T1: lsls    r1, r1, #12
457; CHECK-T2: mov.w   r1, #4096
458; CHECK:    ldrsb   r0, [r0, r1]
459define i32 @ldrsb_ri_t2_too_big(ptr %p) {
460entry:
461  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
462  %0 = load i8, ptr %add.ptr, align 1
463  %conv = sext i8 %0 to i32
464  ret i32 %conv
465}
466
467; CHECK-LABEL: ldrsh_ri_t2_too_big
468; CHECK-T1: movs    r1, #1
469; CHECK-T1: lsls    r1, r1, #12
470; CHECK-T2: mov.w   r1, #4096
471; CHECK:    ldrsh   r0, [r0, r1]
472define i32 @ldrsh_ri_t2_too_big(ptr %p) {
473entry:
474  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
475  %0 = load i16, ptr %add.ptr, align 2
476  %conv = sext i16 %0 to i32
477  ret i32 %conv
478}
479
480; CHECK-LABEL: ldrb_ri_t2_too_big
481; CHECK-T1: movs    r1, #1
482; CHECK-T1: lsls    r1, r1, #12
483; CHECK-T2: mov.w   r1, #4096
484; CHECK:    ldrb    r0, [r0, r1]
485define i32 @ldrb_ri_t2_too_big(ptr %p) {
486entry:
487  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
488  %0 = load i8, ptr %add.ptr, align 1
489  %conv = zext i8 %0 to i32
490  ret i32 %conv
491}
492
493; CHECK-LABEL: ldrh_ri_t2_too_big
494; CHECK-T1: movs    r1, #1
495; CHECK-T1: lsls    r1, r1, #12
496; CHECK-T2: mov.w   r1, #4096
497; CHECK:    ldrh    r0, [r0, r1]
498define i32 @ldrh_ri_t2_too_big(ptr %p) {
499entry:
500  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
501  %0 = load i16, ptr %add.ptr, align 2
502  %conv = zext i16 %0 to i32
503  ret i32 %conv
504}
505
506; CHECK-LABEL: ldr_ri_t2_too_big
507; CHECK-T1: movs    r1, #1
508; CHECK-T1: lsls    r1, r1, #12
509; CHECK-T2: mov.w   r1, #4096
510; CHECK:    ldr     r0, [r0, r1]
511define i32 @ldr_ri_t2_too_big(ptr %p) {
512entry:
513  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
514  %0 = load i32, ptr %add.ptr, align 4
515  ret i32 %0
516}
517
518; CHECK-LABEL: strb_ri_t2_too_big
519; CHECK-T1: movs    r2, #1
520; CHECK-T1: lsls    r2, r2, #12
521; CHECK-T2: mov.w   r2, #4096
522; CHECK:    strb    r1, [r0, r2]
523define void @strb_ri_t2_too_big(ptr %p, i32 %x) {
524entry:
525  %conv = trunc i32 %x to i8
526  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
527  store i8 %conv, ptr %add.ptr, align 1
528  ret void
529}
530
531; CHECK-LABEL: strh_ri_t2_too_big
532; CHECK-T1: movs    r2, #1
533; CHECK-T1: lsls    r2, r2, #12
534; CHECK-T2: mov.w   r2, #4096
535; CHECK:    strh    r1, [r0, r2]
536define void @strh_ri_t2_too_big(ptr %p, i32 %x) {
537entry:
538  %conv = trunc i32 %x to i16
539  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
540  store i16 %conv, ptr %add.ptr, align 2
541  ret void
542}
543
544; CHECK-LABEL: str_ri_t2_too_big
545; CHECK-T1: movs    r2, #1
546; CHECK-T1: lsls    r2, r2, #12
547; CHECK-T2: mov.w   r2, #4096
548; CHECK:    str     r1, [r0, r2]
549define void @str_ri_t2_too_big(ptr %p, i32 %x) {
550entry:
551  %add.ptr = getelementptr inbounds i8, ptr %p, i32 4096
552  store i32 %x, ptr %add.ptr, align 4
553  ret void
554}
555
556
557; Negative offset
558
559define i32 @ldrsb_ri_negative(ptr %p) {
560; CHECK-T1-LABEL: ldrsb_ri_negative:
561; CHECK-T1:       @ %bb.0: @ %entry
562; CHECK-T1-NEXT:    movs r1, #0
563; CHECK-T1-NEXT:    mvns r1, r1
564; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
565; CHECK-T1-NEXT:    bx lr
566;
567; CHECK-T2-LABEL: ldrsb_ri_negative:
568; CHECK-T2:       @ %bb.0: @ %entry
569; CHECK-T2-NEXT:    ldrsb r0, [r0, #-1]
570; CHECK-T2-NEXT:    bx lr
571entry:
572  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
573  %0 = load i8, ptr %add.ptr, align 1
574  %conv = sext i8 %0 to i32
575  ret i32 %conv
576}
577
578define i32 @ldrsh_ri_negative(ptr %p) {
579; CHECK-T1-LABEL: ldrsh_ri_negative:
580; CHECK-T1:       @ %bb.0: @ %entry
581; CHECK-T1-NEXT:    movs r1, #0
582; CHECK-T1-NEXT:    mvns r1, r1
583; CHECK-T1-NEXT:    ldrsh r0, [r0, r1]
584; CHECK-T1-NEXT:    bx lr
585;
586; CHECK-T2-LABEL: ldrsh_ri_negative:
587; CHECK-T2:       @ %bb.0: @ %entry
588; CHECK-T2-NEXT:    ldrsh r0, [r0, #-1]
589; CHECK-T2-NEXT:    bx lr
590entry:
591  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
592  %0 = load i16, ptr %add.ptr, align 2
593  %conv = sext i16 %0 to i32
594  ret i32 %conv
595}
596
597define i32 @ldrb_ri_negative(ptr %p) {
598; CHECK-T1-LABEL: ldrb_ri_negative:
599; CHECK-T1:       @ %bb.0: @ %entry
600; CHECK-T1-NEXT:    subs r0, r0, #1
601; CHECK-T1-NEXT:    ldrb r0, [r0]
602; CHECK-T1-NEXT:    bx lr
603;
604; CHECK-T2-LABEL: ldrb_ri_negative:
605; CHECK-T2:       @ %bb.0: @ %entry
606; CHECK-T2-NEXT:    ldrb r0, [r0, #-1]
607; CHECK-T2-NEXT:    bx lr
608entry:
609  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
610  %0 = load i8, ptr %add.ptr, align 1
611  %conv = zext i8 %0 to i32
612  ret i32 %conv
613}
614
615define i32 @ldrh_ri_negative(ptr %p) {
616; CHECK-T1-LABEL: ldrh_ri_negative:
617; CHECK-T1:       @ %bb.0: @ %entry
618; CHECK-T1-NEXT:    subs r0, r0, #1
619; CHECK-T1-NEXT:    ldrh r0, [r0]
620; CHECK-T1-NEXT:    bx lr
621;
622; CHECK-T2-LABEL: ldrh_ri_negative:
623; CHECK-T2:       @ %bb.0: @ %entry
624; CHECK-T2-NEXT:    ldrh r0, [r0, #-1]
625; CHECK-T2-NEXT:    bx lr
626entry:
627  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
628  %0 = load i16, ptr %add.ptr, align 2
629  %conv = zext i16 %0 to i32
630  ret i32 %conv
631}
632
633define i32 @ldr_ri_negative(ptr %p) {
634; CHECK-T1-LABEL: ldr_ri_negative:
635; CHECK-T1:       @ %bb.0: @ %entry
636; CHECK-T1-NEXT:    subs r0, r0, #1
637; CHECK-T1-NEXT:    ldr r0, [r0]
638; CHECK-T1-NEXT:    bx lr
639;
640; CHECK-T2-LABEL: ldr_ri_negative:
641; CHECK-T2:       @ %bb.0: @ %entry
642; CHECK-T2-NEXT:    ldr r0, [r0, #-1]
643; CHECK-T2-NEXT:    bx lr
644entry:
645  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
646  %0 = load i32, ptr %add.ptr, align 4
647  ret i32 %0
648}
649
650define void @strb_ri_negative(ptr %p, i32 %x) {
651; CHECK-T1-LABEL: strb_ri_negative:
652; CHECK-T1:       @ %bb.0: @ %entry
653; CHECK-T1-NEXT:    subs r0, r0, #1
654; CHECK-T1-NEXT:    strb r1, [r0]
655; CHECK-T1-NEXT:    bx lr
656;
657; CHECK-T2-LABEL: strb_ri_negative:
658; CHECK-T2:       @ %bb.0: @ %entry
659; CHECK-T2-NEXT:    strb r1, [r0, #-1]
660; CHECK-T2-NEXT:    bx lr
661entry:
662  %conv = trunc i32 %x to i8
663  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
664  store i8 %conv, ptr %add.ptr, align 1
665  ret void
666}
667
668define void @strh_ri_negative(ptr %p, i32 %x) {
669; CHECK-T1-LABEL: strh_ri_negative:
670; CHECK-T1:       @ %bb.0: @ %entry
671; CHECK-T1-NEXT:    subs r0, r0, #1
672; CHECK-T1-NEXT:    strh r1, [r0]
673; CHECK-T1-NEXT:    bx lr
674;
675; CHECK-T2-LABEL: strh_ri_negative:
676; CHECK-T2:       @ %bb.0: @ %entry
677; CHECK-T2-NEXT:    strh r1, [r0, #-1]
678; CHECK-T2-NEXT:    bx lr
679entry:
680  %conv = trunc i32 %x to i16
681  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
682  store i16 %conv, ptr %add.ptr, align 2
683  ret void
684}
685
686define void @str_ri_negative(ptr %p, i32 %x) {
687; CHECK-T1-LABEL: str_ri_negative:
688; CHECK-T1:       @ %bb.0: @ %entry
689; CHECK-T1-NEXT:    subs r0, r0, #1
690; CHECK-T1-NEXT:    str r1, [r0]
691; CHECK-T1-NEXT:    bx lr
692;
693; CHECK-T2-LABEL: str_ri_negative:
694; CHECK-T2:       @ %bb.0: @ %entry
695; CHECK-T2-NEXT:    str r1, [r0, #-1]
696; CHECK-T2-NEXT:    bx lr
697entry:
698  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -1
699  store i32 %x, ptr %add.ptr, align 4
700  ret void
701}
702
703
704; Negative 255 offset
705
706define i32 @ldrsb_ri_negative255(ptr %p) {
707; CHECK-T1-LABEL: ldrsb_ri_negative255:
708; CHECK-T1:       @ %bb.0: @ %entry
709; CHECK-T1-NEXT:    movs r1, #254
710; CHECK-T1-NEXT:    mvns r1, r1
711; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
712; CHECK-T1-NEXT:    bx lr
713;
714; CHECK-T2-LABEL: ldrsb_ri_negative255:
715; CHECK-T2:       @ %bb.0: @ %entry
716; CHECK-T2-NEXT:    ldrsb r0, [r0, #-255]
717; CHECK-T2-NEXT:    bx lr
718entry:
719  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
720  %0 = load i8, ptr %add.ptr, align 1
721  %conv = sext i8 %0 to i32
722  ret i32 %conv
723}
724
725define i32 @ldrsh_ri_negative255(ptr %p) {
726; CHECK-T1-LABEL: ldrsh_ri_negative255:
727; CHECK-T1:       @ %bb.0: @ %entry
728; CHECK-T1-NEXT:    movs r1, #254
729; CHECK-T1-NEXT:    mvns r1, r1
730; CHECK-T1-NEXT:    ldrsh r0, [r0, r1]
731; CHECK-T1-NEXT:    bx lr
732;
733; CHECK-T2-LABEL: ldrsh_ri_negative255:
734; CHECK-T2:       @ %bb.0: @ %entry
735; CHECK-T2-NEXT:    ldrsh r0, [r0, #-255]
736; CHECK-T2-NEXT:    bx lr
737entry:
738  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
739  %0 = load i16, ptr %add.ptr, align 2
740  %conv = sext i16 %0 to i32
741  ret i32 %conv
742}
743
744define i32 @ldrb_ri_negative255(ptr %p) {
745; CHECK-T1-LABEL: ldrb_ri_negative255:
746; CHECK-T1:       @ %bb.0: @ %entry
747; CHECK-T1-NEXT:    subs r0, #255
748; CHECK-T1-NEXT:    ldrb r0, [r0]
749; CHECK-T1-NEXT:    bx lr
750;
751; CHECK-T2-LABEL: ldrb_ri_negative255:
752; CHECK-T2:       @ %bb.0: @ %entry
753; CHECK-T2-NEXT:    ldrb r0, [r0, #-255]
754; CHECK-T2-NEXT:    bx lr
755entry:
756  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
757  %0 = load i8, ptr %add.ptr, align 1
758  %conv = zext i8 %0 to i32
759  ret i32 %conv
760}
761
762define i32 @ldrh_ri_negative255(ptr %p) {
763; CHECK-T1-LABEL: ldrh_ri_negative255:
764; CHECK-T1:       @ %bb.0: @ %entry
765; CHECK-T1-NEXT:    subs r0, #255
766; CHECK-T1-NEXT:    ldrh r0, [r0]
767; CHECK-T1-NEXT:    bx lr
768;
769; CHECK-T2-LABEL: ldrh_ri_negative255:
770; CHECK-T2:       @ %bb.0: @ %entry
771; CHECK-T2-NEXT:    ldrh r0, [r0, #-255]
772; CHECK-T2-NEXT:    bx lr
773entry:
774  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
775  %0 = load i16, ptr %add.ptr, align 2
776  %conv = zext i16 %0 to i32
777  ret i32 %conv
778}
779
780define i32 @ldr_ri_negative255(ptr %p) {
781; CHECK-T1-LABEL: ldr_ri_negative255:
782; CHECK-T1:       @ %bb.0: @ %entry
783; CHECK-T1-NEXT:    subs r0, #255
784; CHECK-T1-NEXT:    ldr r0, [r0]
785; CHECK-T1-NEXT:    bx lr
786;
787; CHECK-T2-LABEL: ldr_ri_negative255:
788; CHECK-T2:       @ %bb.0: @ %entry
789; CHECK-T2-NEXT:    ldr r0, [r0, #-255]
790; CHECK-T2-NEXT:    bx lr
791entry:
792  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
793  %0 = load i32, ptr %add.ptr, align 4
794  ret i32 %0
795}
796
797define void @strb_ri_negative255(ptr %p, i32 %x) {
798; CHECK-T1-LABEL: strb_ri_negative255:
799; CHECK-T1:       @ %bb.0: @ %entry
800; CHECK-T1-NEXT:    subs r0, #255
801; CHECK-T1-NEXT:    strb r1, [r0]
802; CHECK-T1-NEXT:    bx lr
803;
804; CHECK-T2-LABEL: strb_ri_negative255:
805; CHECK-T2:       @ %bb.0: @ %entry
806; CHECK-T2-NEXT:    strb r1, [r0, #-255]
807; CHECK-T2-NEXT:    bx lr
808entry:
809  %conv = trunc i32 %x to i8
810  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
811  store i8 %conv, ptr %add.ptr, align 1
812  ret void
813}
814
815define void @strh_ri_negative255(ptr %p, i32 %x) {
816; CHECK-T1-LABEL: strh_ri_negative255:
817; CHECK-T1:       @ %bb.0: @ %entry
818; CHECK-T1-NEXT:    subs r0, #255
819; CHECK-T1-NEXT:    strh r1, [r0]
820; CHECK-T1-NEXT:    bx lr
821;
822; CHECK-T2-LABEL: strh_ri_negative255:
823; CHECK-T2:       @ %bb.0: @ %entry
824; CHECK-T2-NEXT:    strh r1, [r0, #-255]
825; CHECK-T2-NEXT:    bx lr
826entry:
827  %conv = trunc i32 %x to i16
828  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
829  store i16 %conv, ptr %add.ptr, align 2
830  ret void
831}
832
833define void @str_ri_negative255(ptr %p, i32 %x) {
834; CHECK-T1-LABEL: str_ri_negative255:
835; CHECK-T1:       @ %bb.0: @ %entry
836; CHECK-T1-NEXT:    subs r0, #255
837; CHECK-T1-NEXT:    str r1, [r0]
838; CHECK-T1-NEXT:    bx lr
839;
840; CHECK-T2-LABEL: str_ri_negative255:
841; CHECK-T2:       @ %bb.0: @ %entry
842; CHECK-T2-NEXT:    str r1, [r0, #-255]
843; CHECK-T2-NEXT:    bx lr
844entry:
845  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -255
846  store i32 %x, ptr %add.ptr, align 4
847  ret void
848}
849
850
851; Negative 256 offset
852
853define i32 @ldrsb_ri_negative256(ptr %p) {
854; CHECK-T1-LABEL: ldrsb_ri_negative256:
855; CHECK-T1:       @ %bb.0: @ %entry
856; CHECK-T1-NEXT:    movs r1, #255
857; CHECK-T1-NEXT:    mvns r1, r1
858; CHECK-T1-NEXT:    ldrsb r0, [r0, r1]
859; CHECK-T1-NEXT:    bx lr
860;
861; CHECK-T2-LABEL: ldrsb_ri_negative256:
862; CHECK-T2:       @ %bb.0: @ %entry
863; CHECK-T2-NEXT:    mvn r1, #255
864; CHECK-T2-NEXT:    ldrsb r0, [r0, r1]
865; CHECK-T2-NEXT:    bx lr
866entry:
867  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
868  %0 = load i8, ptr %add.ptr, align 1
869  %conv = sext i8 %0 to i32
870  ret i32 %conv
871}
872
873define i32 @ldrsh_ri_negative256(ptr %p) {
874; CHECK-T1-LABEL: ldrsh_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:    ldrsh r0, [r0, r1]
879; CHECK-T1-NEXT:    bx lr
880;
881; CHECK-T2-LABEL: ldrsh_ri_negative256:
882; CHECK-T2:       @ %bb.0: @ %entry
883; CHECK-T2-NEXT:    mvn r1, #255
884; CHECK-T2-NEXT:    ldrsh r0, [r0, r1]
885; CHECK-T2-NEXT:    bx lr
886entry:
887  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
888  %0 = load i16, ptr %add.ptr, align 2
889  %conv = sext i16 %0 to i32
890  ret i32 %conv
891}
892
893define i32 @ldrb_ri_negative256(ptr %p) {
894; CHECK-T1-LABEL: ldrb_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:    ldrb r0, [r0, r1]
899; CHECK-T1-NEXT:    bx lr
900;
901; CHECK-T2-LABEL: ldrb_ri_negative256:
902; CHECK-T2:       @ %bb.0: @ %entry
903; CHECK-T2-NEXT:    mvn r1, #255
904; CHECK-T2-NEXT:    ldrb r0, [r0, r1]
905; CHECK-T2-NEXT:    bx lr
906entry:
907  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
908  %0 = load i8, ptr %add.ptr, align 1
909  %conv = zext i8 %0 to i32
910  ret i32 %conv
911}
912
913define i32 @ldrh_ri_negative256(ptr %p) {
914; CHECK-T1-LABEL: ldrh_ri_negative256:
915; CHECK-T1:       @ %bb.0: @ %entry
916; CHECK-T1-NEXT:    movs r1, #255
917; CHECK-T1-NEXT:    mvns r1, r1
918; CHECK-T1-NEXT:    ldrh r0, [r0, r1]
919; CHECK-T1-NEXT:    bx lr
920;
921; CHECK-T2-LABEL: ldrh_ri_negative256:
922; CHECK-T2:       @ %bb.0: @ %entry
923; CHECK-T2-NEXT:    mvn r1, #255
924; CHECK-T2-NEXT:    ldrh r0, [r0, r1]
925; CHECK-T2-NEXT:    bx lr
926entry:
927  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
928  %0 = load i16, ptr %add.ptr, align 2
929  %conv = zext i16 %0 to i32
930  ret i32 %conv
931}
932
933define i32 @ldr_ri_negative256(ptr %p) {
934; CHECK-T1-LABEL: ldr_ri_negative256:
935; CHECK-T1:       @ %bb.0: @ %entry
936; CHECK-T1-NEXT:    movs r1, #255
937; CHECK-T1-NEXT:    mvns r1, r1
938; CHECK-T1-NEXT:    ldr r0, [r0, r1]
939; CHECK-T1-NEXT:    bx lr
940;
941; CHECK-T2-LABEL: ldr_ri_negative256:
942; CHECK-T2:       @ %bb.0: @ %entry
943; CHECK-T2-NEXT:    mvn r1, #255
944; CHECK-T2-NEXT:    ldr r0, [r0, r1]
945; CHECK-T2-NEXT:    bx lr
946entry:
947  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
948  %0 = load i32, ptr %add.ptr, align 4
949  ret i32 %0
950}
951
952define void @strb_ri_negative256(ptr %p, i32 %x) {
953; CHECK-T1-LABEL: strb_ri_negative256:
954; CHECK-T1:       @ %bb.0: @ %entry
955; CHECK-T1-NEXT:    movs r2, #255
956; CHECK-T1-NEXT:    mvns r2, r2
957; CHECK-T1-NEXT:    strb r1, [r0, r2]
958; CHECK-T1-NEXT:    bx lr
959;
960; CHECK-T2-LABEL: strb_ri_negative256:
961; CHECK-T2:       @ %bb.0: @ %entry
962; CHECK-T2-NEXT:    mvn r2, #255
963; CHECK-T2-NEXT:    strb r1, [r0, r2]
964; CHECK-T2-NEXT:    bx lr
965entry:
966  %conv = trunc i32 %x to i8
967  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
968  store i8 %conv, ptr %add.ptr, align 1
969  ret void
970}
971
972define void @strh_ri_negative256(ptr %p, i32 %x) {
973; CHECK-T1-LABEL: strh_ri_negative256:
974; CHECK-T1:       @ %bb.0: @ %entry
975; CHECK-T1-NEXT:    movs r2, #255
976; CHECK-T1-NEXT:    mvns r2, r2
977; CHECK-T1-NEXT:    strh r1, [r0, r2]
978; CHECK-T1-NEXT:    bx lr
979;
980; CHECK-T2-LABEL: strh_ri_negative256:
981; CHECK-T2:       @ %bb.0: @ %entry
982; CHECK-T2-NEXT:    mvn r2, #255
983; CHECK-T2-NEXT:    strh r1, [r0, r2]
984; CHECK-T2-NEXT:    bx lr
985entry:
986  %conv = trunc i32 %x to i16
987  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
988  store i16 %conv, ptr %add.ptr, align 2
989  ret void
990}
991
992define void @str_ri_negative256(ptr %p, i32 %x) {
993; CHECK-T1-LABEL: str_ri_negative256:
994; CHECK-T1:       @ %bb.0: @ %entry
995; CHECK-T1-NEXT:    movs r2, #255
996; CHECK-T1-NEXT:    mvns r2, r2
997; CHECK-T1-NEXT:    str r1, [r0, r2]
998; CHECK-T1-NEXT:    bx lr
999;
1000; CHECK-T2-LABEL: str_ri_negative256:
1001; CHECK-T2:       @ %bb.0: @ %entry
1002; CHECK-T2-NEXT:    mvn r2, #255
1003; CHECK-T2-NEXT:    str r1, [r0, r2]
1004; CHECK-T2-NEXT:    bx lr
1005entry:
1006  %add.ptr = getelementptr inbounds i8, ptr %p, i32 -256
1007  store i32 %x, ptr %add.ptr, align 4
1008  ret void
1009}
1010