Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -8101,9 +8101,14 @@ // Some checks can be implemented using float comparisons, if floating point // exceptions are ignored. if (Flags.hasNoFPExcept() && - // TODO: Should check isCondCodeLegal isOperationLegalOrCustom(ISD::SETCC, OperandVT.getScalarType())) { - if (isFCmpEqualZero(Test, Semantics, DAG.getMachineFunction())) { + // Even if the condition isn't legal, we're probably better off expanding it + // if it's the combined 0 || denormal compare. + + if (isFCmpEqualZero(Test, Semantics, DAG.getMachineFunction()) && + (Test != fcZero || + isCondCodeLegalOrCustom(IsInverted ? ISD::SETUNE : ISD::SETOEQ, + OperandVT.getScalarType().getSimpleVT()))) { // 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. return DAG.getSetCC(DL, ResultVT, Op, @@ -8111,9 +8116,12 @@ IsInverted ? ISD::SETUNE : ISD::SETOEQ); } - if (Test == fcNan) + if (Test == fcNan && + isCondCodeLegalOrCustom(IsInverted ? ISD::SETO : ISD::SETUO, + OperandVT.getScalarType().getSimpleVT())) { return DAG.getSetCC(DL, ResultVT, Op, Op, IsInverted ? ISD::SETO : ISD::SETUO); + } } // In the general case use integer operations. 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 @@ -160,26 +160,19 @@ define i1 @is_zero_f80(x86_fp80 %x) { ; CHECK-32-LABEL: is_zero_f80: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: fldt {{[0-9]+}}(%esp) -; CHECK-32-NEXT: fldz -; 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: setnp %cl +; CHECK-32-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; CHECK-32-NEXT: andl $32767, %eax # imm = 0x7FFF +; CHECK-32-NEXT: orl {{[0-9]+}}(%esp), %eax +; CHECK-32-NEXT: orl {{[0-9]+}}(%esp), %eax ; CHECK-32-NEXT: sete %al -; CHECK-32-NEXT: andb %cl, %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: is_zero_f80: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: fldt {{[0-9]+}}(%rsp) -; CHECK-64-NEXT: fldz -; CHECK-64-NEXT: fucompi %st(1), %st -; CHECK-64-NEXT: fstp %st(0) -; CHECK-64-NEXT: setnp %cl +; CHECK-64-NEXT: movzwl {{[0-9]+}}(%rsp), %eax +; CHECK-64-NEXT: andl $32767, %eax # imm = 0x7FFF +; CHECK-64-NEXT: orq {{[0-9]+}}(%rsp), %rax ; CHECK-64-NEXT: sete %al -; CHECK-64-NEXT: andb %cl, %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f80(x86_fp80 %x, i32 96) ; 0x60 = "zero" Index: llvm/test/CodeGen/X86/is_fpclass.ll =================================================================== --- llvm/test/CodeGen/X86/is_fpclass.ll +++ llvm/test/CodeGen/X86/is_fpclass.ll @@ -684,24 +684,15 @@ define i1 @iszero_f(float %x) { ; CHECK-32-LABEL: iszero_f: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) -; CHECK-32-NEXT: fldz -; 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: setnp %cl +; CHECK-32-NEXT: testl $2147483647, {{[0-9]+}}(%esp) # imm = 0x7FFFFFFF ; CHECK-32-NEXT: sete %al -; CHECK-32-NEXT: andb %cl, %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: iszero_f: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: xorps %xmm1, %xmm1 -; CHECK-64-NEXT: cmpeqss %xmm0, %xmm1 -; CHECK-64-NEXT: movd %xmm1, %eax -; CHECK-64-NEXT: andl $1, %eax -; CHECK-64-NEXT: # kill: def $al killed $al killed $eax +; CHECK-64-NEXT: movd %xmm0, %eax +; CHECK-64-NEXT: testl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-64-NEXT: sete %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 96) ; 0x60 = "zero" @@ -747,24 +738,15 @@ define i1 @not_iszero_f(float %x) { ; CHECK-32-LABEL: not_iszero_f: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: flds {{[0-9]+}}(%esp) -; CHECK-32-NEXT: fldz -; 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: setp %cl +; CHECK-32-NEXT: testl $2147483647, {{[0-9]+}}(%esp) # imm = 0x7FFFFFFF ; CHECK-32-NEXT: setne %al -; CHECK-32-NEXT: orb %cl, %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: not_iszero_f: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: xorps %xmm1, %xmm1 -; CHECK-64-NEXT: cmpneqss %xmm0, %xmm1 -; CHECK-64-NEXT: movd %xmm1, %eax -; CHECK-64-NEXT: andl $1, %eax -; CHECK-64-NEXT: # kill: def $al killed $al killed $eax +; CHECK-64-NEXT: movd %xmm0, %eax +; CHECK-64-NEXT: testl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-64-NEXT: setne %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 927) ; ~0x60 = "~zero" @@ -1293,24 +1275,18 @@ define i1 @iszero_d(double %x) { ; CHECK-32-LABEL: iszero_d: ; CHECK-32: # %bb.0: # %entry -; CHECK-32-NEXT: fldl {{[0-9]+}}(%esp) -; CHECK-32-NEXT: fldz -; 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: setnp %cl +; CHECK-32-NEXT: movl $2147483647, %eax # imm = 0x7FFFFFFF +; CHECK-32-NEXT: andl {{[0-9]+}}(%esp), %eax +; CHECK-32-NEXT: orl {{[0-9]+}}(%esp), %eax ; CHECK-32-NEXT: sete %al -; CHECK-32-NEXT: andb %cl, %al ; CHECK-32-NEXT: retl ; ; CHECK-64-LABEL: iszero_d: ; CHECK-64: # %bb.0: # %entry -; CHECK-64-NEXT: xorpd %xmm1, %xmm1 -; CHECK-64-NEXT: cmpeqsd %xmm0, %xmm1 -; CHECK-64-NEXT: movq %xmm1, %rax -; CHECK-64-NEXT: andl $1, %eax -; CHECK-64-NEXT: # kill: def $al killed $al killed $rax +; CHECK-64-NEXT: movq %xmm0, %rax +; CHECK-64-NEXT: shlq %rax +; CHECK-64-NEXT: testq %rax, %rax +; CHECK-64-NEXT: sete %al ; CHECK-64-NEXT: retq entry: %0 = tail call i1 @llvm.is.fpclass.f64(double %x, i32 96) ; 0x60 = "zero"