• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -o - %s | FileCheck %s
2
3; This file contains tests for the AArch64 load/store optimizer.
4
5%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 }
16
17; Check the following transform:
18;
19; (ldr|str) X, [x0, #32]
20;  ...
21; add x0, x0, #32
22;  ->
23; (ldr|str) X, [x0, #32]!
24;
25; with X being either w1, x1, s0, d0 or q0.
26
27declare void @bar_word(%s.word*, i32)
28
29define void @load-pre-indexed-word(%struct.word* %ptr) nounwind {
30; CHECK-LABEL: load-pre-indexed-word
31; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
32entry:
33  %a = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1, i32 0
34  %add = load i32* %a, align 4
35  br label %bar
36bar:
37  %c = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1
38  tail call void @bar_word(%s.word* %c, i32 %add)
39  ret void
40}
41
42define 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
55declare 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
70define 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
83declare 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
98define 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
111declare 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
126define 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
139declare 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}
153
154define 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}
166
167; Check the following transform:
168;
169; add x8, x8, #16
170;  ...
171; ldr X, [x8]
172;  ->
173; ldr X, [x8, #16]!
174;
175; with X being either w0, x0, s0, d0 or q0.
176
177%pre.struct.i32 = type { i32, i32, i32}
178%pre.struct.i64 = type { i32, i64, i64}
179%pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>}
180%pre.struct.float = type { i32, float, float}
181%pre.struct.double = type { i32, double, double}
182
183define i32 @load-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
184                                   %pre.struct.i32* %load2) nounwind {
185; CHECK-LABEL: load-pre-indexed-word2
186; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
187  br i1 %cond, label %if.then, label %if.end
188if.then:
189  %load1 = load %pre.struct.i32** %this
190  %gep1 = getelementptr inbounds %pre.struct.i32* %load1, i64 0, i32 1
191  br label %return
192if.end:
193  %gep2 = getelementptr inbounds %pre.struct.i32* %load2, i64 0, i32 2
194  br label %return
195return:
196  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
197  %ret = load i32* %retptr
198  ret i32 %ret
199}
200
201define i64 @load-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
202                                         %pre.struct.i64* %load2) nounwind {
203; CHECK-LABEL: load-pre-indexed-doubleword2
204; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #8]!
205  br i1 %cond, label %if.then, label %if.end
206if.then:
207  %load1 = load %pre.struct.i64** %this
208  %gep1 = getelementptr inbounds %pre.struct.i64* %load1, i64 0, i32 1
209  br label %return
210if.end:
211  %gep2 = getelementptr inbounds %pre.struct.i64* %load2, i64 0, i32 2
212  br label %return
213return:
214  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
215  %ret = load i64* %retptr
216  ret i64 %ret
217}
218
219define <2 x i64> @load-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
220                                             %pre.struct.i128* %load2) nounwind {
221; CHECK-LABEL: load-pre-indexed-quadword2
222; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
223  br i1 %cond, label %if.then, label %if.end
224if.then:
225  %load1 = load %pre.struct.i128** %this
226  %gep1 = getelementptr inbounds %pre.struct.i128* %load1, i64 0, i32 1
227  br label %return
228if.end:
229  %gep2 = getelementptr inbounds %pre.struct.i128* %load2, i64 0, i32 2
230  br label %return
231return:
232  %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
233  %ret = load <2 x i64>* %retptr
234  ret <2 x i64> %ret
235}
236
237define float @load-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
238                                      %pre.struct.float* %load2) nounwind {
239; CHECK-LABEL: load-pre-indexed-float2
240; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
241  br i1 %cond, label %if.then, label %if.end
242if.then:
243  %load1 = load %pre.struct.float** %this
244  %gep1 = getelementptr inbounds %pre.struct.float* %load1, i64 0, i32 1
245  br label %return
246if.end:
247  %gep2 = getelementptr inbounds %pre.struct.float* %load2, i64 0, i32 2
248  br label %return
249return:
250  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
251  %ret = load float* %retptr
252  ret float %ret
253}
254
255define double @load-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
256                                        %pre.struct.double* %load2) nounwind {
257; CHECK-LABEL: load-pre-indexed-double2
258; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
259  br i1 %cond, label %if.then, label %if.end
260if.then:
261  %load1 = load %pre.struct.double** %this
262  %gep1 = getelementptr inbounds %pre.struct.double* %load1, i64 0, i32 1
263  br label %return
264if.end:
265  %gep2 = getelementptr inbounds %pre.struct.double* %load2, i64 0, i32 2
266  br label %return
267return:
268  %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
269  %ret = load double* %retptr
270  ret double %ret
271}
272
273; Check the following transform:
274;
275; add x8, x8, #16
276;  ...
277; str X, [x8]
278;  ->
279; str X, [x8, #16]!
280;
281; with X being either w0, x0, s0, d0 or q0.
282
283define void @store-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
284                                     %pre.struct.i32* %load2,
285                                     i32 %val) nounwind {
286; CHECK-LABEL: store-pre-indexed-word2
287; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
288  br i1 %cond, label %if.then, label %if.end
289if.then:
290  %load1 = load %pre.struct.i32** %this
291  %gep1 = getelementptr inbounds %pre.struct.i32* %load1, i64 0, i32 1
292  br label %return
293if.end:
294  %gep2 = getelementptr inbounds %pre.struct.i32* %load2, i64 0, i32 2
295  br label %return
296return:
297  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
298  store i32 %val, i32* %retptr
299  ret void
300}
301
302define void @store-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
303                                           %pre.struct.i64* %load2,
304                                           i64 %val) nounwind {
305; CHECK-LABEL: store-pre-indexed-doubleword2
306; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]!
307  br i1 %cond, label %if.then, label %if.end
308if.then:
309  %load1 = load %pre.struct.i64** %this
310  %gep1 = getelementptr inbounds %pre.struct.i64* %load1, i64 0, i32 1
311  br label %return
312if.end:
313  %gep2 = getelementptr inbounds %pre.struct.i64* %load2, i64 0, i32 2
314  br label %return
315return:
316  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
317  store i64 %val, i64* %retptr
318  ret void
319}
320
321define void @store-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
322                                         %pre.struct.i128* %load2,
323                                         <2 x i64> %val) nounwind {
324; CHECK-LABEL: store-pre-indexed-quadword2
325; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
326  br i1 %cond, label %if.then, label %if.end
327if.then:
328  %load1 = load %pre.struct.i128** %this
329  %gep1 = getelementptr inbounds %pre.struct.i128* %load1, i64 0, i32 1
330  br label %return
331if.end:
332  %gep2 = getelementptr inbounds %pre.struct.i128* %load2, i64 0, i32 2
333  br label %return
334return:
335  %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
336  store <2 x i64> %val, <2 x i64>* %retptr
337  ret void
338}
339
340define void @store-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
341                                      %pre.struct.float* %load2,
342                                      float %val) nounwind {
343; CHECK-LABEL: store-pre-indexed-float2
344; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
345  br i1 %cond, label %if.then, label %if.end
346if.then:
347  %load1 = load %pre.struct.float** %this
348  %gep1 = getelementptr inbounds %pre.struct.float* %load1, i64 0, i32 1
349  br label %return
350if.end:
351  %gep2 = getelementptr inbounds %pre.struct.float* %load2, i64 0, i32 2
352  br label %return
353return:
354  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
355  store float %val, float* %retptr
356  ret void
357}
358
359define void @store-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
360                                      %pre.struct.double* %load2,
361                                      double %val) nounwind {
362; CHECK-LABEL: store-pre-indexed-double2
363; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
364  br i1 %cond, label %if.then, label %if.end
365if.then:
366  %load1 = load %pre.struct.double** %this
367  %gep1 = getelementptr inbounds %pre.struct.double* %load1, i64 0, i32 1
368  br label %return
369if.end:
370  %gep2 = getelementptr inbounds %pre.struct.double* %load2, i64 0, i32 2
371  br label %return
372return:
373  %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
374  store double %val, double* %retptr
375  ret void
376}
377
378; Check the following transform:
379;
380; ldr X, [x20]
381;  ...
382; add x20, x20, #32
383;  ->
384; ldr X, [x20], #32
385;
386; with X being either w0, x0, s0, d0 or q0.
387
388define void @load-post-indexed-word(i32* %array, i64 %count) nounwind {
389; CHECK-LABEL: load-post-indexed-word
390; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16
391entry:
392  %gep1 = getelementptr i32* %array, i64 2
393  br label %body
394
395body:
396  %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
397  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
398  %gep2 = getelementptr i32* %iv2, i64 -1
399  %load = load i32* %gep2
400  call void @use-word(i32 %load)
401  %load2 = load i32* %iv2
402  call void @use-word(i32 %load2)
403  %iv.next = add i64 %iv, -4
404  %gep3 = getelementptr i32* %iv2, i64 4
405  %cond = icmp eq i64 %iv.next, 0
406  br i1 %cond, label %exit, label %body
407
408exit:
409  ret void
410}
411
412define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind {
413; CHECK-LABEL: load-post-indexed-doubleword
414; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32
415entry:
416  %gep1 = getelementptr i64* %array, i64 2
417  br label %body
418
419body:
420  %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
421  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
422  %gep2 = getelementptr i64* %iv2, i64 -1
423  %load = load i64* %gep2
424  call void @use-doubleword(i64 %load)
425  %load2 = load i64* %iv2
426  call void @use-doubleword(i64 %load2)
427  %iv.next = add i64 %iv, -4
428  %gep3 = getelementptr i64* %iv2, i64 4
429  %cond = icmp eq i64 %iv.next, 0
430  br i1 %cond, label %exit, label %body
431
432exit:
433  ret void
434}
435
436define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind {
437; CHECK-LABEL: load-post-indexed-quadword
438; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64
439entry:
440  %gep1 = getelementptr <2 x i64>* %array, i64 2
441  br label %body
442
443body:
444  %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
445  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
446  %gep2 = getelementptr <2 x i64>* %iv2, i64 -1
447  %load = load <2 x i64>* %gep2
448  call void @use-quadword(<2 x i64> %load)
449  %load2 = load <2 x i64>* %iv2
450  call void @use-quadword(<2 x i64> %load2)
451  %iv.next = add i64 %iv, -4
452  %gep3 = getelementptr <2 x i64>* %iv2, i64 4
453  %cond = icmp eq i64 %iv.next, 0
454  br i1 %cond, label %exit, label %body
455
456exit:
457  ret void
458}
459
460define void @load-post-indexed-float(float* %array, i64 %count) nounwind {
461; CHECK-LABEL: load-post-indexed-float
462; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16
463entry:
464  %gep1 = getelementptr float* %array, i64 2
465  br label %body
466
467body:
468  %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
469  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
470  %gep2 = getelementptr float* %iv2, i64 -1
471  %load = load float* %gep2
472  call void @use-float(float %load)
473  %load2 = load float* %iv2
474  call void @use-float(float %load2)
475  %iv.next = add i64 %iv, -4
476  %gep3 = getelementptr float* %iv2, i64 4
477  %cond = icmp eq i64 %iv.next, 0
478  br i1 %cond, label %exit, label %body
479
480exit:
481  ret void
482}
483
484define void @load-post-indexed-double(double* %array, i64 %count) nounwind {
485; CHECK-LABEL: load-post-indexed-double
486; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32
487entry:
488  %gep1 = getelementptr double* %array, i64 2
489  br label %body
490
491body:
492  %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
493  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
494  %gep2 = getelementptr double* %iv2, i64 -1
495  %load = load double* %gep2
496  call void @use-double(double %load)
497  %load2 = load double* %iv2
498  call void @use-double(double %load2)
499  %iv.next = add i64 %iv, -4
500  %gep3 = getelementptr double* %iv2, i64 4
501  %cond = icmp eq i64 %iv.next, 0
502  br i1 %cond, label %exit, label %body
503
504exit:
505  ret void
506}
507
508; Check the following transform:
509;
510; str X, [x20]
511;  ...
512; add x20, x20, #32
513;  ->
514; str X, [x20], #32
515;
516; with X being either w0, x0, s0, d0 or q0.
517
518define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind {
519; CHECK-LABEL: store-post-indexed-word
520; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16
521entry:
522  %gep1 = getelementptr i32* %array, i64 2
523  br label %body
524
525body:
526  %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
527  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
528  %gep2 = getelementptr i32* %iv2, i64 -1
529  %load = load i32* %gep2
530  call void @use-word(i32 %load)
531  store i32 %val, i32* %iv2
532  %iv.next = add i64 %iv, -4
533  %gep3 = getelementptr i32* %iv2, i64 4
534  %cond = icmp eq i64 %iv.next, 0
535  br i1 %cond, label %exit, label %body
536
537exit:
538  ret void
539}
540
541define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind {
542; CHECK-LABEL: store-post-indexed-doubleword
543; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32
544entry:
545  %gep1 = getelementptr i64* %array, i64 2
546  br label %body
547
548body:
549  %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
550  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
551  %gep2 = getelementptr i64* %iv2, i64 -1
552  %load = load i64* %gep2
553  call void @use-doubleword(i64 %load)
554  store i64 %val, i64* %iv2
555  %iv.next = add i64 %iv, -4
556  %gep3 = getelementptr i64* %iv2, i64 4
557  %cond = icmp eq i64 %iv.next, 0
558  br i1 %cond, label %exit, label %body
559
560exit:
561  ret void
562}
563
564define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind {
565; CHECK-LABEL: store-post-indexed-quadword
566; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64
567entry:
568  %gep1 = getelementptr <2 x i64>* %array, i64 2
569  br label %body
570
571body:
572  %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
573  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
574  %gep2 = getelementptr <2 x i64>* %iv2, i64 -1
575  %load = load <2 x i64>* %gep2
576  call void @use-quadword(<2 x i64> %load)
577  store <2 x i64> %val, <2 x i64>* %iv2
578  %iv.next = add i64 %iv, -4
579  %gep3 = getelementptr <2 x i64>* %iv2, i64 4
580  %cond = icmp eq i64 %iv.next, 0
581  br i1 %cond, label %exit, label %body
582
583exit:
584  ret void
585}
586
587define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind {
588; CHECK-LABEL: store-post-indexed-float
589; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16
590entry:
591  %gep1 = getelementptr float* %array, i64 2
592  br label %body
593
594body:
595  %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
596  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
597  %gep2 = getelementptr float* %iv2, i64 -1
598  %load = load float* %gep2
599  call void @use-float(float %load)
600  store float %val, float* %iv2
601  %iv.next = add i64 %iv, -4
602  %gep3 = getelementptr float* %iv2, i64 4
603  %cond = icmp eq i64 %iv.next, 0
604  br i1 %cond, label %exit, label %body
605
606exit:
607  ret void
608}
609
610define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind {
611; CHECK-LABEL: store-post-indexed-double
612; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32
613entry:
614  %gep1 = getelementptr double* %array, i64 2
615  br label %body
616
617body:
618  %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
619  %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
620  %gep2 = getelementptr double* %iv2, i64 -1
621  %load = load double* %gep2
622  call void @use-double(double %load)
623  store double %val, double* %iv2
624  %iv.next = add i64 %iv, -4
625  %gep3 = getelementptr double* %iv2, i64 4
626  %cond = icmp eq i64 %iv.next, 0
627  br i1 %cond, label %exit, label %body
628
629exit:
630  ret void
631}
632
633declare void @use-word(i32)
634declare void @use-doubleword(i64)
635declare void @use-quadword(<2 x i64>)
636declare void @use-float(float)
637declare void @use-double(double)
638
639; Check the following transform:
640;
641; (ldr|str) X, [x20]
642;  ...
643; sub x20, x20, #16
644;  ->
645; (ldr|str) X, [x20], #-16
646;
647; with X being either w0, x0, s0, d0 or q0.
648
649define void @post-indexed-sub-word(i32* %a, i32* %b, i64 %count) nounwind {
650; CHECK-LABEL: post-indexed-sub-word
651; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-8
652; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-8
653  br label %for.body
654for.body:
655  %phi1 = phi i32* [ %gep4, %for.body ], [ %b, %0 ]
656  %phi2 = phi i32* [ %gep3, %for.body ], [ %a, %0 ]
657  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
658  %gep1 = getelementptr i32* %phi1, i64 -1
659  %load1 = load i32* %gep1
660  %gep2 = getelementptr i32* %phi2, i64 -1
661  store i32 %load1, i32* %gep2
662  %load2 = load i32* %phi1
663  store i32 %load2, i32* %phi2
664  %dec.i = add nsw i64 %i, -1
665  %gep3 = getelementptr i32* %phi2, i64 -2
666  %gep4 = getelementptr i32* %phi1, i64 -2
667  %cond = icmp sgt i64 %dec.i, 0
668  br i1 %cond, label %for.body, label %end
669end:
670  ret void
671}
672
673define void @post-indexed-sub-doubleword(i64* %a, i64* %b, i64 %count) nounwind {
674; CHECK-LABEL: post-indexed-sub-doubleword
675; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-16
676; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-16
677  br label %for.body
678for.body:
679  %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
680  %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
681  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
682  %gep1 = getelementptr i64* %phi1, i64 -1
683  %load1 = load i64* %gep1
684  %gep2 = getelementptr i64* %phi2, i64 -1
685  store i64 %load1, i64* %gep2
686  %load2 = load i64* %phi1
687  store i64 %load2, i64* %phi2
688  %dec.i = add nsw i64 %i, -1
689  %gep3 = getelementptr i64* %phi2, i64 -2
690  %gep4 = getelementptr i64* %phi1, i64 -2
691  %cond = icmp sgt i64 %dec.i, 0
692  br i1 %cond, label %for.body, label %end
693end:
694  ret void
695}
696
697define void @post-indexed-sub-quadword(<2 x i64>* %a, <2 x i64>* %b, i64 %count) nounwind {
698; CHECK-LABEL: post-indexed-sub-quadword
699; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-32
700; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-32
701  br label %for.body
702for.body:
703  %phi1 = phi <2 x i64>* [ %gep4, %for.body ], [ %b, %0 ]
704  %phi2 = phi <2 x i64>* [ %gep3, %for.body ], [ %a, %0 ]
705  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
706  %gep1 = getelementptr <2 x i64>* %phi1, i64 -1
707  %load1 = load <2 x i64>* %gep1
708  %gep2 = getelementptr <2 x i64>* %phi2, i64 -1
709  store <2 x i64> %load1, <2 x i64>* %gep2
710  %load2 = load <2 x i64>* %phi1
711  store <2 x i64> %load2, <2 x i64>* %phi2
712  %dec.i = add nsw i64 %i, -1
713  %gep3 = getelementptr <2 x i64>* %phi2, i64 -2
714  %gep4 = getelementptr <2 x i64>* %phi1, i64 -2
715  %cond = icmp sgt i64 %dec.i, 0
716  br i1 %cond, label %for.body, label %end
717end:
718  ret void
719}
720
721define void @post-indexed-sub-float(float* %a, float* %b, i64 %count) nounwind {
722; CHECK-LABEL: post-indexed-sub-float
723; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-8
724; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-8
725  br label %for.body
726for.body:
727  %phi1 = phi float* [ %gep4, %for.body ], [ %b, %0 ]
728  %phi2 = phi float* [ %gep3, %for.body ], [ %a, %0 ]
729  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
730  %gep1 = getelementptr float* %phi1, i64 -1
731  %load1 = load float* %gep1
732  %gep2 = getelementptr float* %phi2, i64 -1
733  store float %load1, float* %gep2
734  %load2 = load float* %phi1
735  store float %load2, float* %phi2
736  %dec.i = add nsw i64 %i, -1
737  %gep3 = getelementptr float* %phi2, i64 -2
738  %gep4 = getelementptr float* %phi1, i64 -2
739  %cond = icmp sgt i64 %dec.i, 0
740  br i1 %cond, label %for.body, label %end
741end:
742  ret void
743}
744
745define void @post-indexed-sub-double(double* %a, double* %b, i64 %count) nounwind {
746; CHECK-LABEL: post-indexed-sub-double
747; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-16
748; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-16
749  br label %for.body
750for.body:
751  %phi1 = phi double* [ %gep4, %for.body ], [ %b, %0 ]
752  %phi2 = phi double* [ %gep3, %for.body ], [ %a, %0 ]
753  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
754  %gep1 = getelementptr double* %phi1, i64 -1
755  %load1 = load double* %gep1
756  %gep2 = getelementptr double* %phi2, i64 -1
757  store double %load1, double* %gep2
758  %load2 = load double* %phi1
759  store double %load2, double* %phi2
760  %dec.i = add nsw i64 %i, -1
761  %gep3 = getelementptr double* %phi2, i64 -2
762  %gep4 = getelementptr double* %phi1, i64 -2
763  %cond = icmp sgt i64 %dec.i, 0
764  br i1 %cond, label %for.body, label %end
765end:
766  ret void
767}
768