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 @@ -8118,6 +8118,16 @@ ISD::CondCode OrderedCmpOpcode = IsInvertedFP ? ISD::SETUNE : ISD::SETOEQ; ISD::CondCode UnorderedCmpOpcode = IsInvertedFP ? ISD::SETONE : ISD::SETUEQ; + // See if we can fold an | fcNan into an unordered compare. + FPClassTest OrderedFPTestMask = FPTestMask & ~fcNan; + + // Can't fold the ordered check if we're only testing for snan or qnan + // individually. + if ((FPTestMask & fcNan) != fcNan) + OrderedFPTestMask = FPTestMask; + + const bool IsOrdered = FPTestMask == OrderedFPTestMask; + if (std::optional IsCmp0 = isFCmpEqualZero(FPTestMask, Semantics, DAG.getMachineFunction()); IsCmp0 && (isCondCodeLegalOrCustom( @@ -8137,18 +8147,29 @@ return DAG.getSetCC(DL, ResultVT, Op, Op, IsInvertedFP ? ISD::SETO : ISD::SETUO); - bool IsOrderedInf = FPTestMask == fcInf; - if ((FPTestMask == fcInf || FPTestMask == (fcInf | fcNan)) && - isCondCodeLegalOrCustom(IsOrderedInf ? OrderedCmpOpcode - : UnorderedCmpOpcode, - OperandVT.getScalarType().getSimpleVT()) && - isOperationLegalOrCustom(ISD::FABS, OperandVT.getScalarType())) { + if (OrderedFPTestMask == fcInf && + isCondCodeLegalOrCustom(IsOrdered ? OrderedCmpOpcode + : UnorderedCmpOpcode, + OperandVT.getScalarType().getSimpleVT())) { // isinf(x) --> fabs(x) == inf SDValue Abs = DAG.getNode(ISD::FABS, DL, OperandVT, Op); SDValue Inf = DAG.getConstantFP(APFloat::getInf(Semantics), DL, OperandVT); return DAG.getSetCC(DL, ResultVT, Abs, Inf, - IsOrderedInf ? OrderedCmpOpcode : UnorderedCmpOpcode); + IsOrdered ? OrderedCmpOpcode : UnorderedCmpOpcode); + } + + if (OrderedFPTestMask == fcPosInf || OrderedFPTestMask == fcNegInf) { + // isposinf(x) --> x == inf + // isneginf(x) --> x == -inf + // isposinf(x) || nan --> x u== inf + // isneginf(x) || nan --> x u== -inf + + SDValue Inf = DAG.getConstantFP( + APFloat::getInf(Semantics, OrderedFPTestMask == fcNegInf), DL, + OperandVT); + return DAG.getSetCC(DL, ResultVT, Op, Inf, + IsOrdered ? OrderedCmpOpcode : UnorderedCmpOpcode); } } Index: llvm/test/CodeGen/X86/is_fpclass-fp80.ll =================================================================== --- llvm/test/CodeGen/X86/is_fpclass-fp80.ll +++ llvm/test/CodeGen/X86/is_fpclass-fp80.ll @@ -274,23 +274,24 @@ define i1 @is_posinf_f80(x86_fp80 %x) { ; CHECK-32-LABEL: is_posinf_f80: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: movl $-2147483648, %ecx # imm = 0x80000000 -; CHECK-32-NEXT: xorl {{[0-9]+}}(%esp), %ecx -; CHECK-32-NEXT: xorl $32767, %eax # imm = 0x7FFF -; CHECK-32-NEXT: orl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: orl %ecx, %eax -; CHECK-32-NEXT: sete %al +; CHECK-32-NEXT: fldt {{[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: setae %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_posinf_f80: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: movzwl {{[0-9]+}}(%rsp), %eax -; CHECK-64-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000 -; CHECK-64-NEXT: xorq {{[0-9]+}}(%rsp), %rcx -; CHECK-64-NEXT: xorq $32767, %rax # imm = 0x7FFF -; CHECK-64-NEXT: orq %rcx, %rax -; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: fldt {{[0-9]+}}(%rsp) +; CHECK-64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; CHECK-64-NEXT: fxch %st(1) +; CHECK-64-NEXT: fucompi %st(1), %st +; CHECK-64-NEXT: fstp %st(0) +; CHECK-64-NEXT: setae %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f80(x86_fp80 %x, i32 512) ; 0x200 = "+inf" @@ -300,23 +301,22 @@ define i1 @is_neginf_f80(x86_fp80 %x) { ; CHECK-32-LABEL: is_neginf_f80: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: xorl $65535, %eax # imm = 0xFFFF -; CHECK-32-NEXT: movl $-2147483648, %ecx # imm = 0x80000000 -; CHECK-32-NEXT: xorl {{[0-9]+}}(%esp), %ecx -; CHECK-32-NEXT: orl {{[0-9]+}}(%esp), %eax -; CHECK-32-NEXT: orl %ecx, %eax -; CHECK-32-NEXT: sete %al +; CHECK-32-NEXT: fldt {{[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: setae %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_neginf_f80: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: movzwl {{[0-9]+}}(%rsp), %eax -; CHECK-64-NEXT: xorl $65535, %eax # imm = 0xFFFF -; CHECK-64-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000 -; CHECK-64-NEXT: xorq {{[0-9]+}}(%rsp), %rcx -; CHECK-64-NEXT: orq %rcx, %rax -; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: fldt {{[0-9]+}}(%rsp) +; CHECK-64-NEXT: flds {{\.?LCPI[0-9]+_[0-9]+}}(%rip) +; CHECK-64-NEXT: fucompi %st(1), %st +; CHECK-64-NEXT: fstp %st(0) +; CHECK-64-NEXT: setae %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f80(x86_fp80 %x, i32 4) ; "-inf" Index: llvm/test/CodeGen/X86/is_fpclass.ll =================================================================== --- llvm/test/CodeGen/X86/is_fpclass.ll +++ llvm/test/CodeGen/X86/is_fpclass.ll @@ -185,15 +185,20 @@ define i1 @is_plus_inf_f(float %x) { ; CHECK-32-LABEL: is_plus_inf_f: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: cmpl $2139095040, {{[0-9]+}}(%esp) # imm = 0x7F800000 -; CHECK-32-NEXT: sete %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: setae %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_plus_inf_f: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: movd %xmm0, %eax -; CHECK-64-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000 -; CHECK-64-NEXT: sete %al +; CHECK-64-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; CHECK-64-NEXT: setae %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 512) ; 0x200 = "+inf" @@ -203,15 +208,20 @@ define i1 @is_minus_inf_f(float %x) { ; CHECK-32-LABEL: is_minus_inf_f: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: cmpl $-8388608, {{[0-9]+}}(%esp) # imm = 0xFF800000 -; CHECK-32-NEXT: sete %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: setae %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: 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: sete %al +; CHECK-64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; CHECK-64-NEXT: ucomiss %xmm0, %xmm1 +; CHECK-64-NEXT: setae %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 4) ; "-inf" @@ -221,15 +231,20 @@ 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: setne %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: setb %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: setne %al +; CHECK-64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero +; CHECK-64-NEXT: ucomiss %xmm0, %xmm1 +; CHECK-64-NEXT: setb %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1019) ; ~"-inf" @@ -1991,24 +2006,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 @@ -2017,24 +2027,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 @@ -2043,24 +2048,19 @@ 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: 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_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: setne %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 508) ; ~(0x200|0x3) = "~(+inf|nan)" ret i1 %class @@ -2069,24 +2069,19 @@ 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: 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_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: setne %al ; CHECK-64-NEXT: retq %class = tail call i1 @llvm.is.fpclass.f32(float %x, i32 1016) ; "~(-inf|nan)" ret i1 %class