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