blob: a0de6342cb800de1eb1a719f3c4ec9ee63c112de [file] [log] [blame]
Tim Northoverb4ddc082014-05-30 10:09:59 +00001; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -o - %s | FileCheck %s
Tilmann Scheller2d746bc2014-05-26 09:37:19 +00002
3; This file contains tests for the AArch64 load/store optimizer.
4
Tilmann Scheller112ada82014-05-26 12:15:51 +00005%padding = type { i8*, i8*, i8*, i8* }
6%s.word = type { i32, i32 }
7%s.doubleword = type { i64, i32 }
8%s.quadword = type { fp128, i32 }
9%s.float = type { float, i32 }
10%s.double = type { double, i32 }
11%struct.word = type { %padding, %s.word }
12%struct.doubleword = type { %padding, %s.doubleword }
13%struct.quadword = type { %padding, %s.quadword }
14%struct.float = type { %padding, %s.float }
15%struct.double = type { %padding, %s.double }
Tilmann Scheller2d746bc2014-05-26 09:37:19 +000016
17; Check the following transform:
18;
Tilmann Schellercc3ebc82014-05-26 13:36:47 +000019; (ldr|str) X, [x0, #32]
Tilmann Scheller2d746bc2014-05-26 09:37:19 +000020; ...
21; add x0, x0, #32
22; ->
Tilmann Schellercc3ebc82014-05-26 13:36:47 +000023; (ldr|str) X, [x0, #32]!
Tilmann Scheller112ada82014-05-26 12:15:51 +000024;
25; with X being either w1, x1, s0, d0 or q0.
Tilmann Scheller968d5992014-05-26 09:40:40 +000026
Tilmann Scheller112ada82014-05-26 12:15:51 +000027declare void @bar_word(%s.word*, i32)
28
29define void @load-pre-indexed-word(%struct.word* %ptr) nounwind {
30; CHECK-LABEL: load-pre-indexed-word
Tilmann Scheller2d746bc2014-05-26 09:37:19 +000031; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
32entry:
Tilmann Scheller112ada82014-05-26 12:15:51 +000033 %a = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1, i32 0
Tilmann Scheller2d746bc2014-05-26 09:37:19 +000034 %add = load i32* %a, align 4
35 br label %bar
36bar:
Tilmann Scheller112ada82014-05-26 12:15:51 +000037 %c = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1
38 tail call void @bar_word(%s.word* %c, i32 %add)
Tilmann Scheller2d746bc2014-05-26 09:37:19 +000039 ret void
40}
41
Tilmann Schellercc3ebc82014-05-26 13:36:47 +000042define void @store-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind {
43; CHECK-LABEL: store-pre-indexed-word
44; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
45entry:
46 %a = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1, i32 0
47 store i32 %val, i32* %a, align 4
48 br label %bar
49bar:
50 %c = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1
51 tail call void @bar_word(%s.word* %c, i32 %val)
52 ret void
53}
54
Tilmann Scheller112ada82014-05-26 12:15:51 +000055declare void @bar_doubleword(%s.doubleword*, i64)
56
57define void @load-pre-indexed-doubleword(%struct.doubleword* %ptr) nounwind {
58; CHECK-LABEL: load-pre-indexed-doubleword
59; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
60entry:
61 %a = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1, i32 0
62 %add = load i64* %a, align 4
63 br label %bar
64bar:
65 %c = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1
66 tail call void @bar_doubleword(%s.doubleword* %c, i64 %add)
67 ret void
68}
69
Tilmann Schellercc3ebc82014-05-26 13:36:47 +000070define void @store-pre-indexed-doubleword(%struct.doubleword* %ptr, i64 %val) nounwind {
71; CHECK-LABEL: store-pre-indexed-doubleword
72; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
73entry:
74 %a = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1, i32 0
75 store i64 %val, i64* %a, align 4
76 br label %bar
77bar:
78 %c = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1
79 tail call void @bar_doubleword(%s.doubleword* %c, i64 %val)
80 ret void
81}
82
Tilmann Scheller112ada82014-05-26 12:15:51 +000083declare void @bar_quadword(%s.quadword*, fp128)
84
85define void @load-pre-indexed-quadword(%struct.quadword* %ptr) nounwind {
86; CHECK-LABEL: load-pre-indexed-quadword
87; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
88entry:
89 %a = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1, i32 0
90 %add = load fp128* %a, align 4
91 br label %bar
92bar:
93 %c = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1
94 tail call void @bar_quadword(%s.quadword* %c, fp128 %add)
95 ret void
96}
97
Tilmann Schellercc3ebc82014-05-26 13:36:47 +000098define void @store-pre-indexed-quadword(%struct.quadword* %ptr, fp128 %val) nounwind {
99; CHECK-LABEL: store-pre-indexed-quadword
100; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
101entry:
102 %a = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1, i32 0
103 store fp128 %val, fp128* %a, align 4
104 br label %bar
105bar:
106 %c = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1
107 tail call void @bar_quadword(%s.quadword* %c, fp128 %val)
108 ret void
109}
110
Tilmann Scheller112ada82014-05-26 12:15:51 +0000111declare void @bar_float(%s.float*, float)
112
113define void @load-pre-indexed-float(%struct.float* %ptr) nounwind {
114; CHECK-LABEL: load-pre-indexed-float
115; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
116entry:
117 %a = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1, i32 0
118 %add = load float* %a, align 4
119 br label %bar
120bar:
121 %c = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1
122 tail call void @bar_float(%s.float* %c, float %add)
123 ret void
124}
125
Tilmann Schellercc3ebc82014-05-26 13:36:47 +0000126define void @store-pre-indexed-float(%struct.float* %ptr, float %val) nounwind {
127; CHECK-LABEL: store-pre-indexed-float
128; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
129entry:
130 %a = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1, i32 0
131 store float %val, float* %a, align 4
132 br label %bar
133bar:
134 %c = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1
135 tail call void @bar_float(%s.float* %c, float %val)
136 ret void
137}
138
Tilmann Scheller112ada82014-05-26 12:15:51 +0000139declare void @bar_double(%s.double*, double)
140
141define void @load-pre-indexed-double(%struct.double* %ptr) nounwind {
142; CHECK-LABEL: load-pre-indexed-double
143; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
144entry:
145 %a = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1, i32 0
146 %add = load double* %a, align 4
147 br label %bar
148bar:
149 %c = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1
150 tail call void @bar_double(%s.double* %c, double %add)
151 ret void
152}
Tilmann Scheller2d746bc2014-05-26 09:37:19 +0000153
Tilmann Schellercc3ebc82014-05-26 13:36:47 +0000154define void @store-pre-indexed-double(%struct.double* %ptr, double %val) nounwind {
155; CHECK-LABEL: store-pre-indexed-double
156; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
157entry:
158 %a = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1, i32 0
159 store double %val, double* %a, align 4
160 br label %bar
161bar:
162 %c = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1
163 tail call void @bar_double(%s.double* %c, double %val)
164 ret void
165}
Tilmann Scheller35e45142014-05-28 05:44:14 +0000166
167; Check the following transform:
168;
169; ldr X, [x20]
170; ...
171; add x20, x20, #32
172; ->
173; ldr X, [x20], #32
174;
175; with X being either w0, x0, s0, d0 or q0.
176
177define void @load-post-indexed-word(i32* %array, i64 %count) nounwind {
178; CHECK-LABEL: load-post-indexed-word
179; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16
180entry:
181 %gep1 = getelementptr i32* %array, i64 2
182 br label %body
183
184body:
185 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
186 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
187 %gep2 = getelementptr i32* %iv2, i64 -1
188 %load = load i32* %gep2
189 call void @use-word(i32 %load)
190 %load2 = load i32* %iv2
191 call void @use-word(i32 %load2)
192 %iv.next = add i64 %iv, -4
193 %gep3 = getelementptr i32* %iv2, i64 4
194 %cond = icmp eq i64 %iv.next, 0
195 br i1 %cond, label %exit, label %body
196
197exit:
198 ret void
199}
200
201define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind {
202; CHECK-LABEL: load-post-indexed-doubleword
203; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32
204entry:
205 %gep1 = getelementptr i64* %array, i64 2
206 br label %body
207
208body:
209 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
210 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
211 %gep2 = getelementptr i64* %iv2, i64 -1
212 %load = load i64* %gep2
213 call void @use-doubleword(i64 %load)
214 %load2 = load i64* %iv2
215 call void @use-doubleword(i64 %load2)
216 %iv.next = add i64 %iv, -4
217 %gep3 = getelementptr i64* %iv2, i64 4
218 %cond = icmp eq i64 %iv.next, 0
219 br i1 %cond, label %exit, label %body
220
221exit:
222 ret void
223}
224
225define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind {
226; CHECK-LABEL: load-post-indexed-quadword
227; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64
228entry:
229 %gep1 = getelementptr <2 x i64>* %array, i64 2
230 br label %body
231
232body:
233 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
234 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
235 %gep2 = getelementptr <2 x i64>* %iv2, i64 -1
236 %load = load <2 x i64>* %gep2
237 call void @use-quadword(<2 x i64> %load)
238 %load2 = load <2 x i64>* %iv2
239 call void @use-quadword(<2 x i64> %load2)
240 %iv.next = add i64 %iv, -4
241 %gep3 = getelementptr <2 x i64>* %iv2, i64 4
242 %cond = icmp eq i64 %iv.next, 0
243 br i1 %cond, label %exit, label %body
244
245exit:
246 ret void
247}
248
249define void @load-post-indexed-float(float* %array, i64 %count) nounwind {
250; CHECK-LABEL: load-post-indexed-float
251; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16
252entry:
253 %gep1 = getelementptr float* %array, i64 2
254 br label %body
255
256body:
257 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
258 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
259 %gep2 = getelementptr float* %iv2, i64 -1
260 %load = load float* %gep2
261 call void @use-float(float %load)
262 %load2 = load float* %iv2
263 call void @use-float(float %load2)
264 %iv.next = add i64 %iv, -4
265 %gep3 = getelementptr float* %iv2, i64 4
266 %cond = icmp eq i64 %iv.next, 0
267 br i1 %cond, label %exit, label %body
268
269exit:
270 ret void
271}
272
273define void @load-post-indexed-double(double* %array, i64 %count) nounwind {
274; CHECK-LABEL: load-post-indexed-double
275; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32
276entry:
277 %gep1 = getelementptr double* %array, i64 2
278 br label %body
279
280body:
281 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
282 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
283 %gep2 = getelementptr double* %iv2, i64 -1
284 %load = load double* %gep2
285 call void @use-double(double %load)
286 %load2 = load double* %iv2
287 call void @use-double(double %load2)
288 %iv.next = add i64 %iv, -4
289 %gep3 = getelementptr double* %iv2, i64 4
290 %cond = icmp eq i64 %iv.next, 0
291 br i1 %cond, label %exit, label %body
292
293exit:
294 ret void
295}
296
Tilmann Scheller7c747fc2014-05-28 06:43:00 +0000297; Check the following transform:
298;
299; str X, [x20]
300; ...
301; add x20, x20, #32
302; ->
303; str X, [x20], #32
304;
305; with X being either w0, x0, s0, d0 or q0.
306
307define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind {
308; CHECK-LABEL: store-post-indexed-word
309; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16
310entry:
311 %gep1 = getelementptr i32* %array, i64 2
312 br label %body
313
314body:
315 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
316 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
317 %gep2 = getelementptr i32* %iv2, i64 -1
318 %load = load i32* %gep2
319 call void @use-word(i32 %load)
320 store i32 %val, i32* %iv2
321 %iv.next = add i64 %iv, -4
322 %gep3 = getelementptr i32* %iv2, i64 4
323 %cond = icmp eq i64 %iv.next, 0
324 br i1 %cond, label %exit, label %body
325
326exit:
327 ret void
328}
329
330define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind {
331; CHECK-LABEL: store-post-indexed-doubleword
332; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32
333entry:
334 %gep1 = getelementptr i64* %array, i64 2
335 br label %body
336
337body:
338 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
339 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
340 %gep2 = getelementptr i64* %iv2, i64 -1
341 %load = load i64* %gep2
342 call void @use-doubleword(i64 %load)
343 store i64 %val, i64* %iv2
344 %iv.next = add i64 %iv, -4
345 %gep3 = getelementptr i64* %iv2, i64 4
346 %cond = icmp eq i64 %iv.next, 0
347 br i1 %cond, label %exit, label %body
348
349exit:
350 ret void
351}
352
353define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind {
354; CHECK-LABEL: store-post-indexed-quadword
355; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64
356entry:
357 %gep1 = getelementptr <2 x i64>* %array, i64 2
358 br label %body
359
360body:
361 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
362 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
363 %gep2 = getelementptr <2 x i64>* %iv2, i64 -1
364 %load = load <2 x i64>* %gep2
365 call void @use-quadword(<2 x i64> %load)
366 store <2 x i64> %val, <2 x i64>* %iv2
367 %iv.next = add i64 %iv, -4
368 %gep3 = getelementptr <2 x i64>* %iv2, i64 4
369 %cond = icmp eq i64 %iv.next, 0
370 br i1 %cond, label %exit, label %body
371
372exit:
373 ret void
374}
375
376define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind {
377; CHECK-LABEL: store-post-indexed-float
378; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16
379entry:
380 %gep1 = getelementptr float* %array, i64 2
381 br label %body
382
383body:
384 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
385 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
386 %gep2 = getelementptr float* %iv2, i64 -1
387 %load = load float* %gep2
388 call void @use-float(float %load)
389 store float %val, float* %iv2
390 %iv.next = add i64 %iv, -4
391 %gep3 = getelementptr float* %iv2, i64 4
392 %cond = icmp eq i64 %iv.next, 0
393 br i1 %cond, label %exit, label %body
394
395exit:
396 ret void
397}
398
399define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind {
400; CHECK-LABEL: store-post-indexed-double
401; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32
402entry:
403 %gep1 = getelementptr double* %array, i64 2
404 br label %body
405
406body:
407 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
408 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
409 %gep2 = getelementptr double* %iv2, i64 -1
410 %load = load double* %gep2
411 call void @use-double(double %load)
412 store double %val, double* %iv2
413 %iv.next = add i64 %iv, -4
414 %gep3 = getelementptr double* %iv2, i64 4
415 %cond = icmp eq i64 %iv.next, 0
416 br i1 %cond, label %exit, label %body
417
418exit:
419 ret void
420}
421
Tilmann Scheller35e45142014-05-28 05:44:14 +0000422declare void @use-word(i32)
423declare void @use-doubleword(i64)
424declare void @use-quadword(<2 x i64>)
425declare void @use-float(float)
426declare void @use-double(double)