1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-- -mattr=sse2 | FileCheck %s --check-prefixes=SSE2
3 ; RUN: llc < %s -mtriple=x86_64-- -mattr=avx | FileCheck %s --check-prefixes=AVX,AVX1
4 ; RUN: llc < %s -mtriple=x86_64-- -mattr=avx512f | FileCheck %s --check-prefixes=AVX,AVX512
6 define i1 @olt_ole_and_f32(float %w, float %x, float %y, float %z) {
7 ; SSE2-LABEL: olt_ole_and_f32:
9 ; SSE2-NEXT: cmpleps %xmm3, %xmm2
10 ; SSE2-NEXT: cmpltps %xmm1, %xmm0
11 ; SSE2-NEXT: andps %xmm2, %xmm0
12 ; SSE2-NEXT: movd %xmm0, %eax
13 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
16 ; AVX1-LABEL: olt_ole_and_f32:
18 ; AVX1-NEXT: vcmpleps %xmm3, %xmm2, %xmm2
19 ; AVX1-NEXT: vcmpltps %xmm1, %xmm0, %xmm0
20 ; AVX1-NEXT: vandps %xmm2, %xmm0, %xmm0
21 ; AVX1-NEXT: vmovd %xmm0, %eax
22 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
25 ; AVX512-LABEL: olt_ole_and_f32:
27 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
28 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
29 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
30 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
31 ; AVX512-NEXT: vcmpltps %zmm1, %zmm0, %k1
32 ; AVX512-NEXT: vcmpleps %zmm3, %zmm2, %k0 {%k1}
33 ; AVX512-NEXT: kmovw %k0, %eax
34 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
35 ; AVX512-NEXT: vzeroupper
37 %f1 = fcmp olt float %w, %x
38 %f2 = fcmp ole float %y, %z
43 define i1 @oge_oeq_or_f32(float %w, float %x, float %y, float %z) {
44 ; SSE2-LABEL: oge_oeq_or_f32:
46 ; SSE2-NEXT: cmpeqps %xmm3, %xmm2
47 ; SSE2-NEXT: cmpleps %xmm0, %xmm1
48 ; SSE2-NEXT: orps %xmm2, %xmm1
49 ; SSE2-NEXT: movd %xmm1, %eax
50 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
53 ; AVX1-LABEL: oge_oeq_or_f32:
55 ; AVX1-NEXT: vcmpeqps %xmm3, %xmm2, %xmm2
56 ; AVX1-NEXT: vcmpleps %xmm0, %xmm1, %xmm0
57 ; AVX1-NEXT: vorps %xmm2, %xmm0, %xmm0
58 ; AVX1-NEXT: vmovd %xmm0, %eax
59 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
62 ; AVX512-LABEL: oge_oeq_or_f32:
64 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
65 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
66 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
67 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
68 ; AVX512-NEXT: vcmpeqps %zmm3, %zmm2, %k0
69 ; AVX512-NEXT: vcmpleps %zmm0, %zmm1, %k1
70 ; AVX512-NEXT: korw %k0, %k1, %k0
71 ; AVX512-NEXT: kmovw %k0, %eax
72 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
73 ; AVX512-NEXT: vzeroupper
75 %f1 = fcmp oge float %w, %x
76 %f2 = fcmp oeq float %y, %z
81 define i1 @ord_one_xor_f32(float %w, float %x, float %y, float %z) {
82 ; SSE2-LABEL: ord_one_xor_f32:
84 ; SSE2-NEXT: ucomiss %xmm1, %xmm0
85 ; SSE2-NEXT: setnp %cl
86 ; SSE2-NEXT: ucomiss %xmm3, %xmm2
87 ; SSE2-NEXT: setne %al
88 ; SSE2-NEXT: xorb %cl, %al
91 ; AVX1-LABEL: ord_one_xor_f32:
93 ; AVX1-NEXT: vcmpneq_oqps %xmm3, %xmm2, %xmm2
94 ; AVX1-NEXT: vcmpordps %xmm1, %xmm0, %xmm0
95 ; AVX1-NEXT: vxorps %xmm2, %xmm0, %xmm0
96 ; AVX1-NEXT: vmovd %xmm0, %eax
97 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
100 ; AVX512-LABEL: ord_one_xor_f32:
102 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
103 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
104 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
105 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
106 ; AVX512-NEXT: vcmpneq_oqps %zmm3, %zmm2, %k0
107 ; AVX512-NEXT: vcmpordps %zmm1, %zmm0, %k1
108 ; AVX512-NEXT: kxorw %k0, %k1, %k0
109 ; AVX512-NEXT: kmovw %k0, %eax
110 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
111 ; AVX512-NEXT: vzeroupper
113 %f1 = fcmp ord float %w, %x
114 %f2 = fcmp one float %y, %z
120 define i1 @une_oeq_xor_f32(float %w, float %x, float %y, float %z) {
121 ; SSE2-LABEL: une_oeq_xor_f32:
123 ; SSE2-NEXT: cmpeqps %xmm3, %xmm2
124 ; SSE2-NEXT: cmpneqps %xmm1, %xmm0
125 ; SSE2-NEXT: xorps %xmm2, %xmm0
126 ; SSE2-NEXT: movd %xmm0, %eax
127 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
130 ; AVX1-LABEL: une_oeq_xor_f32:
132 ; AVX1-NEXT: vcmpeqps %xmm3, %xmm2, %xmm2
133 ; AVX1-NEXT: vcmpneqps %xmm1, %xmm0, %xmm0
134 ; AVX1-NEXT: vxorps %xmm2, %xmm0, %xmm0
135 ; AVX1-NEXT: vmovd %xmm0, %eax
136 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
139 ; AVX512-LABEL: une_oeq_xor_f32:
141 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
142 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
143 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
144 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
145 ; AVX512-NEXT: vcmpeqps %zmm3, %zmm2, %k0
146 ; AVX512-NEXT: vcmpneqps %zmm1, %zmm0, %k1
147 ; AVX512-NEXT: kxorw %k0, %k1, %k0
148 ; AVX512-NEXT: kmovw %k0, %eax
149 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
150 ; AVX512-NEXT: vzeroupper
152 %f1 = fcmp une float %w, %x
153 %f2 = fcmp oeq float %y, %z
158 define i1 @une_ugt_and_f64(double %w, double %x, double %y, double %z) {
159 ; SSE2-LABEL: une_ugt_and_f64:
161 ; SSE2-NEXT: cmpnlepd %xmm3, %xmm2
162 ; SSE2-NEXT: cmpneqpd %xmm1, %xmm0
163 ; SSE2-NEXT: andpd %xmm2, %xmm0
164 ; SSE2-NEXT: movd %xmm0, %eax
165 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
168 ; AVX1-LABEL: une_ugt_and_f64:
170 ; AVX1-NEXT: vcmpnlepd %xmm3, %xmm2, %xmm2
171 ; AVX1-NEXT: vcmpneqpd %xmm1, %xmm0, %xmm0
172 ; AVX1-NEXT: vandpd %xmm2, %xmm0, %xmm0
173 ; AVX1-NEXT: vmovd %xmm0, %eax
174 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
177 ; AVX512-LABEL: une_ugt_and_f64:
179 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
180 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
181 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
182 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
183 ; AVX512-NEXT: vcmpneqpd %zmm1, %zmm0, %k1
184 ; AVX512-NEXT: vcmpnlepd %zmm3, %zmm2, %k0 {%k1}
185 ; AVX512-NEXT: kmovw %k0, %eax
186 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
187 ; AVX512-NEXT: vzeroupper
189 %f1 = fcmp une double %w, %x
190 %f2 = fcmp ugt double %y, %z
195 define i1 @ult_uge_or_f64(double %w, double %x, double %y, double %z) {
196 ; SSE2-LABEL: ult_uge_or_f64:
198 ; SSE2-NEXT: cmpnltpd %xmm3, %xmm2
199 ; SSE2-NEXT: cmpnlepd %xmm0, %xmm1
200 ; SSE2-NEXT: orpd %xmm2, %xmm1
201 ; SSE2-NEXT: movd %xmm1, %eax
202 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
205 ; AVX1-LABEL: ult_uge_or_f64:
207 ; AVX1-NEXT: vcmpnltpd %xmm3, %xmm2, %xmm2
208 ; AVX1-NEXT: vcmpnlepd %xmm0, %xmm1, %xmm0
209 ; AVX1-NEXT: vorpd %xmm2, %xmm0, %xmm0
210 ; AVX1-NEXT: vmovd %xmm0, %eax
211 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
214 ; AVX512-LABEL: ult_uge_or_f64:
216 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
217 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
218 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
219 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
220 ; AVX512-NEXT: vcmpnltpd %zmm3, %zmm2, %k0
221 ; AVX512-NEXT: vcmpnlepd %zmm0, %zmm1, %k1
222 ; AVX512-NEXT: korw %k0, %k1, %k0
223 ; AVX512-NEXT: kmovw %k0, %eax
224 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
225 ; AVX512-NEXT: vzeroupper
227 %f1 = fcmp ult double %w, %x
228 %f2 = fcmp uge double %y, %z
233 define i1 @une_uno_xor_f64(double %w, double %x, double %y, double %z) {
234 ; SSE2-LABEL: une_uno_xor_f64:
236 ; SSE2-NEXT: cmpunordpd %xmm3, %xmm2
237 ; SSE2-NEXT: cmpneqpd %xmm1, %xmm0
238 ; SSE2-NEXT: xorpd %xmm2, %xmm0
239 ; SSE2-NEXT: movd %xmm0, %eax
240 ; SSE2-NEXT: # kill: def $al killed $al killed $eax
243 ; AVX1-LABEL: une_uno_xor_f64:
245 ; AVX1-NEXT: vcmpunordpd %xmm3, %xmm2, %xmm2
246 ; AVX1-NEXT: vcmpneqpd %xmm1, %xmm0, %xmm0
247 ; AVX1-NEXT: vxorpd %xmm2, %xmm0, %xmm0
248 ; AVX1-NEXT: vmovd %xmm0, %eax
249 ; AVX1-NEXT: # kill: def $al killed $al killed $eax
252 ; AVX512-LABEL: une_uno_xor_f64:
254 ; AVX512-NEXT: # kill: def $xmm3 killed $xmm3 def $zmm3
255 ; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $zmm2
256 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
257 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
258 ; AVX512-NEXT: vcmpunordpd %zmm3, %zmm2, %k0
259 ; AVX512-NEXT: vcmpneqpd %zmm1, %zmm0, %k1
260 ; AVX512-NEXT: kxorw %k0, %k1, %k0
261 ; AVX512-NEXT: kmovw %k0, %eax
262 ; AVX512-NEXT: # kill: def $al killed $al killed $eax
263 ; AVX512-NEXT: vzeroupper
265 %f1 = fcmp une double %w, %x
266 %f2 = fcmp uno double %y, %z
271 ; This uses ucomis because the types do not match.
272 ; TODO: Merge down to narrow type?
274 define i1 @olt_olt_and_f32_f64(float %w, float %x, double %y, double %z) {
275 ; SSE2-LABEL: olt_olt_and_f32_f64:
277 ; SSE2-NEXT: ucomiss %xmm0, %xmm1
278 ; SSE2-NEXT: seta %cl
279 ; SSE2-NEXT: ucomisd %xmm2, %xmm3
280 ; SSE2-NEXT: seta %al
281 ; SSE2-NEXT: andb %cl, %al
284 ; AVX-LABEL: olt_olt_and_f32_f64:
286 ; AVX-NEXT: vucomiss %xmm0, %xmm1
288 ; AVX-NEXT: vucomisd %xmm2, %xmm3
290 ; AVX-NEXT: andb %cl, %al
292 %f1 = fcmp olt float %w, %x
293 %f2 = fcmp olt double %y, %z
298 ; This uses ucomis because of extra uses.
300 define i1 @une_uno_xor_f64_use1(double %w, double %x, double %y, double %z, ptr %p) {
301 ; SSE2-LABEL: une_uno_xor_f64_use1:
303 ; SSE2-NEXT: ucomisd %xmm1, %xmm0
304 ; SSE2-NEXT: setp %al
305 ; SSE2-NEXT: setne %cl
306 ; SSE2-NEXT: orb %al, %cl
307 ; SSE2-NEXT: movb %cl, (%rdi)
308 ; SSE2-NEXT: ucomisd %xmm3, %xmm2
309 ; SSE2-NEXT: setp %al
310 ; SSE2-NEXT: xorb %cl, %al
313 ; AVX-LABEL: une_uno_xor_f64_use1:
315 ; AVX-NEXT: vucomisd %xmm1, %xmm0
317 ; AVX-NEXT: setne %cl
318 ; AVX-NEXT: orb %al, %cl
319 ; AVX-NEXT: movb %cl, (%rdi)
320 ; AVX-NEXT: vucomisd %xmm3, %xmm2
322 ; AVX-NEXT: xorb %cl, %al
324 %f1 = fcmp une double %w, %x
326 %f2 = fcmp uno double %y, %z
331 ; This uses ucomis because of extra uses.
333 define i1 @une_uno_xor_f64_use2(double %w, double %x, double %y, double %z, ptr %p) {
334 ; SSE2-LABEL: une_uno_xor_f64_use2:
336 ; SSE2-NEXT: ucomisd %xmm1, %xmm0
337 ; SSE2-NEXT: setp %al
338 ; SSE2-NEXT: setne %cl
339 ; SSE2-NEXT: orb %al, %cl
340 ; SSE2-NEXT: ucomisd %xmm3, %xmm2
341 ; SSE2-NEXT: setp %al
342 ; SSE2-NEXT: setp (%rdi)
343 ; SSE2-NEXT: xorb %cl, %al
346 ; AVX-LABEL: une_uno_xor_f64_use2:
348 ; AVX-NEXT: vucomisd %xmm1, %xmm0
350 ; AVX-NEXT: setne %cl
351 ; AVX-NEXT: orb %al, %cl
352 ; AVX-NEXT: vucomisd %xmm3, %xmm2
354 ; AVX-NEXT: setp (%rdi)
355 ; AVX-NEXT: xorb %cl, %al
357 %f1 = fcmp une double %w, %x
358 %f2 = fcmp uno double %y, %z
365 ; bool f32cmp3(float x, float y, float z, float w) {
366 ; return ((x > 0) || (y > 0)) != (z < w);
369 define i1 @f32cmp3(float %x, float %y, float %z, float %w) {
370 ; SSE2-LABEL: f32cmp3:
372 ; SSE2-NEXT: xorps %xmm4, %xmm4
373 ; SSE2-NEXT: xorps %xmm5, %xmm5
374 ; SSE2-NEXT: cmpltps %xmm1, %xmm5
375 ; SSE2-NEXT: cmpltps %xmm0, %xmm4
376 ; SSE2-NEXT: orps %xmm5, %xmm4
377 ; SSE2-NEXT: movd %xmm4, %ecx
378 ; SSE2-NEXT: ucomiss %xmm2, %xmm3
379 ; SSE2-NEXT: seta %al
380 ; SSE2-NEXT: xorb %cl, %al
383 ; AVX1-LABEL: f32cmp3:
385 ; AVX1-NEXT: vxorps %xmm4, %xmm4, %xmm4
386 ; AVX1-NEXT: vcmpltps %xmm1, %xmm4, %xmm1
387 ; AVX1-NEXT: vcmpltps %xmm0, %xmm4, %xmm0
388 ; AVX1-NEXT: vorps %xmm1, %xmm0, %xmm0
389 ; AVX1-NEXT: vmovd %xmm0, %ecx
390 ; AVX1-NEXT: vucomiss %xmm2, %xmm3
391 ; AVX1-NEXT: seta %al
392 ; AVX1-NEXT: xorb %cl, %al
395 ; AVX512-LABEL: f32cmp3:
397 ; AVX512-NEXT: # kill: def $xmm1 killed $xmm1 def $zmm1
398 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $zmm0
399 ; AVX512-NEXT: vxorps %xmm4, %xmm4, %xmm4
400 ; AVX512-NEXT: vcmpltps %zmm1, %zmm4, %k0
401 ; AVX512-NEXT: vcmpltps %zmm0, %zmm4, %k1
402 ; AVX512-NEXT: korw %k0, %k1, %k0
403 ; AVX512-NEXT: kmovw %k0, %ecx
404 ; AVX512-NEXT: vucomiss %xmm2, %xmm3
405 ; AVX512-NEXT: seta %al
406 ; AVX512-NEXT: xorb %cl, %al
407 ; AVX512-NEXT: vzeroupper
409 %cmpx = fcmp ogt float %x, 0.0
410 %cmpy = fcmp ogt float %y, 0.0
411 %or = select i1 %cmpx, i1 true, i1 %cmpy
412 %cmpzw = fcmp olt float %z, %w
413 %r = xor i1 %or, %cmpzw