Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / X86 / vselect-constants.ll
blob0630a40b88099e05a7a963213282243cf0c88924
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=SSE
3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx  | FileCheck %s --check-prefix=AVX
5 ; First, check the generic pattern for any 2 vector constants. Then, check special cases where
6 ; the constants are all off-by-one. Finally, check the extra special cases where the constants
7 ; include 0 or -1.
8 ; Each minimal select test is repeated with a more typical pattern that includes a compare to
9 ; generate the condition value.
11 ; TODO: If we don't have blendv, this can definitely be improved. There's also a selection of
12 ; chips where it makes sense to transform the general case blendv to 2 bit-ops. That should be
13 ; a uarch-specfic transform. At some point (Ryzen?), the implementation should catch up to the
14 ; architecture, so blendv is as fast as a single bit-op.
16 define <4 x i32> @sel_C1_or_C2_vec(<4 x i1> %cond) {
17 ; SSE-LABEL: sel_C1_or_C2_vec:
18 ; SSE:       # %bb.0:
19 ; SSE-NEXT:    pslld $31, %xmm0
20 ; SSE-NEXT:    psrad $31, %xmm0
21 ; SSE-NEXT:    movdqa %xmm0, %xmm1
22 ; SSE-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
23 ; SSE-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
24 ; SSE-NEXT:    por %xmm1, %xmm0
25 ; SSE-NEXT:    retq
27 ; AVX-LABEL: sel_C1_or_C2_vec:
28 ; AVX:       # %bb.0:
29 ; AVX-NEXT:    vpslld $31, %xmm0, %xmm0
30 ; AVX-NEXT:    vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
31 ; AVX-NEXT:    vblendvps %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0
32 ; AVX-NEXT:    retq
33   %add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
34   ret <4 x i32> %add
37 define <4 x i32> @cmp_sel_C1_or_C2_vec(<4 x i32> %x, <4 x i32> %y) {
38 ; SSE-LABEL: cmp_sel_C1_or_C2_vec:
39 ; SSE:       # %bb.0:
40 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
41 ; SSE-NEXT:    movdqa %xmm0, %xmm1
42 ; SSE-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
43 ; SSE-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
44 ; SSE-NEXT:    por %xmm1, %xmm0
45 ; SSE-NEXT:    retq
47 ; AVX-LABEL: cmp_sel_C1_or_C2_vec:
48 ; AVX:       # %bb.0:
49 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
50 ; AVX-NEXT:    vmovaps {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
51 ; AVX-NEXT:    vblendvps %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0
52 ; AVX-NEXT:    retq
53   %cond = icmp eq <4 x i32> %x, %y
54   %add = select <4 x i1> %cond, <4 x i32> <i32 3000, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
55   ret <4 x i32> %add
58 define <4 x i32> @sel_Cplus1_or_C_vec(<4 x i1> %cond) {
59 ; SSE-LABEL: sel_Cplus1_or_C_vec:
60 ; SSE:       # %bb.0:
61 ; SSE-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
62 ; SSE-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
63 ; SSE-NEXT:    retq
65 ; AVX-LABEL: sel_Cplus1_or_C_vec:
66 ; AVX:       # %bb.0:
67 ; AVX-NEXT:    vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
68 ; AVX-NEXT:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
69 ; AVX-NEXT:    retq
70   %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
71   ret <4 x i32> %add
74 define <4 x i32> @cmp_sel_Cplus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {
75 ; SSE-LABEL: cmp_sel_Cplus1_or_C_vec:
76 ; SSE:       # %bb.0:
77 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
78 ; SSE-NEXT:    movdqa {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
79 ; SSE-NEXT:    psubd %xmm0, %xmm1
80 ; SSE-NEXT:    movdqa %xmm1, %xmm0
81 ; SSE-NEXT:    retq
83 ; AVX-LABEL: cmp_sel_Cplus1_or_C_vec:
84 ; AVX:       # %bb.0:
85 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
86 ; AVX-NEXT:    vmovdqa {{.*#+}} xmm1 = [42,0,4294967294,4294967295]
87 ; AVX-NEXT:    vpsubd %xmm0, %xmm1, %xmm0
88 ; AVX-NEXT:    retq
89   %cond = icmp eq <4 x i32> %x, %y
90   %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 42, i32 0, i32 -2, i32 -1>
91   ret <4 x i32> %add
94 define <4 x i32> @sel_Cminus1_or_C_vec(<4 x i1> %cond) {
95 ; SSE-LABEL: sel_Cminus1_or_C_vec:
96 ; SSE:       # %bb.0:
97 ; SSE-NEXT:    pslld $31, %xmm0
98 ; SSE-NEXT:    psrad $31, %xmm0
99 ; SSE-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
100 ; SSE-NEXT:    retq
102 ; AVX-LABEL: sel_Cminus1_or_C_vec:
103 ; AVX:       # %bb.0:
104 ; AVX-NEXT:    vpslld $31, %xmm0, %xmm0
105 ; AVX-NEXT:    vpsrad $31, %xmm0, %xmm0
106 ; AVX-NEXT:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
107 ; AVX-NEXT:    retq
108   %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>
109   ret <4 x i32> %add
112 define <4 x i32> @cmp_sel_Cminus1_or_C_vec(<4 x i32> %x, <4 x i32> %y) {
113 ; SSE-LABEL: cmp_sel_Cminus1_or_C_vec:
114 ; SSE:       # %bb.0:
115 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
116 ; SSE-NEXT:    paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
117 ; SSE-NEXT:    retq
119 ; AVX-LABEL: cmp_sel_Cminus1_or_C_vec:
120 ; AVX:       # %bb.0:
121 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
122 ; AVX-NEXT:    vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
123 ; AVX-NEXT:    retq
124   %cond = icmp eq <4 x i32> %x, %y
125   %add = select <4 x i1> %cond, <4 x i32> <i32 43, i32 1, i32 -1, i32 0>, <4 x i32> <i32 44, i32 2, i32 0, i32 1>
126   ret <4 x i32> %add
129 define <4 x i32> @sel_minus1_or_0_vec(<4 x i1> %cond) {
130 ; SSE-LABEL: sel_minus1_or_0_vec:
131 ; SSE:       # %bb.0:
132 ; SSE-NEXT:    pslld $31, %xmm0
133 ; SSE-NEXT:    psrad $31, %xmm0
134 ; SSE-NEXT:    retq
136 ; AVX-LABEL: sel_minus1_or_0_vec:
137 ; AVX:       # %bb.0:
138 ; AVX-NEXT:    vpslld $31, %xmm0, %xmm0
139 ; AVX-NEXT:    vpsrad $31, %xmm0, %xmm0
140 ; AVX-NEXT:    retq
141   %add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
142   ret <4 x i32> %add
145 define <4 x i32> @cmp_sel_minus1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {
146 ; SSE-LABEL: cmp_sel_minus1_or_0_vec:
147 ; SSE:       # %bb.0:
148 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
149 ; SSE-NEXT:    retq
151 ; AVX-LABEL: cmp_sel_minus1_or_0_vec:
152 ; AVX:       # %bb.0:
153 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
154 ; AVX-NEXT:    retq
155   %cond = icmp eq <4 x i32> %x, %y
156   %add = select <4 x i1> %cond, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
157   ret <4 x i32> %add
160 define <4 x i32> @sel_0_or_minus1_vec(<4 x i1> %cond) {
161 ; SSE-LABEL: sel_0_or_minus1_vec:
162 ; SSE:       # %bb.0:
163 ; SSE-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
164 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm1
165 ; SSE-NEXT:    paddd %xmm1, %xmm0
166 ; SSE-NEXT:    retq
168 ; AVX-LABEL: sel_0_or_minus1_vec:
169 ; AVX:       # %bb.0:
170 ; AVX-NEXT:    vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
171 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
172 ; AVX-NEXT:    vpaddd %xmm1, %xmm0, %xmm0
173 ; AVX-NEXT:    retq
174   %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
175   ret <4 x i32> %add
178 define <4 x i32> @cmp_sel_0_or_minus1_vec(<4 x i32> %x, <4 x i32> %y) {
179 ; SSE-LABEL: cmp_sel_0_or_minus1_vec:
180 ; SSE:       # %bb.0:
181 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
182 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm1
183 ; SSE-NEXT:    pxor %xmm1, %xmm0
184 ; SSE-NEXT:    retq
186 ; AVX-LABEL: cmp_sel_0_or_minus1_vec:
187 ; AVX:       # %bb.0:
188 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
189 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm1, %xmm1
190 ; AVX-NEXT:    vpxor %xmm1, %xmm0, %xmm0
191 ; AVX-NEXT:    retq
192   %cond = icmp eq <4 x i32> %x, %y
193   %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
194   ret <4 x i32> %add
197 define <4 x i32> @sel_1_or_0_vec(<4 x i1> %cond) {
198 ; SSE-LABEL: sel_1_or_0_vec:
199 ; SSE:       # %bb.0:
200 ; SSE-NEXT:    andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
201 ; SSE-NEXT:    retq
203 ; AVX-LABEL: sel_1_or_0_vec:
204 ; AVX:       # %bb.0:
205 ; AVX-NEXT:    vandps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
206 ; AVX-NEXT:    retq
207   %add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
208   ret <4 x i32> %add
211 define <4 x i32> @cmp_sel_1_or_0_vec(<4 x i32> %x, <4 x i32> %y) {
212 ; SSE-LABEL: cmp_sel_1_or_0_vec:
213 ; SSE:       # %bb.0:
214 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
215 ; SSE-NEXT:    psrld $31, %xmm0
216 ; SSE-NEXT:    retq
218 ; AVX-LABEL: cmp_sel_1_or_0_vec:
219 ; AVX:       # %bb.0:
220 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
221 ; AVX-NEXT:    vpsrld $31, %xmm0, %xmm0
222 ; AVX-NEXT:    retq
223   %cond = icmp eq <4 x i32> %x, %y
224   %add = select <4 x i1> %cond, <4 x i32> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 0, i32 0, i32 0, i32 0>
225   ret <4 x i32> %add
228 define <4 x i32> @sel_0_or_1_vec(<4 x i1> %cond) {
229 ; SSE-LABEL: sel_0_or_1_vec:
230 ; SSE:       # %bb.0:
231 ; SSE-NEXT:    andnps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
232 ; SSE-NEXT:    retq
234 ; AVX-LABEL: sel_0_or_1_vec:
235 ; AVX:       # %bb.0:
236 ; AVX-NEXT:    vandnps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
237 ; AVX-NEXT:    retq
238   %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
239   ret <4 x i32> %add
242 define <4 x i32> @cmp_sel_0_or_1_vec(<4 x i32> %x, <4 x i32> %y) {
243 ; SSE-LABEL: cmp_sel_0_or_1_vec:
244 ; SSE:       # %bb.0:
245 ; SSE-NEXT:    pcmpeqd %xmm1, %xmm0
246 ; SSE-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
247 ; SSE-NEXT:    retq
249 ; AVX-LABEL: cmp_sel_0_or_1_vec:
250 ; AVX:       # %bb.0:
251 ; AVX-NEXT:    vpcmpeqd %xmm1, %xmm0, %xmm0
252 ; AVX-NEXT:    vpandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0
253 ; AVX-NEXT:    retq
254   %cond = icmp eq <4 x i32> %x, %y
255   %add = select <4 x i1> %cond, <4 x i32> <i32 0, i32 0, i32 0, i32 0>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
256   ret <4 x i32> %add
259 ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21167
260 define <2 x i37> @ossfuzz21167(<2 x i37> %x, <2 x i37> %y) {
261 ; SSE-LABEL: ossfuzz21167:
262 ; SSE:       # %bb.0: # %BB
263 ; SSE-NEXT:    xorps %xmm0, %xmm0
264 ; SSE-NEXT:    retq
266 ; AVX-LABEL: ossfuzz21167:
267 ; AVX:       # %bb.0: # %BB
268 ; AVX-NEXT:    vxorps %xmm0, %xmm0, %xmm0
269 ; AVX-NEXT:    retq
271   %c0 = icmp sgt <2 x i37> %y, zeroinitializer
272   %xor_x = xor <2 x i37> undef, undef
273   %smax96 = select <2 x i1> %c0, <2 x i37> %xor_x, <2 x i37> zeroinitializer
274   ret <2 x i37> %smax96
277 ; PR53401
279 define i32 @wrong_min_signbits(<2 x i16> %x) {
280 ; SSE-LABEL: wrong_min_signbits:
281 ; SSE:       # %bb.0:
282 ; SSE-NEXT:    pxor %xmm1, %xmm1
283 ; SSE-NEXT:    pcmpeqw %xmm0, %xmm1
284 ; SSE-NEXT:    movdqa {{.*#+}} xmm0 = [1,0,0,0]
285 ; SSE-NEXT:    pand %xmm1, %xmm0
286 ; SSE-NEXT:    pandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
287 ; SSE-NEXT:    por %xmm0, %xmm1
288 ; SSE-NEXT:    movd %xmm1, %eax
289 ; SSE-NEXT:    retq
291 ; AVX-LABEL: wrong_min_signbits:
292 ; AVX:       # %bb.0:
293 ; AVX-NEXT:    vpxor %xmm1, %xmm1, %xmm1
294 ; AVX-NEXT:    vpcmpeqw %xmm1, %xmm0, %xmm0
295 ; AVX-NEXT:    vmovdqa {{.*#+}} xmm1 = [2,0,0,0]
296 ; AVX-NEXT:    vpblendvb %xmm0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0
297 ; AVX-NEXT:    vmovd %xmm0, %eax
298 ; AVX-NEXT:    retq
299   %true_true = icmp ne <2 x i16> %x, zeroinitializer
300   %true_false = and <2 x i1> %true_true, <i1 true, i1 false>
301   %sel = select <2 x i1> %true_false, <2 x i16> <i16 2, i16 0>, <2 x i16> <i16 1, i16 0>
302   %t1 = bitcast <2 x i16> %sel to i32
303   ret i32 %t1