Merging r258471:
[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.byte = type { i8, i8 }
7 %s.halfword = type { i16, i16 }
8 %s.word = type { i32, i32 }
9 %s.doubleword = type { i64, i32 }
10 %s.quadword = type { fp128, i32 }
11 %s.float = type { float, i32 }
12 %s.double = type { double, i32 }
13 %struct.byte = type { %padding, %s.byte }
14 %struct.halfword = type { %padding, %s.halfword }
15 %struct.word = type { %padding, %s.word }
16 %struct.doubleword = type { %padding, %s.doubleword }
17 %struct.quadword = type { %padding, %s.quadword }
18 %struct.float = type { %padding, %s.float }
19 %struct.double = type { %padding, %s.double }
20
21 ; Check the following transform:
22 ;
23 ; (ldr|str) X, [x0, #32]
24 ;  ...
25 ; add x0, x0, #32
26 ;  ->
27 ; (ldr|str) X, [x0, #32]!
28 ;
29 ; with X being either w1, x1, s0, d0 or q0.
30
31 declare void @bar_byte(%s.byte*, i8)
32
33 define void @load-pre-indexed-byte(%struct.byte* %ptr) nounwind {
34 ; CHECK-LABEL: load-pre-indexed-byte
35 ; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
36 entry:
37   %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0
38   %add = load i8, i8* %a, align 4
39   br label %bar
40 bar:
41   %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1
42   tail call void @bar_byte(%s.byte* %c, i8 %add)
43   ret void
44 }
45
46 define void @store-pre-indexed-byte(%struct.byte* %ptr, i8 %val) nounwind {
47 ; CHECK-LABEL: store-pre-indexed-byte
48 ; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
49 entry:
50   %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0
51   store i8 %val, i8* %a, align 4
52   br label %bar
53 bar:
54   %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1
55   tail call void @bar_byte(%s.byte* %c, i8 %val)
56   ret void
57 }
58
59 declare void @bar_halfword(%s.halfword*, i16)
60
61 define void @load-pre-indexed-halfword(%struct.halfword* %ptr) nounwind {
62 ; CHECK-LABEL: load-pre-indexed-halfword
63 ; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
64 entry:
65   %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0
66   %add = load i16, i16* %a, align 4
67   br label %bar
68 bar:
69   %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1
70   tail call void @bar_halfword(%s.halfword* %c, i16 %add)
71   ret void
72 }
73
74 define void @store-pre-indexed-halfword(%struct.halfword* %ptr, i16 %val) nounwind {
75 ; CHECK-LABEL: store-pre-indexed-halfword
76 ; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
77 entry:
78   %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0
79   store i16 %val, i16* %a, align 4
80   br label %bar
81 bar:
82   %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1
83   tail call void @bar_halfword(%s.halfword* %c, i16 %val)
84   ret void
85 }
86
87 declare void @bar_word(%s.word*, i32)
88
89 define void @load-pre-indexed-word(%struct.word* %ptr) nounwind {
90 ; CHECK-LABEL: load-pre-indexed-word
91 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
92 entry:
93   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
94   %add = load i32, i32* %a, align 4
95   br label %bar
96 bar:
97   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
98   tail call void @bar_word(%s.word* %c, i32 %add)
99   ret void
100 }
101
102 define void @store-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind {
103 ; CHECK-LABEL: store-pre-indexed-word
104 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
105 entry:
106   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
107   store i32 %val, i32* %a, align 4
108   br label %bar
109 bar:
110   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
111   tail call void @bar_word(%s.word* %c, i32 %val)
112   ret void
113 }
114
115 declare void @bar_doubleword(%s.doubleword*, i64)
116
117 define void @load-pre-indexed-doubleword(%struct.doubleword* %ptr) nounwind {
118 ; CHECK-LABEL: load-pre-indexed-doubleword
119 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
120 entry:
121   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
122   %add = load i64, i64* %a, align 4
123   br label %bar
124 bar:
125   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
126   tail call void @bar_doubleword(%s.doubleword* %c, i64 %add)
127   ret void
128 }
129
130 define void @store-pre-indexed-doubleword(%struct.doubleword* %ptr, i64 %val) nounwind {
131 ; CHECK-LABEL: store-pre-indexed-doubleword
132 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
133 entry:
134   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
135   store i64 %val, i64* %a, align 4
136   br label %bar
137 bar:
138   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
139   tail call void @bar_doubleword(%s.doubleword* %c, i64 %val)
140   ret void
141 }
142
143 declare void @bar_quadword(%s.quadword*, fp128)
144
145 define void @load-pre-indexed-quadword(%struct.quadword* %ptr) nounwind {
146 ; CHECK-LABEL: load-pre-indexed-quadword
147 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
148 entry:
149   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
150   %add = load fp128, fp128* %a, align 4
151   br label %bar
152 bar:
153   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
154   tail call void @bar_quadword(%s.quadword* %c, fp128 %add)
155   ret void
156 }
157
158 define void @store-pre-indexed-quadword(%struct.quadword* %ptr, fp128 %val) nounwind {
159 ; CHECK-LABEL: store-pre-indexed-quadword
160 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
161 entry:
162   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
163   store fp128 %val, fp128* %a, align 4
164   br label %bar
165 bar:
166   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
167   tail call void @bar_quadword(%s.quadword* %c, fp128 %val)
168   ret void
169 }
170
171 declare void @bar_float(%s.float*, float)
172
173 define void @load-pre-indexed-float(%struct.float* %ptr) nounwind {
174 ; CHECK-LABEL: load-pre-indexed-float
175 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
176 entry:
177   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
178   %add = load float, float* %a, align 4
179   br label %bar
180 bar:
181   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
182   tail call void @bar_float(%s.float* %c, float %add)
183   ret void
184 }
185
186 define void @store-pre-indexed-float(%struct.float* %ptr, float %val) nounwind {
187 ; CHECK-LABEL: store-pre-indexed-float
188 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
189 entry:
190   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
191   store float %val, float* %a, align 4
192   br label %bar
193 bar:
194   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
195   tail call void @bar_float(%s.float* %c, float %val)
196   ret void
197 }
198
199 declare void @bar_double(%s.double*, double)
200
201 define void @load-pre-indexed-double(%struct.double* %ptr) nounwind {
202 ; CHECK-LABEL: load-pre-indexed-double
203 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
204 entry:
205   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
206   %add = load double, double* %a, align 4
207   br label %bar
208 bar:
209   %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1
210   tail call void @bar_double(%s.double* %c, double %add)
211   ret void
212 }
213
214 define void @store-pre-indexed-double(%struct.double* %ptr, double %val) nounwind {
215 ; CHECK-LABEL: store-pre-indexed-double
216 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
217 entry:
218   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
219   store double %val, double* %a, align 4
220   br label %bar
221 bar:
222   %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1
223   tail call void @bar_double(%s.double* %c, double %val)
224   ret void
225 }
226
227 ; Check the following transform:
228 ;
229 ; (ldp|stp) w1, w2 [x0, #32]
230 ;  ...
231 ; add x0, x0, #32
232 ;  ->
233 ; (ldp|stp) w1, w2, [x0, #32]!
234 ;
235
236 define void @load-pair-pre-indexed-word(%struct.word* %ptr) nounwind {
237 ; CHECK-LABEL: load-pair-pre-indexed-word
238 ; CHECK: ldp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!
239 ; CHECK-NOT: add x0, x0, #32
240 entry:
241   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
242   %a1 = load i32, i32* %a, align 4
243   %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1
244   %b1 = load i32, i32* %b, align 4
245   %add = add i32 %a1, %b1
246   br label %bar
247 bar:
248   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
249   tail call void @bar_word(%s.word* %c, i32 %add)
250   ret void
251 }
252
253 define void @store-pair-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind {
254 ; CHECK-LABEL: store-pair-pre-indexed-word
255 ; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!
256 ; CHECK-NOT: add x0, x0, #32
257 entry:
258   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
259   store i32 %val, i32* %a, align 4
260   %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1
261   store i32 %val, i32* %b, align 4
262   br label %bar
263 bar:
264   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
265   tail call void @bar_word(%s.word* %c, i32 %val)
266   ret void
267 }
268
269 ; Check the following transform:
270 ;
271 ; add x8, x8, #16
272 ;  ...
273 ; ldr X, [x8]
274 ;  ->
275 ; ldr X, [x8, #16]!
276 ;
277 ; with X being either w0, x0, s0, d0 or q0.
278
279 %pre.struct.i32 = type { i32, i32, i32, i32, i32}
280 %pre.struct.i64 = type { i32, i64, i64, i64, i64}
281 %pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>, <2 x i64>}
282 %pre.struct.float = type { i32, float, float, float}
283 %pre.struct.double = type { i32, double, double, double}
284
285 define i32 @load-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
286                                    %pre.struct.i32* %load2) nounwind {
287 ; CHECK-LABEL: load-pre-indexed-word2
288 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
289   br i1 %cond, label %if.then, label %if.end
290 if.then:
291   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
292   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
293   br label %return
294 if.end:
295   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
296   br label %return
297 return:
298   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
299   %ret = load i32, i32* %retptr
300   ret i32 %ret
301 }
302
303 define i64 @load-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
304                                          %pre.struct.i64* %load2) nounwind {
305 ; CHECK-LABEL: load-pre-indexed-doubleword2
306 ; CHECK: ldr 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   %ret = load i64, i64* %retptr
318   ret i64 %ret
319 }
320
321 define <2 x i64> @load-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
322                                              %pre.struct.i128* %load2) nounwind {
323 ; CHECK-LABEL: load-pre-indexed-quadword2
324 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
325   br i1 %cond, label %if.then, label %if.end
326 if.then:
327   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
328   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
329   br label %return
330 if.end:
331   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
332   br label %return
333 return:
334   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
335   %ret = load <2 x i64>, <2 x i64>* %retptr
336   ret <2 x i64> %ret
337 }
338
339 define float @load-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
340                                       %pre.struct.float* %load2) nounwind {
341 ; CHECK-LABEL: load-pre-indexed-float2
342 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
343   br i1 %cond, label %if.then, label %if.end
344 if.then:
345   %load1 = load %pre.struct.float*, %pre.struct.float** %this
346   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
347   br label %return
348 if.end:
349   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
350   br label %return
351 return:
352   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
353   %ret = load float, float* %retptr
354   ret float %ret
355 }
356
357 define double @load-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
358                                         %pre.struct.double* %load2) nounwind {
359 ; CHECK-LABEL: load-pre-indexed-double2
360 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
361   br i1 %cond, label %if.then, label %if.end
362 if.then:
363   %load1 = load %pre.struct.double*, %pre.struct.double** %this
364   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
365   br label %return
366 if.end:
367   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
368   br label %return
369 return:
370   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
371   %ret = load double, double* %retptr
372   ret double %ret
373 }
374
375 define i32 @load-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond,
376                                    %pre.struct.i32* %load2) nounwind {
377 ; CHECK-LABEL: load-pre-indexed-word3
378 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #12]!
379   br i1 %cond, label %if.then, label %if.end
380 if.then:
381   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
382   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3
383   br label %return
384 if.end:
385   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
386   br label %return
387 return:
388   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
389   %ret = load i32, i32* %retptr
390   ret i32 %ret
391 }
392
393 define i64 @load-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond,
394                                          %pre.struct.i64* %load2) nounwind {
395 ; CHECK-LABEL: load-pre-indexed-doubleword3
396 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #16]!
397   br i1 %cond, label %if.then, label %if.end
398 if.then:
399   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
400   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 2
401   br label %return
402 if.end:
403   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 3
404   br label %return
405 return:
406   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
407   %ret = load i64, i64* %retptr
408   ret i64 %ret
409 }
410
411 define <2 x i64> @load-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond,
412                                              %pre.struct.i128* %load2) nounwind {
413 ; CHECK-LABEL: load-pre-indexed-quadword3
414 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
415   br i1 %cond, label %if.then, label %if.end
416 if.then:
417   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
418   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2
419   br label %return
420 if.end:
421   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
422   br label %return
423 return:
424   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
425   %ret = load <2 x i64>, <2 x i64>* %retptr
426   ret <2 x i64> %ret
427 }
428
429 define float @load-pre-indexed-float3(%pre.struct.float** %this, i1 %cond,
430                                       %pre.struct.float* %load2) nounwind {
431 ; CHECK-LABEL: load-pre-indexed-float3
432 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #8]!
433   br i1 %cond, label %if.then, label %if.end
434 if.then:
435   %load1 = load %pre.struct.float*, %pre.struct.float** %this
436   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2
437   br label %return
438 if.end:
439   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
440   br label %return
441 return:
442   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
443   %ret = load float, float* %retptr
444   ret float %ret
445 }
446
447 define double @load-pre-indexed-double3(%pre.struct.double** %this, i1 %cond,
448                                         %pre.struct.double* %load2) nounwind {
449 ; CHECK-LABEL: load-pre-indexed-double3
450 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #16]!
451   br i1 %cond, label %if.then, label %if.end
452 if.then:
453   %load1 = load %pre.struct.double*, %pre.struct.double** %this
454   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2
455   br label %return
456 if.end:
457   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
458   br label %return
459 return:
460   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
461   %ret = load double, double* %retptr
462   ret double %ret
463 }
464
465 ; Check the following transform:
466 ;
467 ; add x8, x8, #16
468 ;  ...
469 ; str X, [x8]
470 ;  ->
471 ; str X, [x8, #16]!
472 ;
473 ; with X being either w0, x0, s0, d0 or q0.
474
475 define void @store-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
476                                      %pre.struct.i32* %load2,
477                                      i32 %val) nounwind {
478 ; CHECK-LABEL: store-pre-indexed-word2
479 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
480   br i1 %cond, label %if.then, label %if.end
481 if.then:
482   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
483   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
484   br label %return
485 if.end:
486   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
487   br label %return
488 return:
489   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
490   store i32 %val, i32* %retptr
491   ret void
492 }
493
494 define void @store-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
495                                            %pre.struct.i64* %load2,
496                                            i64 %val) nounwind {
497 ; CHECK-LABEL: store-pre-indexed-doubleword2
498 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]!
499   br i1 %cond, label %if.then, label %if.end
500 if.then:
501   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
502   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1
503   br label %return
504 if.end:
505   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
506   br label %return
507 return:
508   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
509   store i64 %val, i64* %retptr
510   ret void
511 }
512
513 define void @store-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
514                                          %pre.struct.i128* %load2,
515                                          <2 x i64> %val) nounwind {
516 ; CHECK-LABEL: store-pre-indexed-quadword2
517 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
518   br i1 %cond, label %if.then, label %if.end
519 if.then:
520   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
521   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
522   br label %return
523 if.end:
524   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
525   br label %return
526 return:
527   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
528   store <2 x i64> %val, <2 x i64>* %retptr
529   ret void
530 }
531
532 define void @store-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
533                                       %pre.struct.float* %load2,
534                                       float %val) nounwind {
535 ; CHECK-LABEL: store-pre-indexed-float2
536 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
537   br i1 %cond, label %if.then, label %if.end
538 if.then:
539   %load1 = load %pre.struct.float*, %pre.struct.float** %this
540   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
541   br label %return
542 if.end:
543   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
544   br label %return
545 return:
546   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
547   store float %val, float* %retptr
548   ret void
549 }
550
551 define void @store-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
552                                       %pre.struct.double* %load2,
553                                       double %val) nounwind {
554 ; CHECK-LABEL: store-pre-indexed-double2
555 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
556   br i1 %cond, label %if.then, label %if.end
557 if.then:
558   %load1 = load %pre.struct.double*, %pre.struct.double** %this
559   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
560   br label %return
561 if.end:
562   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
563   br label %return
564 return:
565   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
566   store double %val, double* %retptr
567   ret void
568 }
569
570 define void @store-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond,
571                                      %pre.struct.i32* %load2,
572                                      i32 %val) nounwind {
573 ; CHECK-LABEL: store-pre-indexed-word3
574 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #12]!
575   br i1 %cond, label %if.then, label %if.end
576 if.then:
577   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
578   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3
579   br label %return
580 if.end:
581   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
582   br label %return
583 return:
584   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
585   store i32 %val, i32* %retptr
586   ret void
587 }
588
589 define void @store-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond,
590                                            %pre.struct.i64* %load2,
591                                            i64 %val) nounwind {
592 ; CHECK-LABEL: store-pre-indexed-doubleword3
593 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #24]!
594   br i1 %cond, label %if.then, label %if.end
595 if.then:
596   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
597   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 3
598   br label %return
599 if.end:
600   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 4
601   br label %return
602 return:
603   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
604   store i64 %val, i64* %retptr
605   ret void
606 }
607
608 define void @store-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond,
609                                          %pre.struct.i128* %load2,
610                                          <2 x i64> %val) nounwind {
611 ; CHECK-LABEL: store-pre-indexed-quadword3
612 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
613   br i1 %cond, label %if.then, label %if.end
614 if.then:
615   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
616   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2
617   br label %return
618 if.end:
619   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
620   br label %return
621 return:
622   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
623   store <2 x i64> %val, <2 x i64>* %retptr
624   ret void
625 }
626
627 define void @store-pre-indexed-float3(%pre.struct.float** %this, i1 %cond,
628                                       %pre.struct.float* %load2,
629                                       float %val) nounwind {
630 ; CHECK-LABEL: store-pre-indexed-float3
631 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #8]!
632   br i1 %cond, label %if.then, label %if.end
633 if.then:
634   %load1 = load %pre.struct.float*, %pre.struct.float** %this
635   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2
636   br label %return
637 if.end:
638   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
639   br label %return
640 return:
641   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
642   store float %val, float* %retptr
643   ret void
644 }
645
646 define void @store-pre-indexed-double3(%pre.struct.double** %this, i1 %cond,
647                                       %pre.struct.double* %load2,
648                                       double %val) nounwind {
649 ; CHECK-LABEL: store-pre-indexed-double3
650 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #16]!
651   br i1 %cond, label %if.then, label %if.end
652 if.then:
653   %load1 = load %pre.struct.double*, %pre.struct.double** %this
654   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2
655   br label %return
656 if.end:
657   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
658   br label %return
659 return:
660   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
661   store double %val, double* %retptr
662   ret void
663 }
664
665 ; Check the following transform:
666 ;
667 ; ldr X, [x20]
668 ;  ...
669 ; add x20, x20, #32
670 ;  ->
671 ; ldr X, [x20], #32
672 ;
673 ; with X being either w0, x0, s0, d0 or q0.
674
675 define void @load-post-indexed-byte(i8* %array, i64 %count) nounwind {
676 ; CHECK-LABEL: load-post-indexed-byte
677 ; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}], #4
678 entry:
679   %gep1 = getelementptr i8, i8* %array, i64 2
680   br label %body
681
682 body:
683   %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ]
684   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
685   %gep2 = getelementptr i8, i8* %iv2, i64 -1
686   %load = load i8, i8* %gep2
687   call void @use-byte(i8 %load)
688   %load2 = load i8, i8* %iv2
689   call void @use-byte(i8 %load2)
690   %iv.next = add i64 %iv, -4
691   %gep3 = getelementptr i8, i8* %iv2, i64 4
692   %cond = icmp eq i64 %iv.next, 0
693   br i1 %cond, label %exit, label %body
694
695 exit:
696   ret void
697 }
698
699 define void @load-post-indexed-halfword(i16* %array, i64 %count) nounwind {
700 ; CHECK-LABEL: load-post-indexed-halfword
701 ; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}], #8
702 entry:
703   %gep1 = getelementptr i16, i16* %array, i64 2
704   br label %body
705
706 body:
707   %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ]
708   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
709   %gep2 = getelementptr i16, i16* %iv2, i64 -1
710   %load = load i16, i16* %gep2
711   call void @use-halfword(i16 %load)
712   %load2 = load i16, i16* %iv2
713   call void @use-halfword(i16 %load2)
714   %iv.next = add i64 %iv, -4
715   %gep3 = getelementptr i16, i16* %iv2, i64 4
716   %cond = icmp eq i64 %iv.next, 0
717   br i1 %cond, label %exit, label %body
718
719 exit:
720   ret void
721 }
722
723 define void @load-post-indexed-word(i32* %array, i64 %count) nounwind {
724 ; CHECK-LABEL: load-post-indexed-word
725 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16
726 entry:
727   %gep1 = getelementptr i32, i32* %array, i64 2
728   br label %body
729
730 body:
731   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
732   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
733   %gep2 = getelementptr i32, i32* %iv2, i64 -1
734   %load = load i32, i32* %gep2
735   call void @use-word(i32 %load)
736   %load2 = load i32, i32* %iv2
737   call void @use-word(i32 %load2)
738   %iv.next = add i64 %iv, -4
739   %gep3 = getelementptr i32, i32* %iv2, i64 4
740   %cond = icmp eq i64 %iv.next, 0
741   br i1 %cond, label %exit, label %body
742
743 exit:
744   ret void
745 }
746
747 define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind {
748 ; CHECK-LABEL: load-post-indexed-doubleword
749 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32
750 entry:
751   %gep1 = getelementptr i64, i64* %array, i64 2
752   br label %body
753
754 body:
755   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
756   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
757   %gep2 = getelementptr i64, i64* %iv2, i64 -1
758   %load = load i64, i64* %gep2
759   call void @use-doubleword(i64 %load)
760   %load2 = load i64, i64* %iv2
761   call void @use-doubleword(i64 %load2)
762   %iv.next = add i64 %iv, -4
763   %gep3 = getelementptr i64, i64* %iv2, i64 4
764   %cond = icmp eq i64 %iv.next, 0
765   br i1 %cond, label %exit, label %body
766
767 exit:
768   ret void
769 }
770
771 define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind {
772 ; CHECK-LABEL: load-post-indexed-quadword
773 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64
774 entry:
775   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
776   br label %body
777
778 body:
779   %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
780   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
781   %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1
782   %load = load <2 x i64>, <2 x i64>* %gep2
783   call void @use-quadword(<2 x i64> %load)
784   %load2 = load <2 x i64>, <2 x i64>* %iv2
785   call void @use-quadword(<2 x i64> %load2)
786   %iv.next = add i64 %iv, -4
787   %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4
788   %cond = icmp eq i64 %iv.next, 0
789   br i1 %cond, label %exit, label %body
790
791 exit:
792   ret void
793 }
794
795 define void @load-post-indexed-float(float* %array, i64 %count) nounwind {
796 ; CHECK-LABEL: load-post-indexed-float
797 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16
798 entry:
799   %gep1 = getelementptr float, float* %array, i64 2
800   br label %body
801
802 body:
803   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
804   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
805   %gep2 = getelementptr float, float* %iv2, i64 -1
806   %load = load float, float* %gep2
807   call void @use-float(float %load)
808   %load2 = load float, float* %iv2
809   call void @use-float(float %load2)
810   %iv.next = add i64 %iv, -4
811   %gep3 = getelementptr float, float* %iv2, i64 4
812   %cond = icmp eq i64 %iv.next, 0
813   br i1 %cond, label %exit, label %body
814
815 exit:
816   ret void
817 }
818
819 define void @load-post-indexed-double(double* %array, i64 %count) nounwind {
820 ; CHECK-LABEL: load-post-indexed-double
821 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32
822 entry:
823   %gep1 = getelementptr double, double* %array, i64 2
824   br label %body
825
826 body:
827   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
828   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
829   %gep2 = getelementptr double, double* %iv2, i64 -1
830   %load = load double, double* %gep2
831   call void @use-double(double %load)
832   %load2 = load double, double* %iv2
833   call void @use-double(double %load2)
834   %iv.next = add i64 %iv, -4
835   %gep3 = getelementptr double, double* %iv2, i64 4
836   %cond = icmp eq i64 %iv.next, 0
837   br i1 %cond, label %exit, label %body
838
839 exit:
840   ret void
841 }
842
843 ; Check the following transform:
844 ;
845 ; str X, [x20]
846 ;  ...
847 ; add x20, x20, #32
848 ;  ->
849 ; str X, [x20], #32
850 ;
851 ; with X being either w0, x0, s0, d0 or q0.
852
853 define void @store-post-indexed-byte(i8* %array, i64 %count, i8 %val) nounwind {
854 ; CHECK-LABEL: store-post-indexed-byte
855 ; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}], #4
856 entry:
857   %gep1 = getelementptr i8, i8* %array, i64 2
858   br label %body
859
860 body:
861   %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ]
862   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
863   %gep2 = getelementptr i8, i8* %iv2, i64 -1
864   %load = load i8, i8* %gep2
865   call void @use-byte(i8 %load)
866   store i8 %val, i8* %iv2
867   %iv.next = add i64 %iv, -4
868   %gep3 = getelementptr i8, i8* %iv2, i64 4
869   %cond = icmp eq i64 %iv.next, 0
870   br i1 %cond, label %exit, label %body
871
872 exit:
873   ret void
874 }
875
876 define void @store-post-indexed-halfword(i16* %array, i64 %count, i16 %val) nounwind {
877 ; CHECK-LABEL: store-post-indexed-halfword
878 ; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}], #8
879 entry:
880   %gep1 = getelementptr i16, i16* %array, i64 2
881   br label %body
882
883 body:
884   %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ]
885   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
886   %gep2 = getelementptr i16, i16* %iv2, i64 -1
887   %load = load i16, i16* %gep2
888   call void @use-halfword(i16 %load)
889   store i16 %val, i16* %iv2
890   %iv.next = add i64 %iv, -4
891   %gep3 = getelementptr i16, i16* %iv2, i64 4
892   %cond = icmp eq i64 %iv.next, 0
893   br i1 %cond, label %exit, label %body
894
895 exit:
896   ret void
897 }
898
899 define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind {
900 ; CHECK-LABEL: store-post-indexed-word
901 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16
902 entry:
903   %gep1 = getelementptr i32, i32* %array, i64 2
904   br label %body
905
906 body:
907   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
908   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
909   %gep2 = getelementptr i32, i32* %iv2, i64 -1
910   %load = load i32, i32* %gep2
911   call void @use-word(i32 %load)
912   store i32 %val, i32* %iv2
913   %iv.next = add i64 %iv, -4
914   %gep3 = getelementptr i32, i32* %iv2, i64 4
915   %cond = icmp eq i64 %iv.next, 0
916   br i1 %cond, label %exit, label %body
917
918 exit:
919   ret void
920 }
921
922 define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind {
923 ; CHECK-LABEL: store-post-indexed-doubleword
924 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32
925 entry:
926   %gep1 = getelementptr i64, i64* %array, i64 2
927   br label %body
928
929 body:
930   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
931   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
932   %gep2 = getelementptr i64, i64* %iv2, i64 -1
933   %load = load i64, i64* %gep2
934   call void @use-doubleword(i64 %load)
935   store i64 %val, i64* %iv2
936   %iv.next = add i64 %iv, -4
937   %gep3 = getelementptr i64, i64* %iv2, i64 4
938   %cond = icmp eq i64 %iv.next, 0
939   br i1 %cond, label %exit, label %body
940
941 exit:
942   ret void
943 }
944
945 define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind {
946 ; CHECK-LABEL: store-post-indexed-quadword
947 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64
948 entry:
949   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
950   br label %body
951
952 body:
953   %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
954   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
955   %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1
956   %load = load <2 x i64>, <2 x i64>* %gep2
957   call void @use-quadword(<2 x i64> %load)
958   store <2 x i64> %val, <2 x i64>* %iv2
959   %iv.next = add i64 %iv, -4
960   %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4
961   %cond = icmp eq i64 %iv.next, 0
962   br i1 %cond, label %exit, label %body
963
964 exit:
965   ret void
966 }
967
968 define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind {
969 ; CHECK-LABEL: store-post-indexed-float
970 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16
971 entry:
972   %gep1 = getelementptr float, float* %array, i64 2
973   br label %body
974
975 body:
976   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
977   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
978   %gep2 = getelementptr float, float* %iv2, i64 -1
979   %load = load float, float* %gep2
980   call void @use-float(float %load)
981   store float %val, float* %iv2
982   %iv.next = add i64 %iv, -4
983   %gep3 = getelementptr float, float* %iv2, i64 4
984   %cond = icmp eq i64 %iv.next, 0
985   br i1 %cond, label %exit, label %body
986
987 exit:
988   ret void
989 }
990
991 define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind {
992 ; CHECK-LABEL: store-post-indexed-double
993 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32
994 entry:
995   %gep1 = getelementptr double, double* %array, i64 2
996   br label %body
997
998 body:
999   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
1000   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
1001   %gep2 = getelementptr double, double* %iv2, i64 -1
1002   %load = load double, double* %gep2
1003   call void @use-double(double %load)
1004   store double %val, double* %iv2
1005   %iv.next = add i64 %iv, -4
1006   %gep3 = getelementptr double, double* %iv2, i64 4
1007   %cond = icmp eq i64 %iv.next, 0
1008   br i1 %cond, label %exit, label %body
1009
1010 exit:
1011   ret void
1012 }
1013
1014 declare void @use-byte(i8)
1015 declare void @use-halfword(i16)
1016 declare void @use-word(i32)
1017 declare void @use-doubleword(i64)
1018 declare void @use-quadword(<2 x i64>)
1019 declare void @use-float(float)
1020 declare void @use-double(double)
1021
1022 ; Check the following transform:
1023 ;
1024 ; stp w0, [x20]
1025 ;  ...
1026 ; add x20, x20, #32
1027 ;  ->
1028 ; stp w0, [x20], #32
1029
1030 define void @store-pair-post-indexed-word() nounwind {
1031 ; CHECK-LABEL: store-pair-post-indexed-word
1032 ; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [sp], #16
1033 ; CHECK: ret
1034   %src = alloca { i32, i32 }, align 8
1035   %dst = alloca { i32, i32 }, align 8
1036
1037   %src.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 0
1038   %src.real = load i32, i32* %src.realp
1039   %src.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 1
1040   %src.imag = load i32, i32* %src.imagp
1041
1042   %dst.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 0
1043   %dst.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 1
1044   store i32 %src.real, i32* %dst.realp
1045   store i32 %src.imag, i32* %dst.imagp
1046   ret void
1047 }
1048
1049 define void @store-pair-post-indexed-doubleword() nounwind {
1050 ; CHECK-LABEL: store-pair-post-indexed-doubleword
1051 ; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [sp], #32
1052 ; CHECK: ret
1053   %src = alloca { i64, i64 }, align 8
1054   %dst = alloca { i64, i64 }, align 8
1055
1056   %src.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 0
1057   %src.real = load i64, i64* %src.realp
1058   %src.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 1
1059   %src.imag = load i64, i64* %src.imagp
1060
1061   %dst.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 0
1062   %dst.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 1
1063   store i64 %src.real, i64* %dst.realp
1064   store i64 %src.imag, i64* %dst.imagp
1065   ret void
1066 }
1067
1068 define void @store-pair-post-indexed-float() nounwind {
1069 ; CHECK-LABEL: store-pair-post-indexed-float
1070 ; CHECK: stp s{{[0-9]+}}, s{{[0-9]+}}, [sp], #16
1071 ; CHECK: ret
1072   %src = alloca { float, float }, align 8
1073   %dst = alloca { float, float }, align 8
1074
1075   %src.realp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 0
1076   %src.real = load float, float* %src.realp
1077   %src.imagp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 1
1078   %src.imag = load float, float* %src.imagp
1079
1080   %dst.realp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 0
1081   %dst.imagp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 1
1082   store float %src.real, float* %dst.realp
1083   store float %src.imag, float* %dst.imagp
1084   ret void
1085 }
1086
1087 define void @store-pair-post-indexed-double() nounwind {
1088 ; CHECK-LABEL: store-pair-post-indexed-double
1089 ; CHECK: stp d{{[0-9]+}}, d{{[0-9]+}}, [sp], #32
1090 ; CHECK: ret
1091   %src = alloca { double, double }, align 8
1092   %dst = alloca { double, double }, align 8
1093
1094   %src.realp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 0
1095   %src.real = load double, double* %src.realp
1096   %src.imagp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 1
1097   %src.imag = load double, double* %src.imagp
1098
1099   %dst.realp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 0
1100   %dst.imagp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 1
1101   store double %src.real, double* %dst.realp
1102   store double %src.imag, double* %dst.imagp
1103   ret void
1104 }
1105
1106 ; Check the following transform:
1107 ;
1108 ; (ldr|str) X, [x20]
1109 ;  ...
1110 ; sub x20, x20, #16
1111 ;  ->
1112 ; (ldr|str) X, [x20], #-16
1113 ;
1114 ; with X being either w0, x0, s0, d0 or q0.
1115
1116 define void @post-indexed-sub-word(i32* %a, i32* %b, i64 %count) nounwind {
1117 ; CHECK-LABEL: post-indexed-sub-word
1118 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-8
1119 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-8
1120   br label %for.body
1121 for.body:
1122   %phi1 = phi i32* [ %gep4, %for.body ], [ %b, %0 ]
1123   %phi2 = phi i32* [ %gep3, %for.body ], [ %a, %0 ]
1124   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
1125   %gep1 = getelementptr i32, i32* %phi1, i64 -1
1126   %load1 = load i32, i32* %gep1
1127   %gep2 = getelementptr i32, i32* %phi2, i64 -1
1128   store i32 %load1, i32* %gep2
1129   %load2 = load i32, i32* %phi1
1130   store i32 %load2, i32* %phi2
1131   %dec.i = add nsw i64 %i, -1
1132   %gep3 = getelementptr i32, i32* %phi2, i64 -2
1133   %gep4 = getelementptr i32, i32* %phi1, i64 -2
1134   %cond = icmp sgt i64 %dec.i, 0
1135   br i1 %cond, label %for.body, label %end
1136 end:
1137   ret void
1138 }
1139
1140 define void @post-indexed-sub-doubleword(i64* %a, i64* %b, i64 %count) nounwind {
1141 ; CHECK-LABEL: post-indexed-sub-doubleword
1142 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-16
1143 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-16
1144   br label %for.body
1145 for.body:
1146   %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
1147   %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
1148   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
1149   %gep1 = getelementptr i64, i64* %phi1, i64 -1
1150   %load1 = load i64, i64* %gep1
1151   %gep2 = getelementptr i64, i64* %phi2, i64 -1
1152   store i64 %load1, i64* %gep2
1153   %load2 = load i64, i64* %phi1
1154   store i64 %load2, i64* %phi2
1155   %dec.i = add nsw i64 %i, -1
1156   %gep3 = getelementptr i64, i64* %phi2, i64 -2
1157   %gep4 = getelementptr i64, i64* %phi1, i64 -2
1158   %cond = icmp sgt i64 %dec.i, 0
1159   br i1 %cond, label %for.body, label %end
1160 end:
1161   ret void
1162 }
1163
1164 define void @post-indexed-sub-quadword(<2 x i64>* %a, <2 x i64>* %b, i64 %count) nounwind {
1165 ; CHECK-LABEL: post-indexed-sub-quadword
1166 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-32
1167 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-32
1168   br label %for.body
1169 for.body:
1170   %phi1 = phi <2 x i64>* [ %gep4, %for.body ], [ %b, %0 ]
1171   %phi2 = phi <2 x i64>* [ %gep3, %for.body ], [ %a, %0 ]
1172   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
1173   %gep1 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -1
1174   %load1 = load <2 x i64>, <2 x i64>* %gep1
1175   %gep2 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -1
1176   store <2 x i64> %load1, <2 x i64>* %gep2
1177   %load2 = load <2 x i64>, <2 x i64>* %phi1
1178   store <2 x i64> %load2, <2 x i64>* %phi2
1179   %dec.i = add nsw i64 %i, -1
1180   %gep3 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -2
1181   %gep4 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -2
1182   %cond = icmp sgt i64 %dec.i, 0
1183   br i1 %cond, label %for.body, label %end
1184 end:
1185   ret void
1186 }
1187
1188 define void @post-indexed-sub-float(float* %a, float* %b, i64 %count) nounwind {
1189 ; CHECK-LABEL: post-indexed-sub-float
1190 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-8
1191 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-8
1192   br label %for.body
1193 for.body:
1194   %phi1 = phi float* [ %gep4, %for.body ], [ %b, %0 ]
1195   %phi2 = phi float* [ %gep3, %for.body ], [ %a, %0 ]
1196   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
1197   %gep1 = getelementptr float, float* %phi1, i64 -1
1198   %load1 = load float, float* %gep1
1199   %gep2 = getelementptr float, float* %phi2, i64 -1
1200   store float %load1, float* %gep2
1201   %load2 = load float, float* %phi1
1202   store float %load2, float* %phi2
1203   %dec.i = add nsw i64 %i, -1
1204   %gep3 = getelementptr float, float* %phi2, i64 -2
1205   %gep4 = getelementptr float, float* %phi1, i64 -2
1206   %cond = icmp sgt i64 %dec.i, 0
1207   br i1 %cond, label %for.body, label %end
1208 end:
1209   ret void
1210 }
1211
1212 define void @post-indexed-sub-double(double* %a, double* %b, i64 %count) nounwind {
1213 ; CHECK-LABEL: post-indexed-sub-double
1214 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-16
1215 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-16
1216   br label %for.body
1217 for.body:
1218   %phi1 = phi double* [ %gep4, %for.body ], [ %b, %0 ]
1219   %phi2 = phi double* [ %gep3, %for.body ], [ %a, %0 ]
1220   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
1221   %gep1 = getelementptr double, double* %phi1, i64 -1
1222   %load1 = load double, double* %gep1
1223   %gep2 = getelementptr double, double* %phi2, i64 -1
1224   store double %load1, double* %gep2
1225   %load2 = load double, double* %phi1
1226   store double %load2, double* %phi2
1227   %dec.i = add nsw i64 %i, -1
1228   %gep3 = getelementptr double, double* %phi2, i64 -2
1229   %gep4 = getelementptr double, double* %phi1, i64 -2
1230   %cond = icmp sgt i64 %dec.i, 0
1231   br i1 %cond, label %for.body, label %end
1232 end:
1233   ret void
1234 }