xref: /llvm-project/llvm/test/CodeGen/X86/fcmp-logic.ll (revision 2f448bf509432c1a19ec46ab8cbc7353c03c6280)
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
5
6define i1 @olt_ole_and_f32(float %w, float %x, float %y, float %z) {
7; SSE2-LABEL: olt_ole_and_f32:
8; SSE2:       # %bb.0:
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
14; SSE2-NEXT:    retq
15;
16; AVX1-LABEL: olt_ole_and_f32:
17; AVX1:       # %bb.0:
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
23; AVX1-NEXT:    retq
24;
25; AVX512-LABEL: olt_ole_and_f32:
26; AVX512:       # %bb.0:
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
36; AVX512-NEXT:    retq
37  %f1 = fcmp olt float %w, %x
38  %f2 = fcmp ole float %y, %z
39  %r = and i1 %f1, %f2
40  ret i1 %r
41}
42
43define i1 @oge_oeq_or_f32(float %w, float %x, float %y, float %z) {
44; SSE2-LABEL: oge_oeq_or_f32:
45; SSE2:       # %bb.0:
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
51; SSE2-NEXT:    retq
52;
53; AVX1-LABEL: oge_oeq_or_f32:
54; AVX1:       # %bb.0:
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
60; AVX1-NEXT:    retq
61;
62; AVX512-LABEL: oge_oeq_or_f32:
63; AVX512:       # %bb.0:
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
74; AVX512-NEXT:    retq
75  %f1 = fcmp oge float %w, %x
76  %f2 = fcmp oeq float %y, %z
77  %r = or i1 %f1, %f2
78  ret i1 %r
79}
80
81define i1 @ord_one_xor_f32(float %w, float %x, float %y, float %z) {
82; SSE2-LABEL: ord_one_xor_f32:
83; SSE2:       # %bb.0:
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
89; SSE2-NEXT:    retq
90;
91; AVX1-LABEL: ord_one_xor_f32:
92; AVX1:       # %bb.0:
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
98; AVX1-NEXT:    retq
99;
100; AVX512-LABEL: ord_one_xor_f32:
101; AVX512:       # %bb.0:
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
112; AVX512-NEXT:    retq
113  %f1 = fcmp ord float %w, %x
114  %f2 = fcmp one float %y, %z
115  %r = xor i1 %f1, %f2
116  ret i1 %r
117}
118
119; PR51068
120define i1 @une_oeq_xor_f32(float %w, float %x, float %y, float %z) {
121; SSE2-LABEL: une_oeq_xor_f32:
122; SSE2:       # %bb.0:
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
128; SSE2-NEXT:    retq
129;
130; AVX1-LABEL: une_oeq_xor_f32:
131; AVX1:       # %bb.0:
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
137; AVX1-NEXT:    retq
138;
139; AVX512-LABEL: une_oeq_xor_f32:
140; AVX512:       # %bb.0:
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
151; AVX512-NEXT:    retq
152  %f1 = fcmp une float %w, %x
153  %f2 = fcmp oeq float %y, %z
154  %r = xor i1 %f1, %f2
155  ret i1 %r
156}
157
158define i1 @une_ugt_and_f64(double %w, double %x, double %y, double %z) {
159; SSE2-LABEL: une_ugt_and_f64:
160; SSE2:       # %bb.0:
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
166; SSE2-NEXT:    retq
167;
168; AVX1-LABEL: une_ugt_and_f64:
169; AVX1:       # %bb.0:
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
175; AVX1-NEXT:    retq
176;
177; AVX512-LABEL: une_ugt_and_f64:
178; AVX512:       # %bb.0:
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
188; AVX512-NEXT:    retq
189  %f1 = fcmp une double %w, %x
190  %f2 = fcmp ugt double %y, %z
191  %r = and i1 %f1, %f2
192  ret i1 %r
193}
194
195define i1 @ult_uge_or_f64(double %w, double %x, double %y, double %z) {
196; SSE2-LABEL: ult_uge_or_f64:
197; SSE2:       # %bb.0:
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
203; SSE2-NEXT:    retq
204;
205; AVX1-LABEL: ult_uge_or_f64:
206; AVX1:       # %bb.0:
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
212; AVX1-NEXT:    retq
213;
214; AVX512-LABEL: ult_uge_or_f64:
215; AVX512:       # %bb.0:
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
226; AVX512-NEXT:    retq
227  %f1 = fcmp ult double %w, %x
228  %f2 = fcmp uge double %y, %z
229  %r = or i1 %f1, %f2
230  ret i1 %r
231}
232
233define i1 @une_uno_xor_f64(double %w, double %x, double %y, double %z) {
234; SSE2-LABEL: une_uno_xor_f64:
235; SSE2:       # %bb.0:
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
241; SSE2-NEXT:    retq
242;
243; AVX1-LABEL: une_uno_xor_f64:
244; AVX1:       # %bb.0:
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
250; AVX1-NEXT:    retq
251;
252; AVX512-LABEL: une_uno_xor_f64:
253; AVX512:       # %bb.0:
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
264; AVX512-NEXT:    retq
265  %f1 = fcmp une double %w, %x
266  %f2 = fcmp uno double %y, %z
267  %r = xor i1 %f1, %f2
268  ret i1 %r
269}
270
271; This uses ucomis because the types do not match.
272; TODO: Merge down to narrow type?
273
274define i1 @olt_olt_and_f32_f64(float %w, float %x, double %y, double %z) {
275; SSE2-LABEL: olt_olt_and_f32_f64:
276; SSE2:       # %bb.0:
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
282; SSE2-NEXT:    retq
283;
284; AVX-LABEL: olt_olt_and_f32_f64:
285; AVX:       # %bb.0:
286; AVX-NEXT:    vucomiss %xmm0, %xmm1
287; AVX-NEXT:    seta %cl
288; AVX-NEXT:    vucomisd %xmm2, %xmm3
289; AVX-NEXT:    seta %al
290; AVX-NEXT:    andb %cl, %al
291; AVX-NEXT:    retq
292  %f1 = fcmp olt float %w, %x
293  %f2 = fcmp olt double %y, %z
294  %r = and i1 %f1, %f2
295  ret i1 %r
296}
297
298; This uses ucomis because of extra uses.
299
300define i1 @une_uno_xor_f64_use1(double %w, double %x, double %y, double %z, ptr %p) {
301; SSE2-LABEL: une_uno_xor_f64_use1:
302; SSE2:       # %bb.0:
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
311; SSE2-NEXT:    retq
312;
313; AVX-LABEL: une_uno_xor_f64_use1:
314; AVX:       # %bb.0:
315; AVX-NEXT:    vucomisd %xmm1, %xmm0
316; AVX-NEXT:    setp %al
317; AVX-NEXT:    setne %cl
318; AVX-NEXT:    orb %al, %cl
319; AVX-NEXT:    movb %cl, (%rdi)
320; AVX-NEXT:    vucomisd %xmm3, %xmm2
321; AVX-NEXT:    setp %al
322; AVX-NEXT:    xorb %cl, %al
323; AVX-NEXT:    retq
324  %f1 = fcmp une double %w, %x
325  store i1 %f1, ptr %p
326  %f2 = fcmp uno double %y, %z
327  %r = xor i1 %f1, %f2
328  ret i1 %r
329}
330
331; This uses ucomis because of extra uses.
332
333define i1 @une_uno_xor_f64_use2(double %w, double %x, double %y, double %z, ptr %p) {
334; SSE2-LABEL: une_uno_xor_f64_use2:
335; SSE2:       # %bb.0:
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
344; SSE2-NEXT:    retq
345;
346; AVX-LABEL: une_uno_xor_f64_use2:
347; AVX:       # %bb.0:
348; AVX-NEXT:    vucomisd %xmm1, %xmm0
349; AVX-NEXT:    setp %al
350; AVX-NEXT:    setne %cl
351; AVX-NEXT:    orb %al, %cl
352; AVX-NEXT:    vucomisd %xmm3, %xmm2
353; AVX-NEXT:    setp %al
354; AVX-NEXT:    setp (%rdi)
355; AVX-NEXT:    xorb %cl, %al
356; AVX-NEXT:    retq
357  %f1 = fcmp une double %w, %x
358  %f2 = fcmp uno double %y, %z
359  store i1 %f2, ptr %p
360  %r = xor i1 %f1, %f2
361  ret i1 %r
362}
363
364
365; bool f32cmp3(float x, float y, float z, float w) {
366;     return ((x > 0) || (y > 0)) != (z < w);
367; }
368
369define i1 @f32cmp3(float %x, float %y, float %z, float %w) {
370; SSE2-LABEL: f32cmp3:
371; SSE2:       # %bb.0:
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
381; SSE2-NEXT:    retq
382;
383; AVX1-LABEL: f32cmp3:
384; AVX1:       # %bb.0:
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
393; AVX1-NEXT:    retq
394;
395; AVX512-LABEL: f32cmp3:
396; AVX512:       # %bb.0:
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
408; AVX512-NEXT:    retq
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
414  ret i1 %r
415}
416