xref: /llvm-project/llvm/test/CodeGen/ARM/indexed-mem.ll (revision a1cdb323e2610a8e9d8f67382c27172f5f3f3511)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s --check-prefix=CHECK-V8M
3; RUN: llc -mtriple=armv8 %s -o - | FileCheck %s  --check-prefix=CHECK-V8A
4
5define ptr @pre_inc_ldr(ptr %base, i32 %a) {
6; CHECK-V8M-LABEL: pre_inc_ldr:
7; CHECK-V8M:       @ %bb.0:
8; CHECK-V8M-NEXT:    ldr r2, [r0, #4]!
9; CHECK-V8M-NEXT:    add r1, r2
10; CHECK-V8M-NEXT:    str r1, [r0, #4]
11; CHECK-V8M-NEXT:    bx lr
12;
13; CHECK-V8A-LABEL: pre_inc_ldr:
14; CHECK-V8A:       @ %bb.0:
15; CHECK-V8A-NEXT:    ldr r2, [r0, #4]!
16; CHECK-V8A-NEXT:    add r1, r2, r1
17; CHECK-V8A-NEXT:    str r1, [r0, #4]
18; CHECK-V8A-NEXT:    bx lr
19  %addr = getelementptr i32, ptr %base, i32 1
20  %ld = load i32, ptr %addr
21  %addr.1 = getelementptr i32, ptr %base, i32 2
22  %res = add i32 %ld, %a
23  store i32 %res, ptr %addr.1
24  ret ptr %addr
25}
26
27define ptr @pre_dec_ldr(ptr %base, i32 %a) {
28; CHECK-V8M-LABEL: pre_dec_ldr:
29; CHECK-V8M:       @ %bb.0:
30; CHECK-V8M-NEXT:    ldr r2, [r0, #-4]!
31; CHECK-V8M-NEXT:    add r1, r2
32; CHECK-V8M-NEXT:    str r1, [r0, #12]
33; CHECK-V8M-NEXT:    bx lr
34;
35; CHECK-V8A-LABEL: pre_dec_ldr:
36; CHECK-V8A:       @ %bb.0:
37; CHECK-V8A-NEXT:    ldr r2, [r0, #-4]!
38; CHECK-V8A-NEXT:    add r1, r2, r1
39; CHECK-V8A-NEXT:    str r1, [r0, #12]
40; CHECK-V8A-NEXT:    bx lr
41  %addr = getelementptr i32, ptr %base, i32 -1
42  %ld = load i32, ptr %addr
43  %addr.1 = getelementptr i32, ptr %base, i32 2
44  %res = add i32 %ld, %a
45  store i32 %res, ptr %addr.1
46  ret ptr %addr
47}
48
49define ptr @post_inc_ldr(ptr %base, ptr %addr.2, i32 %a) {
50; CHECK-V8M-LABEL: post_inc_ldr:
51; CHECK-V8M:       @ %bb.0:
52; CHECK-V8M-NEXT:    ldr r3, [r0], #4
53; CHECK-V8M-NEXT:    add r2, r3
54; CHECK-V8M-NEXT:    str r2, [r1]
55; CHECK-V8M-NEXT:    bx lr
56;
57; CHECK-V8A-LABEL: post_inc_ldr:
58; CHECK-V8A:       @ %bb.0:
59; CHECK-V8A-NEXT:    ldr r3, [r0], #4
60; CHECK-V8A-NEXT:    add r2, r3, r2
61; CHECK-V8A-NEXT:    str r2, [r1]
62; CHECK-V8A-NEXT:    bx lr
63  %ld = load i32, ptr %base
64  %addr.1 = getelementptr i32, ptr %base, i32 1
65  %res = add i32 %ld, %a
66  store i32 %res, ptr %addr.2
67  ret ptr %addr.1
68}
69
70define ptr @post_dec_ldr(ptr %base, ptr %addr.2, i32 %a) {
71; CHECK-V8M-LABEL: post_dec_ldr:
72; CHECK-V8M:       @ %bb.0:
73; CHECK-V8M-NEXT:    ldr r3, [r0], #-4
74; CHECK-V8M-NEXT:    add r2, r3
75; CHECK-V8M-NEXT:    str r2, [r1]
76; CHECK-V8M-NEXT:    bx lr
77;
78; CHECK-V8A-LABEL: post_dec_ldr:
79; CHECK-V8A:       @ %bb.0:
80; CHECK-V8A-NEXT:    ldr r3, [r0], #-4
81; CHECK-V8A-NEXT:    add r2, r3, r2
82; CHECK-V8A-NEXT:    str r2, [r1]
83; CHECK-V8A-NEXT:    bx lr
84  %ld = load i32, ptr %base
85  %addr.1 = getelementptr i32, ptr %base, i32 -1
86  %res = add i32 %ld, %a
87  store i32 %res, ptr %addr.2
88  ret ptr %addr.1
89}
90
91define ptr @pre_inc_str(ptr %base, i32 %a, i32 %b) {
92; CHECK-V8M-LABEL: pre_inc_str:
93; CHECK-V8M:       @ %bb.0:
94; CHECK-V8M-NEXT:    add r1, r2
95; CHECK-V8M-NEXT:    str r1, [r0, #4]!
96; CHECK-V8M-NEXT:    bx lr
97;
98; CHECK-V8A-LABEL: pre_inc_str:
99; CHECK-V8A:       @ %bb.0:
100; CHECK-V8A-NEXT:    add r1, r1, r2
101; CHECK-V8A-NEXT:    str r1, [r0, #4]!
102; CHECK-V8A-NEXT:    bx lr
103  %addr.1 = getelementptr i32, ptr %base, i32 1
104  %res = add i32 %a, %b
105  store i32 %res, ptr %addr.1
106  ret ptr %addr.1
107}
108
109define ptr @pre_dec_str(ptr %base, i32 %a, i32 %b) {
110; CHECK-V8M-LABEL: pre_dec_str:
111; CHECK-V8M:       @ %bb.0:
112; CHECK-V8M-NEXT:    add r1, r2
113; CHECK-V8M-NEXT:    str r1, [r0, #-4]!
114; CHECK-V8M-NEXT:    bx lr
115;
116; CHECK-V8A-LABEL: pre_dec_str:
117; CHECK-V8A:       @ %bb.0:
118; CHECK-V8A-NEXT:    add r1, r1, r2
119; CHECK-V8A-NEXT:    str r1, [r0, #-4]!
120; CHECK-V8A-NEXT:    bx lr
121  %res = add i32 %a, %b
122  %addr.1 = getelementptr i32, ptr %base, i32 -1
123  store i32 %res, ptr %addr.1
124  ret ptr %addr.1
125}
126
127define ptr @post_inc_str(ptr %base, i32 %a, i32 %b) {
128; CHECK-V8M-LABEL: post_inc_str:
129; CHECK-V8M:       @ %bb.0:
130; CHECK-V8M-NEXT:    add r1, r2
131; CHECK-V8M-NEXT:    str r1, [r0], #4
132; CHECK-V8M-NEXT:    bx lr
133;
134; CHECK-V8A-LABEL: post_inc_str:
135; CHECK-V8A:       @ %bb.0:
136; CHECK-V8A-NEXT:    add r1, r1, r2
137; CHECK-V8A-NEXT:    str r1, [r0], #4
138; CHECK-V8A-NEXT:    bx lr
139  %addr.1 = getelementptr i32, ptr %base, i32 1
140  %res = add i32 %a, %b
141  store i32 %res, ptr %base
142  ret ptr %addr.1
143}
144
145define ptr @post_dec_str(ptr %base, i32 %a, i32 %b) {
146; CHECK-V8M-LABEL: post_dec_str:
147; CHECK-V8M:       @ %bb.0:
148; CHECK-V8M-NEXT:    add r1, r2
149; CHECK-V8M-NEXT:    str r1, [r0], #-4
150; CHECK-V8M-NEXT:    bx lr
151;
152; CHECK-V8A-LABEL: post_dec_str:
153; CHECK-V8A:       @ %bb.0:
154; CHECK-V8A-NEXT:    add r1, r1, r2
155; CHECK-V8A-NEXT:    str r1, [r0], #-4
156; CHECK-V8A-NEXT:    bx lr
157  %addr.1 = getelementptr i32, ptr %base, i32 -1
158  %res = add i32 %a, %b
159  store i32 %res, ptr %base
160  ret ptr %addr.1
161}
162
163; TODO: Generate ldrd
164define ptr @pre_inc_ldrd(ptr %base) {
165; CHECK-V8M-LABEL: pre_inc_ldrd:
166; CHECK-V8M:       @ %bb.0:
167; CHECK-V8M-NEXT:    ldr r1, [r0, #4]!
168; CHECK-V8M-NEXT:    ldr r2, [r0, #4]
169; CHECK-V8M-NEXT:    add r1, r2
170; CHECK-V8M-NEXT:    str r1, [r0, #8]
171; CHECK-V8M-NEXT:    bx lr
172;
173; CHECK-V8A-LABEL: pre_inc_ldrd:
174; CHECK-V8A:       @ %bb.0:
175; CHECK-V8A-NEXT:    ldr r1, [r0, #4]!
176; CHECK-V8A-NEXT:    ldr r2, [r0, #4]
177; CHECK-V8A-NEXT:    add r1, r1, r2
178; CHECK-V8A-NEXT:    str r1, [r0, #8]
179; CHECK-V8A-NEXT:    bx lr
180  %addr = getelementptr i32, ptr %base, i32 1
181  %addr.1 = getelementptr i32, ptr %base, i32 2
182  %addr.2 = getelementptr i32, ptr %base, i32 3
183  %ld = load i32, ptr %addr
184  %ld.1 = load i32, ptr %addr.1
185  %res = add i32 %ld, %ld.1
186  store i32 %res, ptr %addr.2
187  ret ptr %addr
188}
189
190; TODO: Generate ldrd
191define ptr @pre_dec_ldrd(ptr %base) {
192; CHECK-V8M-LABEL: pre_dec_ldrd:
193; CHECK-V8M:       @ %bb.0:
194; CHECK-V8M-NEXT:    ldr r1, [r0, #-4]!
195; CHECK-V8M-NEXT:    ldr r2, [r0, #-4]
196; CHECK-V8M-NEXT:    add r1, r2
197; CHECK-V8M-NEXT:    str r1, [r0, #-8]
198; CHECK-V8M-NEXT:    bx lr
199;
200; CHECK-V8A-LABEL: pre_dec_ldrd:
201; CHECK-V8A:       @ %bb.0:
202; CHECK-V8A-NEXT:    ldr r1, [r0, #-4]!
203; CHECK-V8A-NEXT:    ldr r2, [r0, #-4]
204; CHECK-V8A-NEXT:    add r1, r1, r2
205; CHECK-V8A-NEXT:    str r1, [r0, #-8]
206; CHECK-V8A-NEXT:    bx lr
207  %addr = getelementptr i32, ptr %base, i32 -1
208  %addr.1 = getelementptr i32, ptr %base, i32 -2
209  %addr.2 = getelementptr i32, ptr %base, i32 -3
210  %ld = load i32, ptr %addr
211  %ld.1 = load i32, ptr %addr.1
212  %res = add i32 %ld, %ld.1
213  store i32 %res, ptr %addr.2
214  ret ptr %addr
215}
216
217; TODO: Generate post inc
218define ptr @post_inc_ldrd(ptr %base, ptr %addr.3) {
219; CHECK-V8M-LABEL: post_inc_ldrd:
220; CHECK-V8M:       @ %bb.0:
221; CHECK-V8M-NEXT:    ldrd r2, r3, [r0], #8
222; CHECK-V8M-NEXT:    add r2, r3
223; CHECK-V8M-NEXT:    str r2, [r1]
224; CHECK-V8M-NEXT:    bx lr
225;
226; CHECK-V8A-LABEL: post_inc_ldrd:
227; CHECK-V8A:       @ %bb.0:
228; CHECK-V8A-NEXT:    ldrd r2, r3, [r0]
229; CHECK-V8A-NEXT:    add r0, r0, #8
230; CHECK-V8A-NEXT:    add r2, r2, r3
231; CHECK-V8A-NEXT:    str r2, [r1]
232; CHECK-V8A-NEXT:    bx lr
233  %ld = load i32, ptr %base
234  %addr.1 = getelementptr i32, ptr %base, i32 1
235  %ld.1 = load i32, ptr %addr.1
236  %addr.2 = getelementptr i32, ptr %base, i32 2
237  %res = add i32 %ld, %ld.1
238  store i32 %res, ptr %addr.3
239  ret ptr %addr.2
240}
241
242define ptr @pre_inc_str_multi(ptr %base) {
243; CHECK-V8M-LABEL: pre_inc_str_multi:
244; CHECK-V8M:       @ %bb.0:
245; CHECK-V8M-NEXT:    ldrd r1, r2, [r0]
246; CHECK-V8M-NEXT:    add r1, r2
247; CHECK-V8M-NEXT:    str r1, [r0, #8]!
248; CHECK-V8M-NEXT:    bx lr
249;
250; CHECK-V8A-LABEL: pre_inc_str_multi:
251; CHECK-V8A:       @ %bb.0:
252; CHECK-V8A-NEXT:    ldrd r2, r3, [r0]
253; CHECK-V8A-NEXT:    add r1, r2, r3
254; CHECK-V8A-NEXT:    str r1, [r0, #8]!
255; CHECK-V8A-NEXT:    bx lr
256  %addr.1 = getelementptr i32, ptr %base, i32 1
257  %ld = load i32, ptr %base
258  %ld.1 = load i32, ptr %addr.1
259  %res = add i32 %ld, %ld.1
260  %addr.2 = getelementptr i32, ptr %base, i32 2
261  store i32 %res, ptr %addr.2
262  ret ptr %addr.2
263}
264
265define ptr @pre_dec_str_multi(ptr %base) {
266; CHECK-V8M-LABEL: pre_dec_str_multi:
267; CHECK-V8M:       @ %bb.0:
268; CHECK-V8M-NEXT:    ldrd r1, r2, [r0]
269; CHECK-V8M-NEXT:    add r1, r2
270; CHECK-V8M-NEXT:    str r1, [r0, #-4]!
271; CHECK-V8M-NEXT:    bx lr
272;
273; CHECK-V8A-LABEL: pre_dec_str_multi:
274; CHECK-V8A:       @ %bb.0:
275; CHECK-V8A-NEXT:    ldrd r2, r3, [r0]
276; CHECK-V8A-NEXT:    add r1, r2, r3
277; CHECK-V8A-NEXT:    str r1, [r0, #-4]!
278; CHECK-V8A-NEXT:    bx lr
279  %addr.1 = getelementptr i32, ptr %base, i32 1
280  %ld = load i32, ptr %base
281  %ld.1 = load i32, ptr %addr.1
282  %res = add i32 %ld, %ld.1
283  %addr.2 = getelementptr i32, ptr %base, i32 -1
284  store i32 %res, ptr %addr.2
285  ret ptr %addr.2
286}
287
288define ptr @illegal_pre_inc_store_1(ptr %base) {
289; CHECK-V8M-LABEL: illegal_pre_inc_store_1:
290; CHECK-V8M:       @ %bb.0: @ %entry
291; CHECK-V8M-NEXT:    str r0, [r0, #8]
292; CHECK-V8M-NEXT:    adds r0, #8
293; CHECK-V8M-NEXT:    bx lr
294;
295; CHECK-V8A-LABEL: illegal_pre_inc_store_1:
296; CHECK-V8A:       @ %bb.0: @ %entry
297; CHECK-V8A-NEXT:    str r0, [r0, #8]
298; CHECK-V8A-NEXT:    add r0, r0, #8
299; CHECK-V8A-NEXT:    bx lr
300entry:
301  %ptr.to.use = getelementptr i32, ptr %base, i32 2
302  %ptr.to.store = ptrtoint ptr %base to i32
303  store i32 %ptr.to.store, ptr %ptr.to.use, align 4
304  ret ptr %ptr.to.use
305}
306
307define ptr @legal_pre_inc_store_needs_copy_1(ptr %base) {
308; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_1:
309; CHECK-V8M:       @ %bb.0: @ %entry
310; CHECK-V8M-NEXT:    add.w r1, r0, #8
311; CHECK-V8M-NEXT:    str r1, [r0, #8]
312; CHECK-V8M-NEXT:    mov r0, r1
313; CHECK-V8M-NEXT:    bx lr
314;
315; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_1:
316; CHECK-V8A:       @ %bb.0: @ %entry
317; CHECK-V8A-NEXT:    add r1, r0, #8
318; CHECK-V8A-NEXT:    str r1, [r0, #8]
319; CHECK-V8A-NEXT:    mov r0, r1
320; CHECK-V8A-NEXT:    bx lr
321entry:
322  %ptr.to.use = getelementptr i32, ptr %base, i32 2
323  %ptr.to.store = ptrtoint ptr %ptr.to.use to i32
324  store i32 %ptr.to.store, ptr %ptr.to.use, align 4
325  ret ptr %ptr.to.use
326}
327
328define ptr @legal_pre_inc_store_needs_copy_2(i32 %base) {
329; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_2:
330; CHECK-V8M:       @ %bb.0: @ %entry
331; CHECK-V8M-NEXT:    str r0, [r0, #8]
332; CHECK-V8M-NEXT:    adds r0, #8
333; CHECK-V8M-NEXT:    bx lr
334;
335; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_2:
336; CHECK-V8A:       @ %bb.0: @ %entry
337; CHECK-V8A-NEXT:    str r0, [r0, #8]
338; CHECK-V8A-NEXT:    add r0, r0, #8
339; CHECK-V8A-NEXT:    bx lr
340entry:
341  %ptr = inttoptr i32 %base to ptr
342  %ptr.to.use = getelementptr i32, ptr %ptr, i32 2
343  store i32 %base, ptr %ptr.to.use, align 4
344  ret ptr %ptr.to.use
345}
346