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(i8* %p, i32 %n) {
10entry:
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
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(i16* %p, i32 %n) {
22entry:
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
27}
28
29; CHECK-LABEL: ldrb_rr
30; CHECK:    ldrb r0, [r0, r1]
31define i32 @ldrb_rr(i8* %p, i32 %n) {
32entry:
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
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(i16* %p, i32 %n) {
44entry:
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
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(i32* %p, i32 %n) {
56entry:
57  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
58  %0 = load i32, i32* %arrayidx, align 4
59  ret i32 %0
60}
61
62; CHECK-LABEL: strb_rr
63; CHECK:    strb    r2, [r0, r1]
64define void @strb_rr(i8* %p, i32 %n, i32 %x) {
65entry:
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
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(i16* %p, i32 %n, i32 %x) {
77entry:
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
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(i32* %p, i32 %n, i32 %x) {
89entry:
90  %arrayidx = getelementptr inbounds i32, i32* %p, i32 %n
91  store i32 %x, i32* %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(i8* %p) {
103entry:
104  %0 = load i8, i8* %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(i16* %p) {
114entry:
115  %0 = load i16, i16* %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(i8* %p) {
123entry:
124  %0 = load i8, i8* %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(i16* %p) {
132entry:
133  %0 = load i16, i16* %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(i32* %p) {
141entry:
142  %0 = load i32, i32* %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(i8* %p, i32 %x) {
149entry:
150  %conv = trunc i32 %x to i8
151  store i8 %conv, i8* %p, align 1
152  ret void
153}
154
155; CHECK-LABEL: strh_ri_zero
156; CHECK:    strh    r1, [r0]
157define void @strh_ri_zero(i16* %p, i32 %x) {
158entry:
159  %conv = trunc i32 %x to i16
160  store i16 %conv, i16* %p, align 2
161  ret void
162}
163
164; CHECK-LABEL: str_ri_zero
165; CHECK:    str     r1, [r0]
166define void @str_ri_zero(i32* %p, i32 %x) {
167entry:
168  store i32 %x, i32* %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(i8* %p) {
180entry:
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
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(i16* %p) {
192entry:
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
197}
198
199; CHECK-LABEL: ldrb_ri_t1_max
200; CHECK:    ldrb    r0, [r0, #31]
201define i32 @ldrb_ri_t1_max(i8* %p) {
202entry:
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
207}
208
209; CHECK-LABEL: ldrh_ri_t1_max
210; CHECK:    ldrh    r0, [r0, #62]
211define i32 @ldrh_ri_t1_max(i16* %p) {
212entry:
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
217}
218
219; CHECK-LABEL: ldr_ri_t1_max
220; CHECK:    ldr     r0, [r0, #124]
221define i32 @ldr_ri_t1_max(i32* %p) {
222entry:
223  %arrayidx = getelementptr inbounds i32, i32* %p, i32 31
224  %0 = load i32, i32* %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(i8* %p, i32 %x) {
231entry:
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
236}
237
238; CHECK-LABEL: strh_ri_t1_max
239; CHECK:    strh    r1, [r0, #62]
240define void @strh_ri_t1_max(i16* %p, i32 %x) {
241entry:
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
246}
247
248; CHECK-LABEL: str_ri_t1_max
249; CHECK:    str     r1, [r0, #124]
250define void @str_ri_t1_max(i32* %p, i32 %x) {
251entry:
252  %arrayidx = getelementptr inbounds i32, i32* %p, i32 31
253  store i32 %x, i32* %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(i8* %p) {
265entry:
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
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(i16* %p) {
277entry:
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
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(i8* %p) {
289entry:
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
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(i16* %p) {
301entry:
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
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(i32* %p) {
313entry:
314  %arrayidx = getelementptr inbounds i32, i32* %p, i32 32
315  %0 = load i32, i32* %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(i8* %p, i32 %x) {
324entry:
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
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(i16* %p, i32 %x) {
336entry:
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
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(i32* %p, i32 %x) {
348entry:
349  %arrayidx = getelementptr inbounds i32, i32* %p, i32 32
350  store i32 %x, i32* %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(i8* %p) {
362entry:
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
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(i8* %p) {
374entry:
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
380}
381
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]
386define i32 @ldrb_ri_t2_max(i8* %p) {
387entry:
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
392}
393
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]
398define i32 @ldrh_ri_t2_max(i8* %p) {
399entry:
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
405}
406
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]
411define i32 @ldr_ri_t2_max(i8* %p) {
412entry:
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
417}
418
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]
423define void @strb_ri_t2_max(i8* %p, i32 %x) {
424entry:
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
429}
430
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]
435define void @strh_ri_t2_max(i8* %p, i32 %x) {
436entry:
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
442}
443
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]
448define void @str_ri_t2_max(i8* %p, i32 %x) {
449entry:
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
454}
455
456
457; One past maximum Thumb-2 immediate offset
458
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]
464define i32 @ldrsb_ri_t2_too_big(i8* %p) {
465entry:
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
470}
471
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]
477define i32 @ldrsh_ri_t2_too_big(i8* %p) {
478entry:
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
484}
485
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]
491define i32 @ldrb_ri_t2_too_big(i8* %p) {
492entry:
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
497}
498
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]
504define i32 @ldrh_ri_t2_too_big(i8* %p) {
505entry:
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
511}
512
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]
518define i32 @ldr_ri_t2_too_big(i8* %p) {
519entry:
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
524}
525
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]
531define void @strb_ri_t2_too_big(i8* %p, i32 %x) {
532entry:
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
537}
538
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]
544define void @strh_ri_t2_too_big(i8* %p, i32 %x) {
545entry:
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
551}
552
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]
558define void @str_ri_t2_too_big(i8* %p, i32 %x) {
559entry:
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
564}
565
566
567; Negative offset
568
569define 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
576;
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
581entry:
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
586}
587
588define 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
595;
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
600entry:
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
606}
607
608define 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
614;
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
619entry:
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
624}
625
626define 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
632;
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
637entry:
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
643}
644
645define 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
651;
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
656entry:
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
661}
662
663define 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
669;
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
674entry:
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
679}
680
681define 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
687;
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
692entry:
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
698}
699
700define 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
706;
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
711entry:
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
716}
717
718
719; Negative 255 offset
720
721define 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
728;
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
733entry:
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
738}
739
740define 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
747;
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
752entry:
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
758}
759
760define 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
766;
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
771entry:
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
776}
777
778define 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
784;
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
789entry:
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
795}
796
797define 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
803;
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
808entry:
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
813}
814
815define 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
821;
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
826entry:
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
831}
832
833define 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
839;
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
844entry:
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
850}
851
852define 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
858;
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
863entry:
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
868}
869
870
871; Negative 256 offset
872
873define 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
880;
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
886entry:
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
891}
892
893define 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
900;
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
906entry:
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
912}
913
914define 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
921;
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
927entry:
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
932}
933
934define 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
941;
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
947entry:
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
953}
954
955define 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
962;
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
968entry:
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
973}
974
975define 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
982;
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
988entry:
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
993}
994
995define 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
1002;
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
1008entry:
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
1014}
1015
1016define 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
1023;
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
1029entry:
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
1034}
1035