[WinEH] Add some test cases I forgot to add to previous commits
[oota-llvm.git] / test / CodeGen / AArch64 / ldst-opt.ll
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
27 declare void @bar_word(%s.word*, i32)
28
29 define 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]!
32 entry:
33   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
34   %add = load i32, i32* %a, align 4
35   br label %bar
36 bar:
37   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
38   tail call void @bar_word(%s.word* %c, i32 %add)
39   ret void
40 }
41
42 define 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]!
45 entry:
46   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
47   store i32 %val, i32* %a, align 4
48   br label %bar
49 bar:
50   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
51   tail call void @bar_word(%s.word* %c, i32 %val)
52   ret void
53 }
54
55 declare void @bar_doubleword(%s.doubleword*, i64)
56
57 define 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]!
60 entry:
61   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
62   %add = load i64, i64* %a, align 4
63   br label %bar
64 bar:
65   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
66   tail call void @bar_doubleword(%s.doubleword* %c, i64 %add)
67   ret void
68 }
69
70 define 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]!
73 entry:
74   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
75   store i64 %val, i64* %a, align 4
76   br label %bar
77 bar:
78   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
79   tail call void @bar_doubleword(%s.doubleword* %c, i64 %val)
80   ret void
81 }
82
83 declare void @bar_quadword(%s.quadword*, fp128)
84
85 define 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]!
88 entry:
89   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
90   %add = load fp128, fp128* %a, align 4
91   br label %bar
92 bar:
93   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
94   tail call void @bar_quadword(%s.quadword* %c, fp128 %add)
95   ret void
96 }
97
98 define 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]!
101 entry:
102   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
103   store fp128 %val, fp128* %a, align 4
104   br label %bar
105 bar:
106   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
107   tail call void @bar_quadword(%s.quadword* %c, fp128 %val)
108   ret void
109 }
110
111 declare void @bar_float(%s.float*, float)
112
113 define 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]!
116 entry:
117   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
118   %add = load float, float* %a, align 4
119   br label %bar
120 bar:
121   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
122   tail call void @bar_float(%s.float* %c, float %add)
123   ret void
124 }
125
126 define 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]!
129 entry:
130   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
131   store float %val, float* %a, align 4
132   br label %bar
133 bar:
134   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
135   tail call void @bar_float(%s.float* %c, float %val)
136   ret void
137 }
138
139 declare void @bar_double(%s.double*, double)
140
141 define 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]!
144 entry:
145   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
146   %add = load double, double* %a, align 4
147   br label %bar
148 bar:
149   %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1
150   tail call void @bar_double(%s.double* %c, double %add)
151   ret void
152 }
153
154 define 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]!
157 entry:
158   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
159   store double %val, double* %a, align 4
160   br label %bar
161 bar:
162   %c = getelementptr inbounds %struct.double, %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
183 define 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
188 if.then:
189   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
190   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
191   br label %return
192 if.end:
193   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
194   br label %return
195 return:
196   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
197   %ret = load i32, i32* %retptr
198   ret i32 %ret
199 }
200
201 define 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
206 if.then:
207   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
208   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1
209   br label %return
210 if.end:
211   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
212   br label %return
213 return:
214   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
215   %ret = load i64, i64* %retptr
216   ret i64 %ret
217 }
218
219 define <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
224 if.then:
225   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
226   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
227   br label %return
228 if.end:
229   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
230   br label %return
231 return:
232   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
233   %ret = load <2 x i64>, <2 x i64>* %retptr
234   ret <2 x i64> %ret
235 }
236
237 define 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
242 if.then:
243   %load1 = load %pre.struct.float*, %pre.struct.float** %this
244   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
245   br label %return
246 if.end:
247   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
248   br label %return
249 return:
250   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
251   %ret = load float, float* %retptr
252   ret float %ret
253 }
254
255 define 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
260 if.then:
261   %load1 = load %pre.struct.double*, %pre.struct.double** %this
262   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
263   br label %return
264 if.end:
265   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
266   br label %return
267 return:
268   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
269   %ret = load double, 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
283 define 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
289 if.then:
290   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
291   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
292   br label %return
293 if.end:
294   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
295   br label %return
296 return:
297   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
298   store i32 %val, i32* %retptr
299   ret void
300 }
301
302 define 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
308 if.then:
309   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
310   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1
311   br label %return
312 if.end:
313   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
314   br label %return
315 return:
316   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
317   store i64 %val, i64* %retptr
318   ret void
319 }
320
321 define 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
327 if.then:
328   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
329   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
330   br label %return
331 if.end:
332   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
333   br label %return
334 return:
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
340 define 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
346 if.then:
347   %load1 = load %pre.struct.float*, %pre.struct.float** %this
348   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
349   br label %return
350 if.end:
351   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
352   br label %return
353 return:
354   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
355   store float %val, float* %retptr
356   ret void
357 }
358
359 define 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
365 if.then:
366   %load1 = load %pre.struct.double*, %pre.struct.double** %this
367   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
368   br label %return
369 if.end:
370   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
371   br label %return
372 return:
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
388 define 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
391 entry:
392   %gep1 = getelementptr i32, i32* %array, i64 2
393   br label %body
394
395 body:
396   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
397   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
398   %gep2 = getelementptr i32, i32* %iv2, i64 -1
399   %load = load i32, i32* %gep2
400   call void @use-word(i32 %load)
401   %load2 = load i32, i32* %iv2
402   call void @use-word(i32 %load2)
403   %iv.next = add i64 %iv, -4
404   %gep3 = getelementptr i32, i32* %iv2, i64 4
405   %cond = icmp eq i64 %iv.next, 0
406   br i1 %cond, label %exit, label %body
407
408 exit:
409   ret void
410 }
411
412 define 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
415 entry:
416   %gep1 = getelementptr i64, i64* %array, i64 2
417   br label %body
418
419 body:
420   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
421   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
422   %gep2 = getelementptr i64, i64* %iv2, i64 -1
423   %load = load i64, i64* %gep2
424   call void @use-doubleword(i64 %load)
425   %load2 = load i64, i64* %iv2
426   call void @use-doubleword(i64 %load2)
427   %iv.next = add i64 %iv, -4
428   %gep3 = getelementptr i64, i64* %iv2, i64 4
429   %cond = icmp eq i64 %iv.next, 0
430   br i1 %cond, label %exit, label %body
431
432 exit:
433   ret void
434 }
435
436 define 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
439 entry:
440   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
441   br label %body
442
443 body:
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>, <2 x i64>* %iv2, i64 -1
447   %load = load <2 x i64>, <2 x i64>* %gep2
448   call void @use-quadword(<2 x i64> %load)
449   %load2 = load <2 x i64>, <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>, <2 x i64>* %iv2, i64 4
453   %cond = icmp eq i64 %iv.next, 0
454   br i1 %cond, label %exit, label %body
455
456 exit:
457   ret void
458 }
459
460 define 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
463 entry:
464   %gep1 = getelementptr float, float* %array, i64 2
465   br label %body
466
467 body:
468   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
469   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
470   %gep2 = getelementptr float, float* %iv2, i64 -1
471   %load = load float, float* %gep2
472   call void @use-float(float %load)
473   %load2 = load float, float* %iv2
474   call void @use-float(float %load2)
475   %iv.next = add i64 %iv, -4
476   %gep3 = getelementptr float, float* %iv2, i64 4
477   %cond = icmp eq i64 %iv.next, 0
478   br i1 %cond, label %exit, label %body
479
480 exit:
481   ret void
482 }
483
484 define 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
487 entry:
488   %gep1 = getelementptr double, double* %array, i64 2
489   br label %body
490
491 body:
492   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
493   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
494   %gep2 = getelementptr double, double* %iv2, i64 -1
495   %load = load double, double* %gep2
496   call void @use-double(double %load)
497   %load2 = load double, double* %iv2
498   call void @use-double(double %load2)
499   %iv.next = add i64 %iv, -4
500   %gep3 = getelementptr double, double* %iv2, i64 4
501   %cond = icmp eq i64 %iv.next, 0
502   br i1 %cond, label %exit, label %body
503
504 exit:
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
518 define 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
521 entry:
522   %gep1 = getelementptr i32, i32* %array, i64 2
523   br label %body
524
525 body:
526   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
527   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
528   %gep2 = getelementptr i32, i32* %iv2, i64 -1
529   %load = load i32, 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, i32* %iv2, i64 4
534   %cond = icmp eq i64 %iv.next, 0
535   br i1 %cond, label %exit, label %body
536
537 exit:
538   ret void
539 }
540
541 define 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
544 entry:
545   %gep1 = getelementptr i64, i64* %array, i64 2
546   br label %body
547
548 body:
549   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
550   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
551   %gep2 = getelementptr i64, i64* %iv2, i64 -1
552   %load = load i64, 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, i64* %iv2, i64 4
557   %cond = icmp eq i64 %iv.next, 0
558   br i1 %cond, label %exit, label %body
559
560 exit:
561   ret void
562 }
563
564 define 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
567 entry:
568   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
569   br label %body
570
571 body:
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>, <2 x i64>* %iv2, i64 -1
575   %load = load <2 x i64>, <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>, <2 x i64>* %iv2, i64 4
580   %cond = icmp eq i64 %iv.next, 0
581   br i1 %cond, label %exit, label %body
582
583 exit:
584   ret void
585 }
586
587 define 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
590 entry:
591   %gep1 = getelementptr float, float* %array, i64 2
592   br label %body
593
594 body:
595   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
596   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
597   %gep2 = getelementptr float, float* %iv2, i64 -1
598   %load = load float, 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, float* %iv2, i64 4
603   %cond = icmp eq i64 %iv.next, 0
604   br i1 %cond, label %exit, label %body
605
606 exit:
607   ret void
608 }
609
610 define 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
613 entry:
614   %gep1 = getelementptr double, double* %array, i64 2
615   br label %body
616
617 body:
618   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
619   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
620   %gep2 = getelementptr double, double* %iv2, i64 -1
621   %load = load double, 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, double* %iv2, i64 4
626   %cond = icmp eq i64 %iv.next, 0
627   br i1 %cond, label %exit, label %body
628
629 exit:
630   ret void
631 }
632
633 declare void @use-word(i32)
634 declare void @use-doubleword(i64)
635 declare void @use-quadword(<2 x i64>)
636 declare void @use-float(float)
637 declare 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
649 define 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
654 for.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, i32* %phi1, i64 -1
659   %load1 = load i32, i32* %gep1
660   %gep2 = getelementptr i32, i32* %phi2, i64 -1
661   store i32 %load1, i32* %gep2
662   %load2 = load i32, i32* %phi1
663   store i32 %load2, i32* %phi2
664   %dec.i = add nsw i64 %i, -1
665   %gep3 = getelementptr i32, i32* %phi2, i64 -2
666   %gep4 = getelementptr i32, i32* %phi1, i64 -2
667   %cond = icmp sgt i64 %dec.i, 0
668   br i1 %cond, label %for.body, label %end
669 end:
670   ret void
671 }
672
673 define 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
678 for.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, i64* %phi1, i64 -1
683   %load1 = load i64, i64* %gep1
684   %gep2 = getelementptr i64, i64* %phi2, i64 -1
685   store i64 %load1, i64* %gep2
686   %load2 = load i64, i64* %phi1
687   store i64 %load2, i64* %phi2
688   %dec.i = add nsw i64 %i, -1
689   %gep3 = getelementptr i64, i64* %phi2, i64 -2
690   %gep4 = getelementptr i64, i64* %phi1, i64 -2
691   %cond = icmp sgt i64 %dec.i, 0
692   br i1 %cond, label %for.body, label %end
693 end:
694   ret void
695 }
696
697 define 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
702 for.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>, <2 x i64>* %phi1, i64 -1
707   %load1 = load <2 x i64>, <2 x i64>* %gep1
708   %gep2 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -1
709   store <2 x i64> %load1, <2 x i64>* %gep2
710   %load2 = load <2 x i64>, <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>, <2 x i64>* %phi2, i64 -2
714   %gep4 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -2
715   %cond = icmp sgt i64 %dec.i, 0
716   br i1 %cond, label %for.body, label %end
717 end:
718   ret void
719 }
720
721 define 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
726 for.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, float* %phi1, i64 -1
731   %load1 = load float, float* %gep1
732   %gep2 = getelementptr float, float* %phi2, i64 -1
733   store float %load1, float* %gep2
734   %load2 = load float, float* %phi1
735   store float %load2, float* %phi2
736   %dec.i = add nsw i64 %i, -1
737   %gep3 = getelementptr float, float* %phi2, i64 -2
738   %gep4 = getelementptr float, float* %phi1, i64 -2
739   %cond = icmp sgt i64 %dec.i, 0
740   br i1 %cond, label %for.body, label %end
741 end:
742   ret void
743 }
744
745 define 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
750 for.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, double* %phi1, i64 -1
755   %load1 = load double, double* %gep1
756   %gep2 = getelementptr double, double* %phi2, i64 -1
757   store double %load1, double* %gep2
758   %load2 = load double, double* %phi1
759   store double %load2, double* %phi2
760   %dec.i = add nsw i64 %i, -1
761   %gep3 = getelementptr double, double* %phi2, i64 -2
762   %gep4 = getelementptr double, double* %phi1, i64 -2
763   %cond = icmp sgt i64 %dec.i, 0
764   br i1 %cond, label %for.body, label %end
765 end:
766   ret void
767 }