• 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.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
31declare void @bar_byte(%s.byte*, i8)
32
33define 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]!
36entry:
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
40bar:
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
46define 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]!
49entry:
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
53bar:
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
59declare void @bar_halfword(%s.halfword*, i16)
60
61define 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]!
64entry:
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
68bar:
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
74define 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]!
77entry:
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
81bar:
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
87declare void @bar_word(%s.word*, i32)
88
89define 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]!
92entry:
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
96bar:
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
102define 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]!
105entry:
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
109bar:
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
115declare void @bar_doubleword(%s.doubleword*, i64)
116
117define 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]!
120entry:
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
124bar:
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
130define 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]!
133entry:
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
137bar:
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
143declare void @bar_quadword(%s.quadword*, fp128)
144
145define 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]!
148entry:
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
152bar:
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
158define 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]!
161entry:
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
165bar:
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
171declare void @bar_float(%s.float*, float)
172
173define 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]!
176entry:
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
180bar:
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
186define 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]!
189entry:
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
193bar:
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
199declare void @bar_double(%s.double*, double)
200
201define 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]!
204entry:
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
208bar:
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
214define 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]!
217entry:
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
221bar:
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
236define 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
240entry:
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
247bar:
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
253define 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
257entry:
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
263bar:
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
285define 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
290if.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
294if.end:
295  %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
296  br label %return
297return:
298  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
299  %ret = load i32, i32* %retptr
300  ret i32 %ret
301}
302
303define 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
308if.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
312if.end:
313  %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
314  br label %return
315return:
316  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
317  %ret = load i64, i64* %retptr
318  ret i64 %ret
319}
320
321define <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
326if.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
330if.end:
331  %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
332  br label %return
333return:
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
339define 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
344if.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
348if.end:
349  %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
350  br label %return
351return:
352  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
353  %ret = load float, float* %retptr
354  ret float %ret
355}
356
357define 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
362if.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
366if.end:
367  %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
368  br label %return
369return:
370  %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
371  %ret = load double, double* %retptr
372  ret double %ret
373}
374
375define 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
380if.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
384if.end:
385  %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
386  br label %return
387return:
388  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
389  %ret = load i32, i32* %retptr
390  ret i32 %ret
391}
392
393define 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
398if.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
402if.end:
403  %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 3
404  br label %return
405return:
406  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
407  %ret = load i64, i64* %retptr
408  ret i64 %ret
409}
410
411define <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
416if.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
420if.end:
421  %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
422  br label %return
423return:
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
429define 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
434if.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
438if.end:
439  %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
440  br label %return
441return:
442  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
443  %ret = load float, float* %retptr
444  ret float %ret
445}
446
447define 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
452if.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
456if.end:
457  %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
458  br label %return
459return:
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
475define 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
481if.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
485if.end:
486  %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
487  br label %return
488return:
489  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
490  store i32 %val, i32* %retptr
491  ret void
492}
493
494define 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
500if.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
504if.end:
505  %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
506  br label %return
507return:
508  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
509  store i64 %val, i64* %retptr
510  ret void
511}
512
513define 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
519if.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
523if.end:
524  %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
525  br label %return
526return:
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
532define 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
538if.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
542if.end:
543  %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
544  br label %return
545return:
546  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
547  store float %val, float* %retptr
548  ret void
549}
550
551define 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
557if.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
561if.end:
562  %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
563  br label %return
564return:
565  %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
566  store double %val, double* %retptr
567  ret void
568}
569
570define 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
576if.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
580if.end:
581  %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
582  br label %return
583return:
584  %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
585  store i32 %val, i32* %retptr
586  ret void
587}
588
589define 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
595if.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
599if.end:
600  %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 4
601  br label %return
602return:
603  %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
604  store i64 %val, i64* %retptr
605  ret void
606}
607
608define 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
614if.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
618if.end:
619  %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
620  br label %return
621return:
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
627define 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
633if.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
637if.end:
638  %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
639  br label %return
640return:
641  %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
642  store float %val, float* %retptr
643  ret void
644}
645
646define 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
652if.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
656if.end:
657  %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
658  br label %return
659return:
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
675define 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
678entry:
679  %gep1 = getelementptr i8, i8* %array, i64 2
680  br label %body
681
682body:
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
695exit:
696  ret void
697}
698
699define 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
702entry:
703  %gep1 = getelementptr i16, i16* %array, i64 2
704  br label %body
705
706body:
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
719exit:
720  ret void
721}
722
723define 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
726entry:
727  %gep1 = getelementptr i32, i32* %array, i64 2
728  br label %body
729
730body:
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
743exit:
744  ret void
745}
746
747define 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
750entry:
751  %gep1 = getelementptr i64, i64* %array, i64 2
752  br label %body
753
754body:
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
767exit:
768  ret void
769}
770
771define 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
774entry:
775  %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
776  br label %body
777
778body:
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
791exit:
792  ret void
793}
794
795define 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
798entry:
799  %gep1 = getelementptr float, float* %array, i64 2
800  br label %body
801
802body:
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
815exit:
816  ret void
817}
818
819define 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
822entry:
823  %gep1 = getelementptr double, double* %array, i64 2
824  br label %body
825
826body:
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
839exit:
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
853define 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
856entry:
857  %gep1 = getelementptr i8, i8* %array, i64 2
858  br label %body
859
860body:
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
872exit:
873  ret void
874}
875
876define 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
879entry:
880  %gep1 = getelementptr i16, i16* %array, i64 2
881  br label %body
882
883body:
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
895exit:
896  ret void
897}
898
899define 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
902entry:
903  %gep1 = getelementptr i32, i32* %array, i64 2
904  br label %body
905
906body:
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
918exit:
919  ret void
920}
921
922define 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
925entry:
926  %gep1 = getelementptr i64, i64* %array, i64 2
927  br label %body
928
929body:
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
941exit:
942  ret void
943}
944
945define 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
948entry:
949  %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
950  br label %body
951
952body:
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
964exit:
965  ret void
966}
967
968define 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
971entry:
972  %gep1 = getelementptr float, float* %array, i64 2
973  br label %body
974
975body:
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
987exit:
988  ret void
989}
990
991define 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
994entry:
995  %gep1 = getelementptr double, double* %array, i64 2
996  br label %body
997
998body:
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
1010exit:
1011  ret void
1012}
1013
1014declare void @use-byte(i8)
1015declare void @use-halfword(i16)
1016declare void @use-word(i32)
1017declare void @use-doubleword(i64)
1018declare void @use-quadword(<2 x i64>)
1019declare void @use-float(float)
1020declare 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
1030define 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
1049define 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
1068define 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
1087define 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
1116define 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
1121for.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
1136end:
1137  ret void
1138}
1139
1140define 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
1145for.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
1160end:
1161  ret void
1162}
1163
1164define 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
1169for.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
1184end:
1185  ret void
1186}
1187
1188define 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
1193for.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
1208end:
1209  ret void
1210}
1211
1212define 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
1217for.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
1232end:
1233  ret void
1234}
1235