]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGen/X86/sse-fsignum.ll
Vendor import of llvm trunk r291274:
[FreeBSD/FreeBSD.git] / test / CodeGen / X86 / sse-fsignum.ll
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s --check-prefix=AVX --check-prefix=AVX1
3 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2 | FileCheck %s --check-prefix=AVX --check-prefix=AVX2
4 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx512f | FileCheck %s --check-prefix=AVX --check-prefix=AVX512F
5
6 ; 'signum' test cases (PR13248)
7
8 ;
9 ; generic implementation for 128-bit vectors
10 ;
11
12 define void @signum32a(<4 x float>*) {
13 ; AVX-LABEL: signum32a:
14 ; AVX:       # BB#0: # %entry
15 ; AVX-NEXT:    vmovaps (%rdi), %xmm0
16 ; AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1
17 ; AVX-NEXT:    vcmpltps %xmm1, %xmm0, %xmm2
18 ; AVX-NEXT:    vcvtdq2ps %xmm2, %xmm2
19 ; AVX-NEXT:    vcmpltps %xmm0, %xmm1, %xmm0
20 ; AVX-NEXT:    vcvtdq2ps %xmm0, %xmm0
21 ; AVX-NEXT:    vsubps %xmm0, %xmm2, %xmm0
22 ; AVX-NEXT:    vmovaps %xmm0, (%rdi)
23 ; AVX-NEXT:    retq
24 entry:
25   %1 = load <4 x float>, <4 x float>* %0
26   %2 = fcmp olt <4 x float> %1, zeroinitializer
27   %3 = sitofp <4 x i1> %2 to <4 x float>
28   %4 = fcmp ogt <4 x float> %1, zeroinitializer
29   %5 = sitofp <4 x i1> %4 to <4 x float>
30   %6 = fsub <4 x float> %3, %5
31   store <4 x float> %6, <4 x float>* %0
32   ret void
33 }
34
35 define void @signum64a(<2 x double>*) {
36 ; AVX-LABEL: signum64a:
37 ; AVX:       # BB#0: # %entry
38 ; AVX-NEXT:    vmovapd (%rdi), %xmm0
39 ; AVX-NEXT:    vxorpd %xmm1, %xmm1, %xmm1
40 ; AVX-NEXT:    vcmpltpd %xmm1, %xmm0, %xmm2
41 ; AVX-NEXT:    vpermilps {{.*#+}} xmm2 = xmm2[0,2,2,3]
42 ; AVX-NEXT:    vcvtdq2pd %xmm2, %xmm2
43 ; AVX-NEXT:    vcmpltpd %xmm0, %xmm1, %xmm0
44 ; AVX-NEXT:    vpermilps {{.*#+}} xmm0 = xmm0[0,2,2,3]
45 ; AVX-NEXT:    vcvtdq2pd %xmm0, %xmm0
46 ; AVX-NEXT:    vsubpd %xmm0, %xmm2, %xmm0
47 ; AVX-NEXT:    vmovapd %xmm0, (%rdi)
48 ; AVX-NEXT:    retq
49 entry:
50   %1 = load <2 x double>, <2 x double>* %0
51   %2 = fcmp olt <2 x double> %1, zeroinitializer
52   %3 = sitofp <2 x i1> %2 to <2 x double>
53   %4 = fcmp ogt <2 x double> %1, zeroinitializer
54   %5 = sitofp <2 x i1> %4 to <2 x double>
55   %6 = fsub <2 x double> %3, %5
56   store <2 x double> %6, <2 x double>* %0
57   ret void
58 }
59
60 ;
61 ; generic implementation for 256-bit vectors
62 ;
63
64 define void @signum32b(<8 x float>*) {
65 ; AVX1-LABEL: signum32b:
66 ; AVX1:       # BB#0: # %entry
67 ; AVX1-NEXT:    vmovaps (%rdi), %ymm0
68 ; AVX1-NEXT:    vxorps %ymm1, %ymm1, %ymm1
69 ; AVX1-NEXT:    vcmpltps %ymm1, %ymm0, %ymm2
70 ; AVX1-NEXT:    vcvtdq2ps %ymm2, %ymm2
71 ; AVX1-NEXT:    vcmpltps %ymm0, %ymm1, %ymm0
72 ; AVX1-NEXT:    vcvtdq2ps %ymm0, %ymm0
73 ; AVX1-NEXT:    vsubps %ymm0, %ymm2, %ymm0
74 ; AVX1-NEXT:    vmovaps %ymm0, (%rdi)
75 ; AVX1-NEXT:    vzeroupper
76 ; AVX1-NEXT:    retq
77 ;
78 ; AVX2-LABEL: signum32b:
79 ; AVX2:       # BB#0: # %entry
80 ; AVX2-NEXT:    vmovaps (%rdi), %ymm0
81 ; AVX2-NEXT:    vxorps %ymm1, %ymm1, %ymm1
82 ; AVX2-NEXT:    vcmpltps %ymm1, %ymm0, %ymm2
83 ; AVX2-NEXT:    vcvtdq2ps %ymm2, %ymm2
84 ; AVX2-NEXT:    vcmpltps %ymm0, %ymm1, %ymm0
85 ; AVX2-NEXT:    vcvtdq2ps %ymm0, %ymm0
86 ; AVX2-NEXT:    vsubps %ymm0, %ymm2, %ymm0
87 ; AVX2-NEXT:    vmovaps %ymm0, (%rdi)
88 ; AVX2-NEXT:    vzeroupper
89 ; AVX2-NEXT:    retq
90 ;
91 ; AVX512F-LABEL: signum32b:
92 ; AVX512F:       # BB#0: # %entry
93 ; AVX512F-NEXT:    vmovaps (%rdi), %ymm0
94 ; AVX512F-NEXT:    vxorps %ymm1, %ymm1, %ymm1
95 ; AVX512F-NEXT:    vcmpltps %zmm1, %zmm0, %k1
96 ; AVX512F-NEXT:    vpternlogd $255, %zmm2, %zmm2, %zmm2
97 ; AVX512F-NEXT:    vmovdqa64 %zmm2, %zmm3 {%k1} {z}
98 ; AVX512F-NEXT:    vpmovqd %zmm3, %ymm3
99 ; AVX512F-NEXT:    vcvtdq2ps %ymm3, %ymm3
100 ; AVX512F-NEXT:    vcmpltps %zmm0, %zmm1, %k1
101 ; AVX512F-NEXT:    vmovdqa64 %zmm2, %zmm0 {%k1} {z}
102 ; AVX512F-NEXT:    vpmovqd %zmm0, %ymm0
103 ; AVX512F-NEXT:    vcvtdq2ps %ymm0, %ymm0
104 ; AVX512F-NEXT:    vsubps %ymm0, %ymm3, %ymm0
105 ; AVX512F-NEXT:    vmovaps %ymm0, (%rdi)
106 ; AVX512F-NEXT:    retq
107 entry:
108   %1 = load <8 x float>, <8 x float>* %0
109   %2 = fcmp olt <8 x float> %1, zeroinitializer
110   %3 = sitofp <8 x i1> %2 to <8 x float>
111   %4 = fcmp ogt <8 x float> %1, zeroinitializer
112   %5 = sitofp <8 x i1> %4 to <8 x float>
113   %6 = fsub <8 x float> %3, %5
114   store <8 x float> %6, <8 x float>* %0
115   ret void
116 }
117
118 define void @signum64b(<4 x double>*) {
119 ; AVX1-LABEL: signum64b:
120 ; AVX1:       # BB#0: # %entry
121 ; AVX1-NEXT:    vmovapd (%rdi), %ymm0
122 ; AVX1-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
123 ; AVX1-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
124 ; AVX1-NEXT:    vextractf128 $1, %ymm2, %xmm3
125 ; AVX1-NEXT:    vpacksswb %xmm3, %xmm2, %xmm2
126 ; AVX1-NEXT:    vcvtdq2pd %xmm2, %ymm2
127 ; AVX1-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
128 ; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm1
129 ; AVX1-NEXT:    vpacksswb %xmm1, %xmm0, %xmm0
130 ; AVX1-NEXT:    vcvtdq2pd %xmm0, %ymm0
131 ; AVX1-NEXT:    vsubpd %ymm0, %ymm2, %ymm0
132 ; AVX1-NEXT:    vmovapd %ymm0, (%rdi)
133 ; AVX1-NEXT:    vzeroupper
134 ; AVX1-NEXT:    retq
135 ;
136 ; AVX2-LABEL: signum64b:
137 ; AVX2:       # BB#0: # %entry
138 ; AVX2-NEXT:    vmovapd (%rdi), %ymm0
139 ; AVX2-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
140 ; AVX2-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
141 ; AVX2-NEXT:    vextractf128 $1, %ymm2, %xmm3
142 ; AVX2-NEXT:    vpacksswb %xmm3, %xmm2, %xmm2
143 ; AVX2-NEXT:    vcvtdq2pd %xmm2, %ymm2
144 ; AVX2-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
145 ; AVX2-NEXT:    vextractf128 $1, %ymm0, %xmm1
146 ; AVX2-NEXT:    vpacksswb %xmm1, %xmm0, %xmm0
147 ; AVX2-NEXT:    vcvtdq2pd %xmm0, %ymm0
148 ; AVX2-NEXT:    vsubpd %ymm0, %ymm2, %ymm0
149 ; AVX2-NEXT:    vmovapd %ymm0, (%rdi)
150 ; AVX2-NEXT:    vzeroupper
151 ; AVX2-NEXT:    retq
152 ;
153 ; AVX512F-LABEL: signum64b:
154 ; AVX512F:       # BB#0: # %entry
155 ; AVX512F-NEXT:    vmovapd (%rdi), %ymm0
156 ; AVX512F-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
157 ; AVX512F-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
158 ; AVX512F-NEXT:    vpmovqd %zmm2, %ymm2
159 ; AVX512F-NEXT:    vcvtdq2pd %xmm2, %ymm2
160 ; AVX512F-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
161 ; AVX512F-NEXT:    vpmovqd %zmm0, %ymm0
162 ; AVX512F-NEXT:    vcvtdq2pd %xmm0, %ymm0
163 ; AVX512F-NEXT:    vsubpd %ymm0, %ymm2, %ymm0
164 ; AVX512F-NEXT:    vmovapd %ymm0, (%rdi)
165 ; AVX512F-NEXT:    retq
166 entry:
167   %1 = load <4 x double>, <4 x double>* %0
168   %2 = fcmp olt <4 x double> %1, zeroinitializer
169   %3 = sitofp <4 x i1> %2 to <4 x double>
170   %4 = fcmp ogt <4 x double> %1, zeroinitializer
171   %5 = sitofp <4 x i1> %4 to <4 x double>
172   %6 = fsub <4 x double> %3, %5
173   store <4 x double> %6, <4 x double>* %0
174   ret void
175 }
176
177 ;
178 ; implementation using AVX intrinsics for 256-bit vectors
179 ;
180
181 define void @signum32c(<8 x float>*) {
182 ; AVX1-LABEL: signum32c:
183 ; AVX1:       # BB#0: # %entry
184 ; AVX1-NEXT:    vmovaps (%rdi), %ymm0
185 ; AVX1-NEXT:    vxorps %ymm1, %ymm1, %ymm1
186 ; AVX1-NEXT:    vcmpltps %ymm1, %ymm0, %ymm2
187 ; AVX1-NEXT:    vcvtdq2ps %ymm2, %ymm2
188 ; AVX1-NEXT:    vcmpltps %ymm0, %ymm1, %ymm0
189 ; AVX1-NEXT:    vcvtdq2ps %ymm0, %ymm0
190 ; AVX1-NEXT:    vsubps %ymm0, %ymm2, %ymm0
191 ; AVX1-NEXT:    vmovaps %ymm0, (%rdi)
192 ; AVX1-NEXT:    vzeroupper
193 ; AVX1-NEXT:    retq
194 ;
195 ; AVX2-LABEL: signum32c:
196 ; AVX2:       # BB#0: # %entry
197 ; AVX2-NEXT:    vmovaps (%rdi), %ymm0
198 ; AVX2-NEXT:    vxorps %ymm1, %ymm1, %ymm1
199 ; AVX2-NEXT:    vcmpltps %ymm1, %ymm0, %ymm2
200 ; AVX2-NEXT:    vcvtdq2ps %ymm2, %ymm2
201 ; AVX2-NEXT:    vcmpltps %ymm0, %ymm1, %ymm0
202 ; AVX2-NEXT:    vcvtdq2ps %ymm0, %ymm0
203 ; AVX2-NEXT:    vsubps %ymm0, %ymm2, %ymm0
204 ; AVX2-NEXT:    vmovaps %ymm0, (%rdi)
205 ; AVX2-NEXT:    vzeroupper
206 ; AVX2-NEXT:    retq
207 ;
208 ; AVX512F-LABEL: signum32c:
209 ; AVX512F:       # BB#0: # %entry
210 ; AVX512F-NEXT:    vmovaps (%rdi), %ymm0
211 ; AVX512F-NEXT:    vxorps %ymm1, %ymm1, %ymm1
212 ; AVX512F-NEXT:    vcmpltps %ymm1, %ymm0, %ymm2
213 ; AVX512F-NEXT:    vcvtdq2ps %ymm2, %ymm2
214 ; AVX512F-NEXT:    vcmpltps %ymm0, %ymm1, %ymm0
215 ; AVX512F-NEXT:    vcvtdq2ps %ymm0, %ymm0
216 ; AVX512F-NEXT:    vsubps %ymm0, %ymm2, %ymm0
217 ; AVX512F-NEXT:    vmovaps %ymm0, (%rdi)
218 ; AVX512F-NEXT:    retq
219 entry:
220   %1 = load <8 x float>, <8 x float>* %0
221   %2 = tail call <8 x float> @llvm.x86.avx.cmp.ps.256(<8 x float> %1, <8 x float> zeroinitializer, i8 1)
222   %3 = bitcast <8 x float> %2 to <8 x i32>
223   %4 = sitofp <8 x i32> %3 to <8 x float>
224   %5 = tail call <8 x float> @llvm.x86.avx.cmp.ps.256(<8 x float> zeroinitializer, <8 x float> %1, i8 1)
225   %6 = bitcast <8 x float> %5 to <8 x i32>
226   %7 = sitofp <8 x i32> %6 to <8 x float>
227   %8 = fsub <8 x float> %4, %7
228   store <8 x float> %8, <8 x float>* %0
229   ret void
230 }
231
232 define void @signum64c(<4 x double>*) {
233 ; AVX1-LABEL: signum64c:
234 ; AVX1:       # BB#0: # %entry
235 ; AVX1-NEXT:    vmovapd (%rdi), %ymm0
236 ; AVX1-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
237 ; AVX1-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
238 ; AVX1-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
239 ; AVX1-NEXT:    vextractf128 $1, %ymm0, %xmm1
240 ; AVX1-NEXT:    vextractf128 $1, %ymm2, %xmm3
241 ; AVX1-NEXT:    vpsubd %xmm1, %xmm3, %xmm1
242 ; AVX1-NEXT:    vpsubd %xmm0, %xmm2, %xmm0
243 ; AVX1-NEXT:    vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2]
244 ; AVX1-NEXT:    vcvtdq2pd %xmm0, %ymm0
245 ; AVX1-NEXT:    vmovaps %ymm0, (%rdi)
246 ; AVX1-NEXT:    vzeroupper
247 ; AVX1-NEXT:    retq
248 ;
249 ; AVX2-LABEL: signum64c:
250 ; AVX2:       # BB#0: # %entry
251 ; AVX2-NEXT:    vmovapd (%rdi), %ymm0
252 ; AVX2-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
253 ; AVX2-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
254 ; AVX2-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
255 ; AVX2-NEXT:    vpsubd %ymm0, %ymm2, %ymm0
256 ; AVX2-NEXT:    vextracti128 $1, %ymm0, %xmm1
257 ; AVX2-NEXT:    vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2]
258 ; AVX2-NEXT:    vcvtdq2pd %xmm0, %ymm0
259 ; AVX2-NEXT:    vmovaps %ymm0, (%rdi)
260 ; AVX2-NEXT:    vzeroupper
261 ; AVX2-NEXT:    retq
262 ;
263 ; AVX512F-LABEL: signum64c:
264 ; AVX512F:       # BB#0: # %entry
265 ; AVX512F-NEXT:    vmovapd (%rdi), %ymm0
266 ; AVX512F-NEXT:    vxorpd %ymm1, %ymm1, %ymm1
267 ; AVX512F-NEXT:    vcmpltpd %ymm1, %ymm0, %ymm2
268 ; AVX512F-NEXT:    vcmpltpd %ymm0, %ymm1, %ymm0
269 ; AVX512F-NEXT:    vpsubd %ymm0, %ymm2, %ymm0
270 ; AVX512F-NEXT:    vextracti128 $1, %ymm0, %xmm1
271 ; AVX512F-NEXT:    vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2]
272 ; AVX512F-NEXT:    vcvtdq2pd %xmm0, %ymm0
273 ; AVX512F-NEXT:    vmovaps %ymm0, (%rdi)
274 ; AVX512F-NEXT:    retq
275 entry:
276   %x = load <4 x double>, <4 x double>* %0
277   %xgt = tail call <4 x double> @llvm.x86.avx.cmp.pd.256(<4 x double> %x, <4 x double> zeroinitializer, i8 1)
278   %igt = bitcast <4 x double> %xgt to <8 x i32>
279   %xlt = tail call <4 x double> @llvm.x86.avx.cmp.pd.256(<4 x double> zeroinitializer, <4 x double> %x, i8 1)
280   %ilt = bitcast <4 x double> %xlt to <8 x i32>
281   ; it is important to use %igt twice as source in order to make LLVM use a shuffle operation
282   %isign = sub <8 x i32> %igt, %ilt
283   %ssign = shufflevector <8 x i32> %isign, <8 x i32> %isign, <4 x i32> <i32 0, i32 2, i32 12, i32 14>
284   %sign = tail call <4 x double> @llvm.x86.avx.cvtdq2.pd.256(<4 x i32> %ssign)
285   store <4 x double> %sign, <4 x double>* %0
286   ret void
287 }
288
289 declare <8 x float> @llvm.x86.avx.cmp.ps.256(<8 x float>, <8 x float>, i8) nounwind readnone
290
291 declare <4 x double> @llvm.x86.avx.cmp.pd.256(<4 x double>, <4 x double>, i8) nounwind readnone
292
293 declare <4 x double> @llvm.x86.avx.cvtdq2.pd.256(<4 x i32>) nounwind readnone