Index: llvm/lib/CodeGen/CodeGenCommonISel.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenCommonISel.cpp +++ llvm/lib/CodeGen/CodeGenCommonISel.cpp @@ -202,6 +202,8 @@ case fcSubnormal | fcZero | fcNan: return InvertedTest; case fcInf | fcNan: + case fcPosInf | fcNan: + case fcNegInf | fcNan: // If we're trying to use fcmp, we can take advantage of the nan check // behavior of the compare (but this is more instructions in the integer // expansion). Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -8072,11 +8072,20 @@ IsInvertedFP = true; } + // See if we can fold an | fcNan into an unordered compare. + FPClassTest OrderedFPTestMask = + static_cast(FPTestMask & ~fcNan); + if ((FPTestMask & fcNan) != fcNan) + OrderedFPTestMask = FPTestMask; + + const bool IsOrdered = FPTestMask == OrderedFPTestMask; + const ISD::CondCode OrderedCmpOpcode = + IsInvertedFP ? ISD::SETONE : ISD::SETOEQ; + const ISD::CondCode UnorderedCmpOpcode = + IsInvertedFP ? ISD::SETUNE : ISD::SETUEQ; + if (std::optional IsCmp0 = isFCmpEqualZero(FPTestMask, Semantics, DAG.getMachineFunction())) { - ISD::CondCode OrderedCmpOpcode = IsInvertedFP ? ISD::SETONE : ISD::SETOEQ; - ISD::CondCode UnorderedCmpOpcode = - IsInvertedFP ? ISD::SETUNE : ISD::SETUEQ; // If denormals could be implicitly treated as 0, this is not equivalent // to a compare with 0 since it will also be true for denormals. @@ -8089,7 +8098,7 @@ return DAG.getSetCC(DL, ResultVT, Op, Op, IsInvertedFP ? ISD::SETO : ISD::SETUO); - if (FPTestMask == fcInf || FPTestMask == (fcInf | fcNan)) { + if (OrderedFPTestMask == fcInf) { bool IsOrdered = FPTestMask == fcInf; ISD::CondCode OrderedCmpOpcode = IsInvertedFP ? ISD::SETONE : ISD::SETOEQ; ISD::CondCode UnorderedCmpOpcode = @@ -8103,14 +8112,16 @@ IsOrdered ? OrderedCmpOpcode : UnorderedCmpOpcode); } - if (TestMask == fcPosInf || TestMask == fcNegInf) { + if (OrderedFPTestMask == fcPosInf || OrderedFPTestMask == fcNegInf) { // isposinf(x) --> x == inf // isneginf(x) --> x == -inf - // TODO: Handle unordered tests with fcNan + // isposinf(x) || nan --> x u== inf + // isneginf(x) || nan --> x u== -inf + SDValue Inf = DAG.getConstantFP( APFloat::getInf(Semantics, TestMask == fcNegInf), DL, OperandVT); return DAG.getSetCC(DL, ResultVT, Op, Inf, - IsInvertedFP ? ISD::SETONE : ISD::SETOEQ); + IsOrdered ? OrderedCmpOpcode : UnorderedCmpOpcode); } } Index: llvm/test/CodeGen/X86/is_fpclass.ll =================================================================== --- llvm/test/CodeGen/X86/is_fpclass.ll +++ llvm/test/CodeGen/X86/is_fpclass.ll @@ -239,14 +239,18 @@ define i1 @not_is_minus_inf_f(float %x) { ; CHECK-32-LABEL: not_is_minus_inf_f: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: cmpl $-8388608, {{[0-9]+}}(%esp) # imm = 0xFF800000 +; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-32-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} +; CHECK-32-NEXT: fucompp +; CHECK-32-NEXT: fnstsw %ax +; CHECK-32-NEXT: # kill: def $ah killed $ah killed $ax +; CHECK-32-NEXT: sahf ; CHECK-32-NEXT: setne %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: not_is_minus_inf_f: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $-8388608, %eax # imm = 0xFF800000 +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; CHECK-64-NEXT: setne %al ; CHECK-64-NEXT: retq entry: @@ -2056,24 +2060,19 @@ define i1 @is_plus_inf_or_nan_f(float %x) { ; CHECK-32-LABEL: is_plus_inf_or_nan_f: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-32-NEXT: sete %cl -; CHECK-32-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-32-NEXT: cmpl $2139095041, %eax # imm = 0x7F800001 -; CHECK-32-NEXT: setge %al -; CHECK-32-NEXT: orb %cl, %al +; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-32-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} +; CHECK-32-NEXT: fucompp +; CHECK-32-NEXT: fnstsw %ax +; CHECK-32-NEXT: # kill: def $ah killed $ah killed $ax +; CHECK-32-NEXT: sahf +; CHECK-32-NEXT: sete %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_plus_inf_or_nan_f: ; CHECK-64: # %bb.0: -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-64-NEXT: sete %cl -; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-64-NEXT: cmpl $2139095041, %eax # imm = 0x7F800001 -; CHECK-64-NEXT: setge %al -; CHECK-64-NEXT: orb %cl, %al +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-64-NEXT: sete %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 515) ; 0x200|0x3 = "+inf|nan" ret i1 %class @@ -2082,24 +2081,19 @@ define i1 @is_minus_inf_or_nan_f(float %x) { ; CHECK-32-LABEL: is_minus_inf_or_nan_f: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: cmpl $-8388608, %eax # imm = 0xFF800000 -; CHECK-32-NEXT: sete %cl -; CHECK-32-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-32-NEXT: cmpl $2139095041, %eax # imm = 0x7F800001 -; CHECK-32-NEXT: setge %al -; CHECK-32-NEXT: orb %cl, %al +; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-32-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} +; CHECK-32-NEXT: fucompp +; CHECK-32-NEXT: fnstsw %ax +; CHECK-32-NEXT: # kill: def $ah killed $ah killed $ax +; CHECK-32-NEXT: sahf +; CHECK-32-NEXT: sete %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_minus_inf_or_nan_f: ; CHECK-64: # %bb.0: -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $-8388608, %eax # imm = 0xFF800000 -; CHECK-64-NEXT: sete %cl -; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-64-NEXT: cmpl $2139095041, %eax # imm = 0x7F800001 -; CHECK-64-NEXT: setge %al -; CHECK-64-NEXT: orb %cl, %al +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-64-NEXT: sete %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 7) ; "-inf|nan" ret i1 %class @@ -2108,24 +2102,20 @@ define i1 @not_is_plus_inf_or_nan_f(float %x) { ; CHECK-32-LABEL: not_is_plus_inf_or_nan_f: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: cmpl $-8388608, %eax # imm = 0xFF800000 -; CHECK-32-NEXT: sete %cl -; CHECK-32-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-32-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-32-NEXT: setl %al -; CHECK-32-NEXT: orb %cl, %al +; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-32-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} +; CHECK-32-NEXT: fxch %st(1) +; CHECK-32-NEXT: fucompp +; CHECK-32-NEXT: fnstsw %ax +; CHECK-32-NEXT: # kill: def $ah killed $ah killed $ax +; CHECK-32-NEXT: sahf +; CHECK-32-NEXT: setb %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: not_is_plus_inf_or_nan_f: ; CHECK-64: # %bb.0: -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $-8388608, %eax # imm = 0xFF800000 -; CHECK-64-NEXT: sete %cl -; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-64-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-64-NEXT: setl %al -; CHECK-64-NEXT: orb %cl, %al +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-64-NEXT: setb %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 508) ; ~(0x200|0x3) = "~(+inf|nan)" ret i1 %class @@ -2134,24 +2124,20 @@ define i1 @not_is_minus_inf_or_nan_f(float %x) { ; CHECK-32-LABEL: not_is_minus_inf_or_nan_f: ; CHECK-32: # %bb.0: -; CHECK-32-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-32-NEXT: sete %cl -; CHECK-32-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-32-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-32-NEXT: setl %al -; CHECK-32-NEXT: orb %cl, %al +; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) +; CHECK-32-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}} +; CHECK-32-NEXT: fxch %st(1) +; CHECK-32-NEXT: fucompp +; CHECK-32-NEXT: fnstsw %ax +; CHECK-32-NEXT: # kill: def $ah killed $ah killed $ax +; CHECK-32-NEXT: sahf +; CHECK-32-NEXT: setb %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: not_is_minus_inf_or_nan_f: ; CHECK-64: # %bb.0: -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-64-NEXT: sete %cl -; CHECK-64-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF -; CHECK-64-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-64-NEXT: setl %al -; CHECK-64-NEXT: orb %cl, %al +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-64-NEXT: setb %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1016) ; "~(-inf|nan)" ret i1 %class