Implement AArch64 post-index vector load/store multiple N-element structure class...
[oota-llvm.git] / test / CodeGen / AArch64 / neon-simd-post-ldst-multi-elem.ll
1 ; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon | FileCheck %s
2
3 define <4 x i16> @test_vld1_fx_update(i16** %ptr) nounwind {
4 ; CHECK: test_vld1_fx_update
5 ; CHECK: ld1 {v{{[0-9]+}}.4h}, [x{{[0-9]+|sp}}], #8
6   %A = load i16** %ptr
7   %tmp0 = bitcast i16* %A to i8*
8   %tmp1 = call <4 x i16> @llvm.arm.neon.vld1.v4i16(i8* %tmp0, i32 2)
9   %tmp2 = getelementptr i16* %A, i32 4
10   store i16* %tmp2, i16** %ptr
11   ret <4 x i16> %tmp1
12 }
13
14 define <2 x i32> @test_vld1_reg_update(i32** %ptr, i32 %inc) nounwind {
15 ; CHECK: test_vld1_reg_update
16 ; CHECK: ld1 {v{{[0-9]+}}.2s}, [x{{[0-9]+|sp}}], x{{[0-9]+}}
17   %A = load i32** %ptr
18   %tmp0 = bitcast i32* %A to i8*
19   %tmp1 = call <2 x i32> @llvm.arm.neon.vld1.v2i32(i8* %tmp0, i32 4)
20   %tmp2 = getelementptr i32* %A, i32 %inc
21   store i32* %tmp2, i32** %ptr
22   ret <2 x i32> %tmp1
23 }
24
25 define <2 x float> @test_vld2_fx_update(float** %ptr) nounwind {
26 ; CHECK: test_vld2_fx_update
27 ; CHECK: ld2 {v{{[0-9]+}}.2s, v{{[0-9]+}}.2s}, [x{{[0-9]+|sp}}], #16
28   %A = load float** %ptr
29   %tmp0 = bitcast float* %A to i8*
30   %tmp1 = call { <2 x float>, <2 x float> } @llvm.arm.neon.vld2.v2f32(i8* %tmp0, i32 4)
31   %tmp2 = extractvalue { <2 x float>, <2 x float> } %tmp1, 0
32   %tmp3 = getelementptr float* %A, i32 4
33   store float* %tmp3, float** %ptr
34   ret <2 x float> %tmp2
35 }
36
37 define <16 x i8> @test_vld2_reg_update(i8** %ptr, i32 %inc) nounwind {
38 ; CHECK: test_vld2_reg_update
39 ; CHECK: ld2 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [x{{[0-9]+|sp}}], x{{[0-9]+}}
40   %A = load i8** %ptr
41   %tmp0 = call { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2.v16i8(i8* %A, i32 1)
42   %tmp1 = extractvalue { <16 x i8>, <16 x i8> } %tmp0, 0
43   %tmp2 = getelementptr i8* %A, i32 %inc
44   store i8* %tmp2, i8** %ptr
45   ret <16 x i8> %tmp1
46 }
47
48 define <4 x i32> @test_vld3_fx_update(i32** %ptr) nounwind {
49 ; CHECK: test_vld3_fx_update
50 ; CHECK: ld3 {v{{[0-9]+}}.4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s}, [x{{[0-9]+|sp}}], #48
51   %A = load i32** %ptr
52   %tmp0 = bitcast i32* %A to i8*
53   %tmp1 = call { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32(i8* %tmp0, i32 4)
54   %tmp2 = extractvalue { <4 x i32>, <4 x i32>, <4 x i32> } %tmp1, 0
55   %tmp3 = getelementptr i32* %A, i32 12
56   store i32* %tmp3, i32** %ptr
57   ret <4 x i32> %tmp2
58 }
59
60 define <4 x i16> @test_vld3_reg_update(i16** %ptr, i32 %inc) nounwind {
61 ; CHECK: test_vld3_reg_update
62 ; CHECK: ld3 {v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h}, [x{{[0-9]+|sp}}], x{{[0-9]+}}
63   %A = load i16** %ptr
64   %tmp0 = bitcast i16* %A to i8*
65   %tmp1 = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16(i8* %tmp0, i32 2)
66   %tmp2 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %tmp1, 0
67   %tmp3 = getelementptr i16* %A, i32 %inc
68   store i16* %tmp3, i16** %ptr
69   ret <4 x i16> %tmp2
70 }
71
72 define <8 x i16> @test_vld4_fx_update(i16** %ptr) nounwind {
73 ; CHECK: test_vld4_fx_update
74 ; CHECK: ld4 {v{{[0-9]+}}.8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h}, [x{{[0-9]+|sp}}], #64
75   %A = load i16** %ptr
76   %tmp0 = bitcast i16* %A to i8*
77   %tmp1 = call { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16(i8* %tmp0, i32 8)
78   %tmp2 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } %tmp1, 0
79   %tmp3 = getelementptr i16* %A, i32 32
80   store i16* %tmp3, i16** %ptr
81   ret <8 x i16> %tmp2
82 }
83
84 ;Check for a post-increment updating load with register increment.
85 define <8 x i8> @test_vld4_reg_update(i8** %ptr, i32 %inc) nounwind {
86 ; CHECK: test_vld4_reg_update
87 ; CHECK: ld4 {v{{[0-9]+}}.8b, v{{[0-9]+}}.8b, v{{[0-9]+}}.8b, v{{[0-9]+}}.8b}, [x{{[0-9]+|sp}}], x{{[0-9]+}}
88   %A = load i8** %ptr
89   %tmp0 = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4.v8i8(i8* %A, i32 1)
90   %tmp1 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %tmp0, 0
91   %tmp2 = getelementptr i8* %A, i32 %inc
92   store i8* %tmp2, i8** %ptr
93   ret <8 x i8> %tmp1
94 }
95
96 ;Check for a post-increment updating store.
97 define void @test_vst1_fx_update(float** %ptr, <2 x float> %B) nounwind {
98 ; CHECK: test_vst1_fx_update
99 ; CHECK: st1 {v{{[0-9]+}}.2s}, [{{x[0-9]+|sp}}], #8
100   %A = load float** %ptr
101   %tmp0 = bitcast float* %A to i8*
102   call void @llvm.arm.neon.vst1.v2f32(i8* %tmp0, <2 x float> %B, i32 4)
103   %tmp2 = getelementptr float* %A, i32 2
104   store float* %tmp2, float** %ptr
105   ret void
106 }
107
108 define void @test_vst1_reg_update(i16** %ptr, <8 x i16> %B, i32 %inc) nounwind {
109 ; CHECK: test_vst1_reg_update
110 ; CHECK: st1 {v{{[0-9]+}}.8h}, [{{x[0-9]+|sp}}], x{{[0-9]+}}
111   %A = load i16** %ptr
112   %tmp0 = bitcast i16* %A to i8*
113   call void @llvm.arm.neon.vst1.v8i16(i8* %tmp0, <8 x i16> %B, i32 2)
114   %tmp1 = getelementptr i16* %A, i32 %inc
115   store i16* %tmp1, i16** %ptr
116   ret void
117 }
118
119 define void @test_vst2_fx_update(i64** %ptr, <1 x i64> %B) nounwind {
120 ; CHECK: test_vst2_fx_update
121 ; CHECK: st1 {v{{[0-9]+}}.1d, v{{[0-9]+}}.1d}, [{{x[0-9]+|sp}}], #16
122   %A = load i64** %ptr
123   %tmp0 = bitcast i64* %A to i8*
124   call void @llvm.arm.neon.vst2.v1i64(i8* %tmp0, <1 x i64> %B, <1 x i64> %B, i32 8)
125   %tmp1 = getelementptr i64* %A, i32 2
126   store i64* %tmp1, i64** %ptr
127   ret void
128 }
129
130 define void @test_vst2_reg_update(i8** %ptr, <8 x i8> %B, i32 %inc) nounwind {
131 ; CHECK: test_vst2_reg_update
132 ; CHECK: st2 {v{{[0-9]+}}.8b, v{{[0-9]+}}.8b}, [{{x[0-9]+|sp}}], x{{[0-9]+}}
133   %A = load i8** %ptr
134   call void @llvm.arm.neon.vst2.v8i8(i8* %A, <8 x i8> %B, <8 x i8> %B, i32 4)
135   %tmp0 = getelementptr i8* %A, i32 %inc
136   store i8* %tmp0, i8** %ptr
137   ret void
138 }
139
140 define void @test_vst3_fx_update(i32** %ptr, <2 x i32> %B) nounwind {
141 ; CHECK: test_vst3_fx_update
142 ; CHECK: st3 {v{{[0-9]+}}.2s, v{{[0-9]+}}.2s, v{{[0-9]+}}.2s}, [{{x[0-9]+|sp}}], #24
143   %A = load i32** %ptr
144   %tmp0 = bitcast i32* %A to i8*
145   call void @llvm.arm.neon.vst3.v2i32(i8* %tmp0, <2 x i32> %B, <2 x i32> %B, <2 x i32> %B, i32 4)
146   %tmp1 = getelementptr i32* %A, i32 6
147   store i32* %tmp1, i32** %ptr
148   ret void
149 }
150
151 define void @test_vst3_reg_update(i16** %ptr, <8 x i16> %B, i32 %inc) nounwind {
152 ; CHECK: test_vst3_reg_update
153 ; CHECK: st3 {v{{[0-9]+}}.8h, v{{[0-9]+}}.8h, v{{[0-9]+}}.8h}, [{{x[0-9]+|sp}}], x{{[0-9]+}}
154   %A = load i16** %ptr
155   %tmp0 = bitcast i16* %A to i8*
156   call void @llvm.arm.neon.vst3.v8i16(i8* %tmp0, <8 x i16> %B, <8 x i16> %B, <8 x i16> %B, i32 2)
157   %tmp1 = getelementptr i16* %A, i32 %inc
158   store i16* %tmp1, i16** %ptr
159   ret void
160 }
161
162 define void @test_vst4_fx_update(float** %ptr, <4 x float> %B) nounwind {
163 ; CHECK: test_vst4_fx_update
164 ; CHECK: st4 {v{{[0-9]+}}.4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s}, [{{x[0-9]+|sp}}], #64
165   %A = load float** %ptr
166   %tmp0 = bitcast float* %A to i8*
167   call void @llvm.arm.neon.vst4.v4f32(i8* %tmp0, <4 x float> %B, <4 x float> %B, <4 x float> %B, <4 x float> %B, i32 4)
168   %tmp1 = getelementptr float* %A, i32 16
169   store float* %tmp1, float** %ptr
170   ret void
171 }
172
173 define void @test_vst4_reg_update(i8** %ptr, <8 x i8> %B, i32 %inc) nounwind {
174 ; CHECK: test_vst4_reg_update
175 ; CHECK: st4 {v{{[0-9]+}}.8b, v{{[0-9]+}}.8b, v{{[0-9]+}}.8b, v{{[0-9]+}}.8b}, [{{x[0-9]+|sp}}], x{{[0-9]+}}
176   %A = load i8** %ptr
177   call void @llvm.arm.neon.vst4.v8i8(i8* %A, <8 x i8> %B, <8 x i8> %B, <8 x i8> %B, <8 x i8> %B, i32 1)
178   %tmp0 = getelementptr i8* %A, i32 %inc
179   store i8* %tmp0, i8** %ptr
180   ret void
181 }
182
183
184 declare <4 x i16> @llvm.arm.neon.vld1.v4i16(i8*, i32)
185 declare <2 x i32> @llvm.arm.neon.vld1.v2i32(i8*, i32)
186 declare { <16 x i8>, <16 x i8> } @llvm.arm.neon.vld2.v16i8(i8*, i32)
187 declare { <2 x float>, <2 x float> } @llvm.arm.neon.vld2.v2f32(i8*, i32)
188 declare { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16(i8*, i32)
189 declare { <4 x i32>, <4 x i32>, <4 x i32> } @llvm.arm.neon.vld3.v4i32(i8*, i32)
190 declare { <8 x i16>, <8 x i16>, <8 x i16>, <8 x i16> } @llvm.arm.neon.vld4.v8i16(i8*, i32)
191 declare { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.arm.neon.vld4.v8i8(i8*, i32)
192
193 declare void @llvm.arm.neon.vst1.v2f32(i8*, <2 x float>, i32)
194 declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32)
195 declare void @llvm.arm.neon.vst2.v1i64(i8*, <1 x i64>, <1 x i64>, i32)
196 declare void @llvm.arm.neon.vst2.v8i8(i8*, <8 x i8>, <8 x i8>, i32)
197 declare void @llvm.arm.neon.vst3.v2i32(i8*, <2 x i32>, <2 x i32>, <2 x i32>, i32)
198 declare void @llvm.arm.neon.vst3.v8i16(i8*, <8 x i16>, <8 x i16>, <8 x i16>, i32)
199 declare void @llvm.arm.neon.vst4.v4f32(i8*, <4 x float>, <4 x float>, <4 x float>, <4 x float>, i32)
200 declare void @llvm.arm.neon.vst4.v8i8(i8*, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, i32)