1 ; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast
3 ; FIXME: We should not generate ld/st for such register spill/fill, because the
4 ; test case seems very simple and the register pressure is not high. If the
5 ; spill/fill algorithm is optimized, this test case may not be triggered. And
6 ; then we can delete it.
7 define i32 @spill.DPairReg(i8* %arg1, i32 %arg2) {
8 ; CHECK-LABEL: spill.DPairReg:
9 ; CHECK: ld2 {v{{[0-9]+}}.2s, v{{[0-9]+}}.2s}, [{{x[0-9]+|sp}}]
10 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
11 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
13 %vld = tail call { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2.v2i32(i8* %arg1, i32 4)
14 %cmp = icmp eq i32 %arg2, 0
15 br i1 %cmp, label %if.then, label %if.end
22 %vld.extract = extractvalue { <2 x i32>, <2 x i32> } %vld, 0
23 %res = extractelement <2 x i32> %vld.extract, i32 1
27 define i16 @spill.DTripleReg(i8* %arg1, i32 %arg2) {
28 ; CHECK-LABEL: spill.DTripleReg:
29 ; CHECK: ld3 {v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h}, [{{x[0-9]+|sp}}]
30 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
31 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
33 %vld = tail call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16(i8* %arg1, i32 4)
34 %cmp = icmp eq i32 %arg2, 0
35 br i1 %cmp, label %if.then, label %if.end
42 %vld.extract = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %vld, 0
43 %res = extractelement <4 x i16> %vld.extract, i32 1
47 define i16 @spill.DQuadReg(i8* %arg1, i32 %arg2) {
48 ; CHECK-LABEL: spill.DQuadReg:
49 ; CHECK: ld4 {v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h, v{{[0-9]+}}.4h}, [{{x[0-9]+|sp}}]
50 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
51 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
53 %vld = tail call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16(i8* %arg1, i32 4)
54 %cmp = icmp eq i32 %arg2, 0
55 br i1 %cmp, label %if.then, label %if.end
62 %vld.extract = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %vld, 0
63 %res = extractelement <4 x i16> %vld.extract, i32 0
67 define i32 @spill.QPairReg(i8* %arg1, i32 %arg2) {
68 ; CHECK-LABEL: spill.QPairReg:
69 ; CHECK: ld3 {v{{[0-9]+}}.4s, v{{[0-9]+}}.4s}, [{{x[0-9]+|sp}}]
70 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
71 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
73 %vld = tail call { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32(i8* %arg1, i32 4)
74 %cmp = icmp eq i32 %arg2, 0
75 br i1 %cmp, label %if.then, label %if.end
82 %vld.extract = extractvalue { <4 x i32>, <4 x i32> } %vld, 0
83 %res = extractelement <4 x i32> %vld.extract, i32 1
87 define float @spill.QTripleReg(i8* %arg1, i32 %arg2) {
88 ; CHECK-LABEL: spill.QTripleReg:
89 ; CHECK: ld3 {v{{[0-9]+}}.4s, v{{[0-9]+}}.4s, v{{[0-9]+}}.4s}, [{{x[0-9]+|sp}}]
90 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
91 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
93 %vld3 = tail call { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3.v4f32(i8* %arg1, i32 4)
94 %cmp = icmp eq i32 %arg2, 0
95 br i1 %cmp, label %if.then, label %if.end
102 %vld3.extract = extractvalue { <4 x float>, <4 x float>, <4 x float> } %vld3, 0
103 %res = extractelement <4 x float> %vld3.extract, i32 1
107 define i8 @spill.QQuadReg(i8* %arg1, i32 %arg2) {
108 ; CHECK-LABEL: spill.QQuadReg:
109 ; CHECK: ld4 {v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d, v{{[0-9]+}}.2d}, [{{x[0-9]+|sp}}]
110 ; CHECK: st1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
111 ; CHECK: ld1 {v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b}, [{{x[0-9]+|sp}}]
113 %vld = tail call { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4.v16i8(i8* %arg1, i32 4)
114 %cmp = icmp eq i32 %arg2, 0
115 br i1 %cmp, label %if.then, label %if.end
118 tail call void @foo()
122 %vld.extract = extractvalue { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } %vld, 0
123 %res = extractelement <16 x i8> %vld.extract, i32 1
127 declare { <2 x i32>, <2 x i32> } @llvm.arm.neon.vld2.v2i32(i8*, i32)
128 declare { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld3.v4i16(i8*, i32)
129 declare { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.arm.neon.vld4.v4i16(i8*, i32)
130 declare { <4 x i32>, <4 x i32> } @llvm.arm.neon.vld2.v4i32(i8*, i32)
131 declare { <4 x float>, <4 x float>, <4 x float> } @llvm.arm.neon.vld3.v4f32(i8*, i32)
132 declare { <16 x i8>, <16 x i8>, <16 x i8>, <16 x i8> } @llvm.arm.neon.vld4.v16i8(i8*, i32)
136 ; FIXME: We should not generate ld/st for such register spill/fill, because the
137 ; test case seems very simple and the register pressure is not high. If the
138 ; spill/fill algorithm is optimized, this test case may not be triggered. And
139 ; then we can delete it.
140 ; check the spill for Register Class QPair_with_qsub_0_in_FPR128Lo
141 define <8 x i16> @test_2xFPR128Lo(i64 %got, i8* %ptr, <1 x i64> %a) {
142 tail call void @llvm.arm.neon.vst2lane.v1i64(i8* %ptr, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i32 0, i32 8)
143 tail call void @foo()
144 %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
145 %1 = bitcast <2 x i64> %sv to <8 x i16>
146 %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
147 %3 = mul <8 x i16> %2, %2
151 ; check the spill for Register Class QTriple_with_qsub_0_in_FPR128Lo
152 define <8 x i16> @test_3xFPR128Lo(i64 %got, i8* %ptr, <1 x i64> %a) {
153 tail call void @llvm.arm.neon.vst3lane.v1i64(i8* %ptr, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i32 0, i32 8)
154 tail call void @foo()
155 %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
156 %1 = bitcast <2 x i64> %sv to <8 x i16>
157 %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
158 %3 = mul <8 x i16> %2, %2
162 ; check the spill for Register Class QQuad_with_qsub_0_in_FPR128Lo
163 define <8 x i16> @test_4xFPR128Lo(i64 %got, i8* %ptr, <1 x i64> %a) {
164 tail call void @llvm.arm.neon.vst4lane.v1i64(i8* %ptr, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, <1 x i64> zeroinitializer, i32 0, i32 8)
165 tail call void @foo()
166 %sv = shufflevector <1 x i64> zeroinitializer, <1 x i64> %a, <2 x i32> <i32 0, i32 1>
167 %1 = bitcast <2 x i64> %sv to <8 x i16>
168 %2 = shufflevector <8 x i16> %1, <8 x i16> undef, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>
169 %3 = mul <8 x i16> %2, %2
173 declare void @llvm.arm.neon.vst2lane.v1i64(i8*, <1 x i64>, <1 x i64>, i32, i32)
174 declare void @llvm.arm.neon.vst3lane.v1i64(i8*, <1 x i64>, <1 x i64>, <1 x i64>, i32, i32)
175 declare void @llvm.arm.neon.vst4lane.v1i64(i8*, <1 x i64>, <1 x i64>, <1 x i64>, <1 x i64>, i32, i32)