[AArch64] Fix bug in prolog clobbering live reg when shrink wrapping.
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-vector-ldst.ll
1 ; RUN: llc < %s -march=arm64 -aarch64-neon-syntax=apple -verify-machineinstrs | FileCheck %s
2
3 ; rdar://9428579
4
5 %type1 = type { <16 x i8> }
6 %type2 = type { <8 x i8> }
7 %type3 = type { <4 x i16> }
8
9
10 define hidden fastcc void @t1(%type1** %argtable) nounwind {
11 entry:
12 ; CHECK-LABEL: t1:
13 ; CHECK: ldr x[[REG:[0-9]+]], [x0]
14 ; CHECK: str q0, [x[[REG]]]
15   %tmp1 = load %type1*, %type1** %argtable, align 8
16   %tmp2 = getelementptr inbounds %type1, %type1* %tmp1, i64 0, i32 0
17   store <16 x i8> zeroinitializer, <16 x i8>* %tmp2, align 16
18   ret void
19 }
20
21 define hidden fastcc void @t2(%type2** %argtable) nounwind {
22 entry:
23 ; CHECK-LABEL: t2:
24 ; CHECK: ldr x[[REG:[0-9]+]], [x0]
25 ; CHECK: str d0, [x[[REG]]]
26   %tmp1 = load %type2*, %type2** %argtable, align 8
27   %tmp2 = getelementptr inbounds %type2, %type2* %tmp1, i64 0, i32 0
28   store <8 x i8> zeroinitializer, <8 x i8>* %tmp2, align 8
29   ret void
30 }
31
32 ; add a bunch of tests for rdar://11246289
33
34 @globalArray64x2 = common global <2 x i64>* null, align 8
35 @globalArray32x4 = common global <4 x i32>* null, align 8
36 @globalArray16x8 = common global <8 x i16>* null, align 8
37 @globalArray8x16 = common global <16 x i8>* null, align 8
38 @globalArray64x1 = common global <1 x i64>* null, align 8
39 @globalArray32x2 = common global <2 x i32>* null, align 8
40 @globalArray16x4 = common global <4 x i16>* null, align 8
41 @globalArray8x8 = common global <8 x i8>* null, align 8
42 @floatglobalArray64x2 = common global <2 x double>* null, align 8
43 @floatglobalArray32x4 = common global <4 x float>* null, align 8
44 @floatglobalArray64x1 = common global <1 x double>* null, align 8
45 @floatglobalArray32x2 = common global <2 x float>* null, align 8
46
47 define void @fct1_64x2(<2 x i64>* nocapture %array, i64 %offset) nounwind ssp {
48 entry:
49 ; CHECK-LABEL: fct1_64x2:
50 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #4
51 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, [[SHIFTEDOFFSET]]
52 ; CHECK: ldr [[BASE:x[0-9]+]],
53 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
54   %arrayidx = getelementptr inbounds <2 x i64>, <2 x i64>* %array, i64 %offset
55   %tmp = load <2 x i64>, <2 x i64>* %arrayidx, align 16
56   %tmp1 = load <2 x i64>*, <2 x i64>** @globalArray64x2, align 8
57   %arrayidx1 = getelementptr inbounds <2 x i64>, <2 x i64>* %tmp1, i64 %offset
58   store <2 x i64> %tmp, <2 x i64>* %arrayidx1, align 16
59   ret void
60 }
61
62 define void @fct2_64x2(<2 x i64>* nocapture %array) nounwind ssp {
63 entry:
64 ; CHECK-LABEL: fct2_64x2:
65 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, #48]
66 ; CHECK: ldr [[BASE:x[0-9]+]],
67 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #80]
68   %arrayidx = getelementptr inbounds <2 x i64>, <2 x i64>* %array, i64 3
69   %tmp = load <2 x i64>, <2 x i64>* %arrayidx, align 16
70   %tmp1 = load <2 x i64>*, <2 x i64>** @globalArray64x2, align 8
71   %arrayidx1 = getelementptr inbounds <2 x i64>, <2 x i64>* %tmp1, i64 5
72   store <2 x i64> %tmp, <2 x i64>* %arrayidx1, align 16
73   ret void
74 }
75
76 define void @fct1_32x4(<4 x i32>* nocapture %array, i64 %offset) nounwind ssp {
77 entry:
78 ; CHECK-LABEL: fct1_32x4:
79 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #4
80 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
81 ; CHECK: ldr [[BASE:x[0-9]+]],
82 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
83   %arrayidx = getelementptr inbounds <4 x i32>, <4 x i32>* %array, i64 %offset
84   %tmp = load <4 x i32>, <4 x i32>* %arrayidx, align 16
85   %tmp1 = load <4 x i32>*, <4 x i32>** @globalArray32x4, align 8
86   %arrayidx1 = getelementptr inbounds <4 x i32>, <4 x i32>* %tmp1, i64 %offset
87   store <4 x i32> %tmp, <4 x i32>* %arrayidx1, align 16
88   ret void
89 }
90
91 define void @fct2_32x4(<4 x i32>* nocapture %array) nounwind ssp {
92 entry:
93 ; CHECK-LABEL: fct2_32x4:
94 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, #48]
95 ; CHECK: ldr [[BASE:x[0-9]+]],
96 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #80]
97   %arrayidx = getelementptr inbounds <4 x i32>, <4 x i32>* %array, i64 3
98   %tmp = load <4 x i32>, <4 x i32>* %arrayidx, align 16
99   %tmp1 = load <4 x i32>*, <4 x i32>** @globalArray32x4, align 8
100   %arrayidx1 = getelementptr inbounds <4 x i32>, <4 x i32>* %tmp1, i64 5
101   store <4 x i32> %tmp, <4 x i32>* %arrayidx1, align 16
102   ret void
103 }
104
105 define void @fct1_16x8(<8 x i16>* nocapture %array, i64 %offset) nounwind ssp {
106 entry:
107 ; CHECK-LABEL: fct1_16x8:
108 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #4
109 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
110 ; CHECK: ldr [[BASE:x[0-9]+]],
111 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
112   %arrayidx = getelementptr inbounds <8 x i16>, <8 x i16>* %array, i64 %offset
113   %tmp = load <8 x i16>, <8 x i16>* %arrayidx, align 16
114   %tmp1 = load <8 x i16>*, <8 x i16>** @globalArray16x8, align 8
115   %arrayidx1 = getelementptr inbounds <8 x i16>, <8 x i16>* %tmp1, i64 %offset
116   store <8 x i16> %tmp, <8 x i16>* %arrayidx1, align 16
117   ret void
118 }
119
120 define void @fct2_16x8(<8 x i16>* nocapture %array) nounwind ssp {
121 entry:
122 ; CHECK-LABEL: fct2_16x8:
123 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, #48]
124 ; CHECK: ldr [[BASE:x[0-9]+]],
125 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #80]
126   %arrayidx = getelementptr inbounds <8 x i16>, <8 x i16>* %array, i64 3
127   %tmp = load <8 x i16>, <8 x i16>* %arrayidx, align 16
128   %tmp1 = load <8 x i16>*, <8 x i16>** @globalArray16x8, align 8
129   %arrayidx1 = getelementptr inbounds <8 x i16>, <8 x i16>* %tmp1, i64 5
130   store <8 x i16> %tmp, <8 x i16>* %arrayidx1, align 16
131   ret void
132 }
133
134 define void @fct1_8x16(<16 x i8>* nocapture %array, i64 %offset) nounwind ssp {
135 entry:
136 ; CHECK-LABEL: fct1_8x16:
137 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #4
138 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
139 ; CHECK: ldr [[BASE:x[0-9]+]],
140 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
141   %arrayidx = getelementptr inbounds <16 x i8>, <16 x i8>* %array, i64 %offset
142   %tmp = load <16 x i8>, <16 x i8>* %arrayidx, align 16
143   %tmp1 = load <16 x i8>*, <16 x i8>** @globalArray8x16, align 8
144   %arrayidx1 = getelementptr inbounds <16 x i8>, <16 x i8>* %tmp1, i64 %offset
145   store <16 x i8> %tmp, <16 x i8>* %arrayidx1, align 16
146   ret void
147 }
148
149 define void @fct2_8x16(<16 x i8>* nocapture %array) nounwind ssp {
150 entry:
151 ; CHECK-LABEL: fct2_8x16:
152 ; CHECK: ldr [[DEST:q[0-9]+]], [x0, #48]
153 ; CHECK: ldr [[BASE:x[0-9]+]],
154 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #80]
155   %arrayidx = getelementptr inbounds <16 x i8>, <16 x i8>* %array, i64 3
156   %tmp = load <16 x i8>, <16 x i8>* %arrayidx, align 16
157   %tmp1 = load <16 x i8>*, <16 x i8>** @globalArray8x16, align 8
158   %arrayidx1 = getelementptr inbounds <16 x i8>, <16 x i8>* %tmp1, i64 5
159   store <16 x i8> %tmp, <16 x i8>* %arrayidx1, align 16
160   ret void
161 }
162
163 define void @fct1_64x1(<1 x i64>* nocapture %array, i64 %offset) nounwind ssp {
164 entry:
165 ; CHECK-LABEL: fct1_64x1:
166 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #3
167 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
168 ; CHECK: ldr [[BASE:x[0-9]+]],
169 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
170   %arrayidx = getelementptr inbounds <1 x i64>, <1 x i64>* %array, i64 %offset
171   %tmp = load <1 x i64>, <1 x i64>* %arrayidx, align 8
172   %tmp1 = load <1 x i64>*, <1 x i64>** @globalArray64x1, align 8
173   %arrayidx1 = getelementptr inbounds <1 x i64>, <1 x i64>* %tmp1, i64 %offset
174   store <1 x i64> %tmp, <1 x i64>* %arrayidx1, align 8
175   ret void
176 }
177
178 define void @fct2_64x1(<1 x i64>* nocapture %array) nounwind ssp {
179 entry:
180 ; CHECK-LABEL: fct2_64x1:
181 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, #24]
182 ; CHECK: ldr [[BASE:x[0-9]+]],
183 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #40]
184   %arrayidx = getelementptr inbounds <1 x i64>, <1 x i64>* %array, i64 3
185   %tmp = load <1 x i64>, <1 x i64>* %arrayidx, align 8
186   %tmp1 = load <1 x i64>*, <1 x i64>** @globalArray64x1, align 8
187   %arrayidx1 = getelementptr inbounds <1 x i64>, <1 x i64>* %tmp1, i64 5
188   store <1 x i64> %tmp, <1 x i64>* %arrayidx1, align 8
189   ret void
190 }
191
192 define void @fct1_32x2(<2 x i32>* nocapture %array, i64 %offset) nounwind ssp {
193 entry:
194 ; CHECK-LABEL: fct1_32x2:
195 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #3
196 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
197 ; CHECK: ldr [[BASE:x[0-9]+]],
198 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
199   %arrayidx = getelementptr inbounds <2 x i32>, <2 x i32>* %array, i64 %offset
200   %tmp = load <2 x i32>, <2 x i32>* %arrayidx, align 8
201   %tmp1 = load <2 x i32>*, <2 x i32>** @globalArray32x2, align 8
202   %arrayidx1 = getelementptr inbounds <2 x i32>, <2 x i32>* %tmp1, i64 %offset
203   store <2 x i32> %tmp, <2 x i32>* %arrayidx1, align 8
204   ret void
205 }
206
207 define void @fct2_32x2(<2 x i32>* nocapture %array) nounwind ssp {
208 entry:
209 ; CHECK-LABEL: fct2_32x2:
210 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, #24]
211 ; CHECK: ldr [[BASE:x[0-9]+]],
212 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #40]
213   %arrayidx = getelementptr inbounds <2 x i32>, <2 x i32>* %array, i64 3
214   %tmp = load <2 x i32>, <2 x i32>* %arrayidx, align 8
215   %tmp1 = load <2 x i32>*, <2 x i32>** @globalArray32x2, align 8
216   %arrayidx1 = getelementptr inbounds <2 x i32>, <2 x i32>* %tmp1, i64 5
217   store <2 x i32> %tmp, <2 x i32>* %arrayidx1, align 8
218   ret void
219 }
220
221 define void @fct1_16x4(<4 x i16>* nocapture %array, i64 %offset) nounwind ssp {
222 entry:
223 ; CHECK-LABEL: fct1_16x4:
224 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #3
225 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
226 ; CHECK: ldr [[BASE:x[0-9]+]],
227 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
228   %arrayidx = getelementptr inbounds <4 x i16>, <4 x i16>* %array, i64 %offset
229   %tmp = load <4 x i16>, <4 x i16>* %arrayidx, align 8
230   %tmp1 = load <4 x i16>*, <4 x i16>** @globalArray16x4, align 8
231   %arrayidx1 = getelementptr inbounds <4 x i16>, <4 x i16>* %tmp1, i64 %offset
232   store <4 x i16> %tmp, <4 x i16>* %arrayidx1, align 8
233   ret void
234 }
235
236 define void @fct2_16x4(<4 x i16>* nocapture %array) nounwind ssp {
237 entry:
238 ; CHECK-LABEL: fct2_16x4:
239 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, #24]
240 ; CHECK: ldr [[BASE:x[0-9]+]],
241 ; CHECK: str [[DEST]], {{\[}}[[BASE]], #40]
242   %arrayidx = getelementptr inbounds <4 x i16>, <4 x i16>* %array, i64 3
243   %tmp = load <4 x i16>, <4 x i16>* %arrayidx, align 8
244   %tmp1 = load <4 x i16>*, <4 x i16>** @globalArray16x4, align 8
245   %arrayidx1 = getelementptr inbounds <4 x i16>, <4 x i16>* %tmp1, i64 5
246   store <4 x i16> %tmp, <4 x i16>* %arrayidx1, align 8
247   ret void
248 }
249
250 define void @fct1_8x8(<8 x i8>* nocapture %array, i64 %offset) nounwind ssp {
251 entry:
252 ; CHECK-LABEL: fct1_8x8:
253 ; CHECK: lsl [[SHIFTEDOFFSET:x[0-9]+]], x1, #3
254 ; CHECK: ldr [[DEST:d[0-9]+]], [x0, [[SHIFTEDOFFSET]]]
255 ; CHECK: ldr [[BASE:x[0-9]+]],
256 ; CHECK: str [[DEST]], {{\[}}[[BASE]], [[SHIFTEDOFFSET]]]
257   %arrayidx = getelementptr inbounds <8 x i8>, <8 x i8>* %array, i64 %offset
258   %tmp = load <8 x i8>, <8 x i8>* %arrayidx, align 8
259   %tmp1 = load <8 x i8>*, <8 x i8>** @globalArray8x8, align 8
260   %arrayidx1 = getelementptr inbounds <8 x i8>, <8 x i8>* %tmp1, i64 %offset
261   store <8 x i8> %tmp, <8 x i8>* %arrayidx1, align 8
262   ret void
263 }
264
265 ; Add a bunch of tests for rdar://13258794: Match LDUR/STUR for D and Q
266 ; registers for unscaled vector accesses
267 @str = global [63 x i8] c"Test case for rdar://13258794: LDUR/STUR for D and Q registers\00", align 1
268
269 define <1 x i64> @fct0() nounwind readonly ssp {
270 entry:
271 ; CHECK-LABEL: fct0:
272 ; CHECK: ldur {{d[0-9]+}}, [{{x[0-9]+}}, #3]
273   %0 = load <1 x i64>, <1 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <1 x i64>*), align 8
274   ret <1 x i64> %0
275 }
276
277 define <2 x i32> @fct1() nounwind readonly ssp {
278 entry:
279 ; CHECK-LABEL: fct1:
280 ; CHECK: ldur {{d[0-9]+}}, [{{x[0-9]+}}, #3]
281   %0 = load <2 x i32>, <2 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <2 x i32>*), align 8
282   ret <2 x i32> %0
283 }
284
285 define <4 x i16> @fct2() nounwind readonly ssp {
286 entry:
287 ; CHECK-LABEL: fct2:
288 ; CHECK: ldur {{d[0-9]+}}, [{{x[0-9]+}}, #3]
289   %0 = load <4 x i16>, <4 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <4 x i16>*), align 8
290   ret <4 x i16> %0
291 }
292
293 define <8 x i8> @fct3() nounwind readonly ssp {
294 entry:
295 ; CHECK-LABEL: fct3:
296 ; CHECK: ldur {{d[0-9]+}}, [{{x[0-9]+}}, #3]
297   %0 = load <8 x i8>, <8 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <8 x i8>*), align 8
298   ret <8 x i8> %0
299 }
300
301 define <2 x i64> @fct4() nounwind readonly ssp {
302 entry:
303 ; CHECK-LABEL: fct4:
304 ; CHECK: ldur {{q[0-9]+}}, [{{x[0-9]+}}, #3]
305   %0 = load <2 x i64>, <2 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <2 x i64>*), align 16
306   ret <2 x i64> %0
307 }
308
309 define <4 x i32> @fct5() nounwind readonly ssp {
310 entry:
311 ; CHECK-LABEL: fct5:
312 ; CHECK: ldur {{q[0-9]+}}, [{{x[0-9]+}}, #3]
313   %0 = load <4 x i32>, <4 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <4 x i32>*), align 16
314   ret <4 x i32> %0
315 }
316
317 define <8 x i16> @fct6() nounwind readonly ssp {
318 entry:
319 ; CHECK-LABEL: fct6:
320 ; CHECK: ldur {{q[0-9]+}}, [{{x[0-9]+}}, #3]
321   %0 = load <8 x i16>, <8 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <8 x i16>*), align 16
322   ret <8 x i16> %0
323 }
324
325 define <16 x i8> @fct7() nounwind readonly ssp {
326 entry:
327 ; CHECK-LABEL: fct7:
328 ; CHECK: ldur {{q[0-9]+}}, [{{x[0-9]+}}, #3]
329   %0 = load <16 x i8>, <16 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <16 x i8>*), align 16
330   ret <16 x i8> %0
331 }
332
333 define void @fct8() nounwind ssp {
334 entry:
335 ; CHECK-LABEL: fct8:
336 ; CHECK: ldur [[DESTREG:d[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
337 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
338   %0 = load <1 x i64>, <1 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <1 x i64>*), align 8
339   store <1 x i64> %0, <1 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <1 x i64>*), align 8
340   ret void
341 }
342
343 define void @fct9() nounwind ssp {
344 entry:
345 ; CHECK-LABEL: fct9:
346 ; CHECK: ldur [[DESTREG:d[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
347 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
348   %0 = load <2 x i32>, <2 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <2 x i32>*), align 8
349   store <2 x i32> %0, <2 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <2 x i32>*), align 8
350   ret void
351 }
352
353 define void @fct10() nounwind ssp {
354 entry:
355 ; CHECK-LABEL: fct10:
356 ; CHECK: ldur [[DESTREG:d[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
357 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
358   %0 = load <4 x i16>, <4 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <4 x i16>*), align 8
359   store <4 x i16> %0, <4 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <4 x i16>*), align 8
360   ret void
361 }
362
363 define void @fct11() nounwind ssp {
364 entry:
365 ; CHECK-LABEL: fct11:
366 ; CHECK: ldur [[DESTREG:d[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
367 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
368   %0 = load <8 x i8>, <8 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <8 x i8>*), align 8
369   store <8 x i8> %0, <8 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <8 x i8>*), align 8
370   ret void
371 }
372
373 define void @fct12() nounwind ssp {
374 entry:
375 ; CHECK-LABEL: fct12:
376 ; CHECK: ldur [[DESTREG:q[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
377 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
378   %0 = load <2 x i64>, <2 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <2 x i64>*), align 16
379   store <2 x i64> %0, <2 x i64>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <2 x i64>*), align 16
380   ret void
381 }
382
383 define void @fct13() nounwind ssp {
384 entry:
385 ; CHECK-LABEL: fct13:
386 ; CHECK: ldur [[DESTREG:q[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
387 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
388   %0 = load <4 x i32>, <4 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <4 x i32>*), align 16
389   store <4 x i32> %0, <4 x i32>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <4 x i32>*), align 16
390   ret void
391 }
392
393 define void @fct14() nounwind ssp {
394 entry:
395 ; CHECK-LABEL: fct14:
396 ; CHECK: ldur [[DESTREG:q[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
397 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
398   %0 = load <8 x i16>, <8 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <8 x i16>*), align 16
399   store <8 x i16> %0, <8 x i16>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <8 x i16>*), align 16
400   ret void
401 }
402
403 define void @fct15() nounwind ssp {
404 entry:
405 ; CHECK-LABEL: fct15:
406 ; CHECK: ldur [[DESTREG:q[0-9]+]], {{\[}}[[BASEREG:x[0-9]+]], #3]
407 ; CHECK: stur [[DESTREG]], {{\[}}[[BASEREG]], #4]
408   %0 = load <16 x i8>, <16 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 3) to <16 x i8>*), align 16
409   store <16 x i8> %0, <16 x i8>* bitcast (i8* getelementptr inbounds ([63 x i8], [63 x i8]* @str, i64 0, i64 4) to <16 x i8>*), align 16
410   ret void
411 }
412
413 ; Check the building of vector from a single loaded value.
414 ; Part of <rdar://problem/14170854>
415 ;
416 ; Single loads with immediate offset.
417 define <8 x i8> @fct16(i8* nocapture %sp0) {
418 ; CHECK-LABEL: fct16:
419 ; CHECK: ldr b[[REGNUM:[0-9]+]], [x0, #1]
420 ; CHECK-NEXT: mul.8b v0, v[[REGNUM]], v[[REGNUM]]
421 entry:
422   %addr = getelementptr i8, i8* %sp0, i64 1
423   %pix_sp0.0.copyload = load i8, i8* %addr, align 1
424   %vec = insertelement <8 x i8> undef, i8 %pix_sp0.0.copyload, i32 0
425   %vmull.i = mul <8 x i8> %vec, %vec
426   ret <8 x i8> %vmull.i
427 }
428
429 define <16 x i8> @fct17(i8* nocapture %sp0) {
430 ; CHECK-LABEL: fct17:
431 ; CHECK: ldr b[[REGNUM:[0-9]+]], [x0, #1]
432 ; CHECK-NEXT: mul.16b v0, v[[REGNUM]], v[[REGNUM]]
433 entry:
434   %addr = getelementptr i8, i8* %sp0, i64 1
435   %pix_sp0.0.copyload = load i8, i8* %addr, align 1
436   %vec = insertelement <16 x i8> undef, i8 %pix_sp0.0.copyload, i32 0
437   %vmull.i = mul <16 x i8> %vec, %vec
438   ret <16 x i8> %vmull.i
439 }
440
441 define <4 x i16> @fct18(i16* nocapture %sp0) {
442 ; CHECK-LABEL: fct18:
443 ; CHECK: ldr h[[REGNUM:[0-9]+]], [x0, #2]
444 ; CHECK-NEXT: mul.4h v0, v[[REGNUM]], v[[REGNUM]]
445 entry:
446   %addr = getelementptr i16, i16* %sp0, i64 1
447   %pix_sp0.0.copyload = load i16, i16* %addr, align 1
448   %vec = insertelement <4 x i16> undef, i16 %pix_sp0.0.copyload, i32 0
449   %vmull.i = mul <4 x i16> %vec, %vec
450   ret <4 x i16> %vmull.i
451 }
452
453 define <8 x i16> @fct19(i16* nocapture %sp0) {
454 ; CHECK-LABEL: fct19:
455 ; CHECK: ldr h[[REGNUM:[0-9]+]], [x0, #2]
456 ; CHECK-NEXT: mul.8h v0, v[[REGNUM]], v[[REGNUM]]
457 entry:
458   %addr = getelementptr i16, i16* %sp0, i64 1
459   %pix_sp0.0.copyload = load i16, i16* %addr, align 1
460   %vec = insertelement <8 x i16> undef, i16 %pix_sp0.0.copyload, i32 0
461   %vmull.i = mul <8 x i16> %vec, %vec
462   ret <8 x i16> %vmull.i
463 }
464
465 define <2 x i32> @fct20(i32* nocapture %sp0) {
466 ; CHECK-LABEL: fct20:
467 ; CHECK: ldr s[[REGNUM:[0-9]+]], [x0, #4]
468 ; CHECK-NEXT: mul.2s v0, v[[REGNUM]], v[[REGNUM]]
469 entry:
470   %addr = getelementptr i32, i32* %sp0, i64 1
471   %pix_sp0.0.copyload = load i32, i32* %addr, align 1
472   %vec = insertelement <2 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
473   %vmull.i = mul <2 x i32> %vec, %vec
474   ret <2 x i32> %vmull.i
475 }
476
477 define <4 x i32> @fct21(i32* nocapture %sp0) {
478 ; CHECK-LABEL: fct21:
479 ; CHECK: ldr s[[REGNUM:[0-9]+]], [x0, #4]
480 ; CHECK-NEXT: mul.4s v0, v[[REGNUM]], v[[REGNUM]]
481 entry:
482   %addr = getelementptr i32, i32* %sp0, i64 1
483   %pix_sp0.0.copyload = load i32, i32* %addr, align 1
484   %vec = insertelement <4 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
485   %vmull.i = mul <4 x i32> %vec, %vec
486   ret <4 x i32> %vmull.i
487 }
488
489 define <1 x i64> @fct22(i64* nocapture %sp0) {
490 ; CHECK-LABEL: fct22:
491 ; CHECK: ldr d0, [x0, #8]
492 entry:
493   %addr = getelementptr i64, i64* %sp0, i64 1
494   %pix_sp0.0.copyload = load i64, i64* %addr, align 1
495   %vec = insertelement <1 x i64> undef, i64 %pix_sp0.0.copyload, i32 0
496    ret <1 x i64> %vec
497 }
498
499 define <2 x i64> @fct23(i64* nocapture %sp0) {
500 ; CHECK-LABEL: fct23:
501 ; CHECK: ldr d[[REGNUM:[0-9]+]], [x0, #8]
502 entry:
503   %addr = getelementptr i64, i64* %sp0, i64 1
504   %pix_sp0.0.copyload = load i64, i64* %addr, align 1
505   %vec = insertelement <2 x i64> undef, i64 %pix_sp0.0.copyload, i32 0
506   ret <2 x i64> %vec
507 }
508
509 ;
510 ; Single loads with register offset.
511 define <8 x i8> @fct24(i8* nocapture %sp0, i64 %offset) {
512 ; CHECK-LABEL: fct24:
513 ; CHECK: ldr b[[REGNUM:[0-9]+]], [x0, x1]
514 ; CHECK-NEXT: mul.8b v0, v[[REGNUM]], v[[REGNUM]]
515 entry:
516   %addr = getelementptr i8, i8* %sp0, i64 %offset
517   %pix_sp0.0.copyload = load i8, i8* %addr, align 1
518   %vec = insertelement <8 x i8> undef, i8 %pix_sp0.0.copyload, i32 0
519   %vmull.i = mul <8 x i8> %vec, %vec
520   ret <8 x i8> %vmull.i
521 }
522
523 define <16 x i8> @fct25(i8* nocapture %sp0, i64 %offset) {
524 ; CHECK-LABEL: fct25:
525 ; CHECK: ldr b[[REGNUM:[0-9]+]], [x0, x1]
526 ; CHECK-NEXT: mul.16b v0, v[[REGNUM]], v[[REGNUM]]
527 entry:
528   %addr = getelementptr i8, i8* %sp0, i64 %offset
529   %pix_sp0.0.copyload = load i8, i8* %addr, align 1
530   %vec = insertelement <16 x i8> undef, i8 %pix_sp0.0.copyload, i32 0
531   %vmull.i = mul <16 x i8> %vec, %vec
532   ret <16 x i8> %vmull.i
533 }
534
535 define <4 x i16> @fct26(i16* nocapture %sp0, i64 %offset) {
536 ; CHECK-LABEL: fct26:
537 ; CHECK: ldr h[[REGNUM:[0-9]+]], [x0, x1, lsl #1]
538 ; CHECK-NEXT: mul.4h v0, v[[REGNUM]], v[[REGNUM]]
539 entry:
540   %addr = getelementptr i16, i16* %sp0, i64 %offset
541   %pix_sp0.0.copyload = load i16, i16* %addr, align 1
542   %vec = insertelement <4 x i16> undef, i16 %pix_sp0.0.copyload, i32 0
543   %vmull.i = mul <4 x i16> %vec, %vec
544   ret <4 x i16> %vmull.i
545 }
546
547 define <8 x i16> @fct27(i16* nocapture %sp0, i64 %offset) {
548 ; CHECK-LABEL: fct27:
549 ; CHECK: ldr h[[REGNUM:[0-9]+]], [x0, x1, lsl #1]
550 ; CHECK-NEXT: mul.8h v0, v[[REGNUM]], v[[REGNUM]]
551 entry:
552   %addr = getelementptr i16, i16* %sp0, i64 %offset
553   %pix_sp0.0.copyload = load i16, i16* %addr, align 1
554   %vec = insertelement <8 x i16> undef, i16 %pix_sp0.0.copyload, i32 0
555   %vmull.i = mul <8 x i16> %vec, %vec
556   ret <8 x i16> %vmull.i
557 }
558
559 define <2 x i32> @fct28(i32* nocapture %sp0, i64 %offset) {
560 ; CHECK-LABEL: fct28:
561 ; CHECK: ldr s[[REGNUM:[0-9]+]], [x0, x1, lsl #2]
562 ; CHECK-NEXT: mul.2s v0, v[[REGNUM]], v[[REGNUM]]
563 entry:
564   %addr = getelementptr i32, i32* %sp0, i64 %offset
565   %pix_sp0.0.copyload = load i32, i32* %addr, align 1
566   %vec = insertelement <2 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
567   %vmull.i = mul <2 x i32> %vec, %vec
568   ret <2 x i32> %vmull.i
569 }
570
571 define <4 x i32> @fct29(i32* nocapture %sp0, i64 %offset) {
572 ; CHECK-LABEL: fct29:
573 ; CHECK: ldr s[[REGNUM:[0-9]+]], [x0, x1, lsl #2]
574 ; CHECK-NEXT: mul.4s v0, v[[REGNUM]], v[[REGNUM]]
575 entry:
576   %addr = getelementptr i32, i32* %sp0, i64 %offset
577   %pix_sp0.0.copyload = load i32, i32* %addr, align 1
578   %vec = insertelement <4 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
579   %vmull.i = mul <4 x i32> %vec, %vec
580   ret <4 x i32> %vmull.i
581 }
582
583 define <1 x i64> @fct30(i64* nocapture %sp0, i64 %offset) {
584 ; CHECK-LABEL: fct30:
585 ; CHECK: ldr d0, [x0, x1, lsl #3]
586 entry:
587   %addr = getelementptr i64, i64* %sp0, i64 %offset
588   %pix_sp0.0.copyload = load i64, i64* %addr, align 1
589   %vec = insertelement <1 x i64> undef, i64 %pix_sp0.0.copyload, i32 0
590    ret <1 x i64> %vec
591 }
592
593 define <2 x i64> @fct31(i64* nocapture %sp0, i64 %offset) {
594 ; CHECK-LABEL: fct31:
595 ; CHECK: ldr d0, [x0, x1, lsl #3]
596 entry:
597   %addr = getelementptr i64, i64* %sp0, i64 %offset
598   %pix_sp0.0.copyload = load i64, i64* %addr, align 1
599   %vec = insertelement <2 x i64> undef, i64 %pix_sp0.0.copyload, i32 0
600   ret <2 x i64> %vec
601 }