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
5 define i32* @pre_inc_ldr(i32* %base, i32 %a) {
6 ; CHECK-V8M-LABEL: pre_inc_ldr:
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
13 ; CHECK-V8A-LABEL: pre_inc_ldr:
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, i32* %base, i32 1
20 %ld = load i32, i32* %addr
21 %addr.1 = getelementptr i32, i32* %base, i32 2
22 %res = add i32 %ld, %a
23 store i32 %res, i32* %addr.1
27 define i32* @pre_dec_ldr(i32* %base, i32 %a) {
28 ; CHECK-V8M-LABEL: pre_dec_ldr:
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
35 ; CHECK-V8A-LABEL: pre_dec_ldr:
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, i32* %base, i32 -1
42 %ld = load i32, i32* %addr
43 %addr.1 = getelementptr i32, i32* %base, i32 2
44 %res = add i32 %ld, %a
45 store i32 %res, i32* %addr.1
49 define i32* @post_inc_ldr(i32* %base, i32* %addr.2, i32 %a) {
50 ; CHECK-V8M-LABEL: post_inc_ldr:
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
57 ; CHECK-V8A-LABEL: post_inc_ldr:
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 %addr = getelementptr i32, i32* %base, i32 0
64 %ld = load i32, i32* %addr
65 %addr.1 = getelementptr i32, i32* %base, i32 1
66 %res = add i32 %ld, %a
67 store i32 %res, i32* %addr.2
71 define i32* @post_dec_ldr(i32* %base, i32* %addr.2, i32 %a) {
72 ; CHECK-V8M-LABEL: post_dec_ldr:
74 ; CHECK-V8M-NEXT: ldr r3, [r0], #-4
75 ; CHECK-V8M-NEXT: add r2, r3
76 ; CHECK-V8M-NEXT: str r2, [r1]
77 ; CHECK-V8M-NEXT: bx lr
79 ; CHECK-V8A-LABEL: post_dec_ldr:
81 ; CHECK-V8A-NEXT: ldr r3, [r0], #-4
82 ; CHECK-V8A-NEXT: add r2, r3, r2
83 ; CHECK-V8A-NEXT: str r2, [r1]
84 ; CHECK-V8A-NEXT: bx lr
85 %addr = getelementptr i32, i32* %base, i32 0
86 %ld = load i32, i32* %addr
87 %addr.1 = getelementptr i32, i32* %base, i32 -1
88 %res = add i32 %ld, %a
89 store i32 %res, i32* %addr.2
93 define i32* @pre_inc_str(i32* %base, i32 %a, i32 %b) {
94 ; CHECK-V8M-LABEL: pre_inc_str:
96 ; CHECK-V8M-NEXT: add r1, r2
97 ; CHECK-V8M-NEXT: str r1, [r0, #4]!
98 ; CHECK-V8M-NEXT: bx lr
100 ; CHECK-V8A-LABEL: pre_inc_str:
101 ; CHECK-V8A: @ %bb.0:
102 ; CHECK-V8A-NEXT: add r1, r1, r2
103 ; CHECK-V8A-NEXT: str r1, [r0, #4]!
104 ; CHECK-V8A-NEXT: bx lr
105 %addr.1 = getelementptr i32, i32* %base, i32 1
106 %res = add i32 %a, %b
107 store i32 %res, i32* %addr.1
111 define i32* @pre_dec_str(i32* %base, i32 %a, i32 %b) {
112 ; CHECK-V8M-LABEL: pre_dec_str:
113 ; CHECK-V8M: @ %bb.0:
114 ; CHECK-V8M-NEXT: add r1, r2
115 ; CHECK-V8M-NEXT: str r1, [r0, #-4]!
116 ; CHECK-V8M-NEXT: bx lr
118 ; CHECK-V8A-LABEL: pre_dec_str:
119 ; CHECK-V8A: @ %bb.0:
120 ; CHECK-V8A-NEXT: add r1, r1, r2
121 ; CHECK-V8A-NEXT: str r1, [r0, #-4]!
122 ; CHECK-V8A-NEXT: bx lr
123 %res = add i32 %a, %b
124 %addr.1 = getelementptr i32, i32* %base, i32 -1
125 store i32 %res, i32* %addr.1
129 define i32* @post_inc_str(i32* %base, i32 %a, i32 %b) {
130 ; CHECK-V8M-LABEL: post_inc_str:
131 ; CHECK-V8M: @ %bb.0:
132 ; CHECK-V8M-NEXT: add r1, r2
133 ; CHECK-V8M-NEXT: str r1, [r0], #4
134 ; CHECK-V8M-NEXT: bx lr
136 ; CHECK-V8A-LABEL: post_inc_str:
137 ; CHECK-V8A: @ %bb.0:
138 ; CHECK-V8A-NEXT: add r1, r1, r2
139 ; CHECK-V8A-NEXT: str r1, [r0], #4
140 ; CHECK-V8A-NEXT: bx lr
141 %addr.1 = getelementptr i32, i32* %base, i32 1
142 %res = add i32 %a, %b
143 store i32 %res, i32* %base
147 define i32* @post_dec_str(i32* %base, i32 %a, i32 %b) {
148 ; CHECK-V8M-LABEL: post_dec_str:
149 ; CHECK-V8M: @ %bb.0:
150 ; CHECK-V8M-NEXT: add r1, r2
151 ; CHECK-V8M-NEXT: str r1, [r0], #-4
152 ; CHECK-V8M-NEXT: bx lr
154 ; CHECK-V8A-LABEL: post_dec_str:
155 ; CHECK-V8A: @ %bb.0:
156 ; CHECK-V8A-NEXT: add r1, r1, r2
157 ; CHECK-V8A-NEXT: str r1, [r0], #-4
158 ; CHECK-V8A-NEXT: bx lr
159 %addr.1 = getelementptr i32, i32* %base, i32 -1
160 %res = add i32 %a, %b
161 store i32 %res, i32* %base
165 ; TODO: Generate ldrd
166 define i32* @pre_inc_ldrd(i32* %base) {
167 ; CHECK-V8M-LABEL: pre_inc_ldrd:
168 ; CHECK-V8M: @ %bb.0:
169 ; CHECK-V8M-NEXT: ldr r1, [r0, #4]!
170 ; CHECK-V8M-NEXT: ldr r2, [r0, #4]
171 ; CHECK-V8M-NEXT: add r1, r2
172 ; CHECK-V8M-NEXT: str r1, [r0, #8]
173 ; CHECK-V8M-NEXT: bx lr
175 ; CHECK-V8A-LABEL: pre_inc_ldrd:
176 ; CHECK-V8A: @ %bb.0:
177 ; CHECK-V8A-NEXT: ldr r1, [r0, #4]!
178 ; CHECK-V8A-NEXT: ldr r2, [r0, #4]
179 ; CHECK-V8A-NEXT: add r1, r1, r2
180 ; CHECK-V8A-NEXT: str r1, [r0, #8]
181 ; CHECK-V8A-NEXT: bx lr
182 %addr = getelementptr i32, i32* %base, i32 1
183 %addr.1 = getelementptr i32, i32* %base, i32 2
184 %addr.2 = getelementptr i32, i32* %base, i32 3
185 %ld = load i32, i32* %addr
186 %ld.1 = load i32, i32* %addr.1
187 %res = add i32 %ld, %ld.1
188 store i32 %res, i32* %addr.2
192 ; TODO: Generate ldrd
193 define i32* @pre_dec_ldrd(i32* %base) {
194 ; CHECK-V8M-LABEL: pre_dec_ldrd:
195 ; CHECK-V8M: @ %bb.0:
196 ; CHECK-V8M-NEXT: ldr r1, [r0, #-4]!
197 ; CHECK-V8M-NEXT: ldr r2, [r0, #-4]
198 ; CHECK-V8M-NEXT: add r1, r2
199 ; CHECK-V8M-NEXT: str r1, [r0, #-8]
200 ; CHECK-V8M-NEXT: bx lr
202 ; CHECK-V8A-LABEL: pre_dec_ldrd:
203 ; CHECK-V8A: @ %bb.0:
204 ; CHECK-V8A-NEXT: ldr r1, [r0, #-4]!
205 ; CHECK-V8A-NEXT: ldr r2, [r0, #-4]
206 ; CHECK-V8A-NEXT: add r1, r1, r2
207 ; CHECK-V8A-NEXT: str r1, [r0, #-8]
208 ; CHECK-V8A-NEXT: bx lr
209 %addr = getelementptr i32, i32* %base, i32 -1
210 %addr.1 = getelementptr i32, i32* %base, i32 -2
211 %addr.2 = getelementptr i32, i32* %base, i32 -3
212 %ld = load i32, i32* %addr
213 %ld.1 = load i32, i32* %addr.1
214 %res = add i32 %ld, %ld.1
215 store i32 %res, i32* %addr.2
219 ; TODO: Generate post inc
220 define i32* @post_inc_ldrd(i32* %base, i32* %addr.3) {
221 ; CHECK-V8M-LABEL: post_inc_ldrd:
222 ; CHECK-V8M: @ %bb.0:
223 ; CHECK-V8M-NEXT: ldrd r2, r3, [r0], #8
224 ; CHECK-V8M-NEXT: add r2, r3
225 ; CHECK-V8M-NEXT: str r2, [r1]
226 ; CHECK-V8M-NEXT: bx lr
228 ; CHECK-V8A-LABEL: post_inc_ldrd:
229 ; CHECK-V8A: @ %bb.0:
230 ; CHECK-V8A-NEXT: ldm r0!, {r2, r3}
231 ; CHECK-V8A-NEXT: add r2, r2, r3
232 ; CHECK-V8A-NEXT: str r2, [r1]
233 ; CHECK-V8A-NEXT: bx lr
234 %addr = getelementptr i32, i32* %base, i32 0
235 %ld = load i32, i32* %addr
236 %addr.1 = getelementptr i32, i32* %base, i32 1
237 %ld.1 = load i32, i32* %addr.1
238 %addr.2 = getelementptr i32, i32* %base, i32 2
239 %res = add i32 %ld, %ld.1
240 store i32 %res, i32* %addr.3
244 define i32* @pre_inc_str_multi(i32* %base) {
245 ; CHECK-V8M-LABEL: pre_inc_str_multi:
246 ; CHECK-V8M: @ %bb.0:
247 ; CHECK-V8M-NEXT: ldrd r1, r2, [r0]
248 ; CHECK-V8M-NEXT: add r1, r2
249 ; CHECK-V8M-NEXT: str r1, [r0, #8]!
250 ; CHECK-V8M-NEXT: bx lr
252 ; CHECK-V8A-LABEL: pre_inc_str_multi:
253 ; CHECK-V8A: @ %bb.0:
254 ; CHECK-V8A-NEXT: ldm r0, {r1, r2}
255 ; CHECK-V8A-NEXT: add r1, r1, r2
256 ; CHECK-V8A-NEXT: str r1, [r0, #8]!
257 ; CHECK-V8A-NEXT: bx lr
258 %addr = getelementptr i32, i32* %base, i32 0
259 %addr.1 = getelementptr i32, i32* %base, i32 1
260 %ld = load i32, i32* %addr
261 %ld.1 = load i32, i32* %addr.1
262 %res = add i32 %ld, %ld.1
263 %addr.2 = getelementptr i32, i32* %base, i32 2
264 store i32 %res, i32* %addr.2
268 define i32* @pre_dec_str_multi(i32* %base) {
269 ; CHECK-V8M-LABEL: pre_dec_str_multi:
270 ; CHECK-V8M: @ %bb.0:
271 ; CHECK-V8M-NEXT: ldrd r1, r2, [r0]
272 ; CHECK-V8M-NEXT: add r1, r2
273 ; CHECK-V8M-NEXT: str r1, [r0, #-4]!
274 ; CHECK-V8M-NEXT: bx lr
276 ; CHECK-V8A-LABEL: pre_dec_str_multi:
277 ; CHECK-V8A: @ %bb.0:
278 ; CHECK-V8A-NEXT: ldm r0, {r1, r2}
279 ; CHECK-V8A-NEXT: add r1, r1, r2
280 ; CHECK-V8A-NEXT: str r1, [r0, #-4]!
281 ; CHECK-V8A-NEXT: bx lr
282 %addr = getelementptr i32, i32* %base, i32 0
283 %addr.1 = getelementptr i32, i32* %base, i32 1
284 %ld = load i32, i32* %addr
285 %ld.1 = load i32, i32* %addr.1
286 %res = add i32 %ld, %ld.1
287 %addr.2 = getelementptr i32, i32* %base, i32 -1
288 store i32 %res, i32* %addr.2
292 define i32* @illegal_pre_inc_store_1(i32* %base) {
293 ; CHECK-V8M-LABEL: illegal_pre_inc_store_1:
294 ; CHECK-V8M: @ %bb.0: @ %entry
295 ; CHECK-V8M-NEXT: str r0, [r0, #8]
296 ; CHECK-V8M-NEXT: adds r0, #8
297 ; CHECK-V8M-NEXT: bx lr
299 ; CHECK-V8A-LABEL: illegal_pre_inc_store_1:
300 ; CHECK-V8A: @ %bb.0: @ %entry
301 ; CHECK-V8A-NEXT: str r0, [r0, #8]
302 ; CHECK-V8A-NEXT: add r0, r0, #8
303 ; CHECK-V8A-NEXT: bx lr
305 %ptr.to.use = getelementptr i32, i32* %base, i32 2
306 %ptr.to.store = ptrtoint i32* %base to i32
307 store i32 %ptr.to.store, i32* %ptr.to.use, align 4
311 define i32* @legal_pre_inc_store_needs_copy_1(i32* %base) {
312 ; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_1:
313 ; CHECK-V8M: @ %bb.0: @ %entry
314 ; CHECK-V8M-NEXT: add.w r1, r0, #8
315 ; CHECK-V8M-NEXT: str r1, [r0, #8]
316 ; CHECK-V8M-NEXT: mov r0, r1
317 ; CHECK-V8M-NEXT: bx lr
319 ; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_1:
320 ; CHECK-V8A: @ %bb.0: @ %entry
321 ; CHECK-V8A-NEXT: add r1, r0, #8
322 ; CHECK-V8A-NEXT: str r1, [r0, #8]
323 ; CHECK-V8A-NEXT: mov r0, r1
324 ; CHECK-V8A-NEXT: bx lr
326 %ptr.to.use = getelementptr i32, i32* %base, i32 2
327 %ptr.to.store = ptrtoint i32* %ptr.to.use to i32
328 store i32 %ptr.to.store, i32* %ptr.to.use, align 4
332 define i32* @legal_pre_inc_store_needs_copy_2(i32 %base) {
333 ; CHECK-V8M-LABEL: legal_pre_inc_store_needs_copy_2:
334 ; CHECK-V8M: @ %bb.0: @ %entry
335 ; CHECK-V8M-NEXT: str r0, [r0, #8]
336 ; CHECK-V8M-NEXT: adds r0, #8
337 ; CHECK-V8M-NEXT: bx lr
339 ; CHECK-V8A-LABEL: legal_pre_inc_store_needs_copy_2:
340 ; CHECK-V8A: @ %bb.0: @ %entry
341 ; CHECK-V8A-NEXT: str r0, [r0, #8]
342 ; CHECK-V8A-NEXT: add r0, r0, #8
343 ; CHECK-V8A-NEXT: bx lr
345 %ptr = inttoptr i32 %base to i32*
346 %ptr.to.use = getelementptr i32, i32* %ptr, i32 2
347 store i32 %base, i32* %ptr.to.use, align 4