Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -3879,9 +3879,11 @@ return {nullptr, fcNone}; if (ConstRHS->isZero()) { - // Compares with fcNone are only exactly equal to fcZero if input denormals are - // not flushed. - if (FCmpInst::isEquality(Pred) && !inputDenormalIsIEEE(F, LHS->getType())) + // Compares with fcNone are only exactly equal to fcZero if input denormals + // are not flushed. + // TODO: Handle DAZ by expanding masks to cover subnormal cases. + if (Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO && + !inputDenormalIsIEEE(F, LHS->getType())) return {nullptr, fcNone}; switch (Pred) { @@ -3899,6 +3901,22 @@ return {LHS, ~fcNan}; case FCmpInst::FCMP_UNO: return {LHS, fcNan}; + case FCmpInst::FCMP_OGT: // x > 0 + return {LHS, fcPosSubnormal | fcPosNormal | fcPosInf}; + case FCmpInst::FCMP_UGT: // isnan(x) || x > 0 + return {LHS, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan}; + case FCmpInst::FCMP_OGE: // x >= 0 + return {LHS, fcPositive | fcNegZero}; + case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0 + return {LHS, fcPositive | fcNegZero | fcNan}; + case FCmpInst::FCMP_OLT: // x < 0 + return {LHS, fcNegSubnormal | fcNegNormal | fcNegInf}; + case FCmpInst::FCMP_ULT: // isnan(x) || x < 0 + return {LHS, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan}; + case FCmpInst::FCMP_OLE: // x <= 0 + return {LHS, fcNegative | fcPosZero}; + case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0 + return {LHS, fcNegative | fcPosZero | fcNan}; default: break; } Index: llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll +++ llvm/test/Transforms/InstCombine/create-class-from-logic-fcmp.ll @@ -237,10 +237,7 @@ ; Negative test define i1 @olt_0_or_fabs_ueq_inf(half %x) { ; CHECK-LABEL: @olt_0_or_fabs_ueq_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp olt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 543) ; CHECK-NEXT: ret i1 [[CLASS]] ; %fabs = call half @llvm.fabs.f16(half %x) @@ -1908,9 +1905,7 @@ define i1 @fcmp_ueq_neginf_or_oge_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_neginf_or_oge_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xHFC00 -; CHECK-NEXT: [[CMP_OGE_ZERO:%.*]] = fcmp oge half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OGE_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 999) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xHFC00 @@ -1921,9 +1916,7 @@ define i1 @fcmp_oeq_neginf_or_oge_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_neginf_or_oge_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xHFC00 -; CHECK-NEXT: [[CMP_OGE_ZERO:%.*]] = fcmp oge half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OGE_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 996) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xHFC00 @@ -1960,9 +1953,7 @@ define i1 @fcmp_oeq_neginf_or_ogt_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_neginf_or_ogt_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xHFC00 -; CHECK-NEXT: [[CMP_OGT_ZERO:%.*]] = fcmp ogt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OGT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 900) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xHFC00 @@ -1973,9 +1964,7 @@ define i1 @fcmp_ueq_neginf_or_ogt_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_neginf_or_ogt_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xHFC00 -; CHECK-NEXT: [[CMP_OGT_ZERO:%.*]] = fcmp ogt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OGT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 903) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xHFC00 @@ -2012,9 +2001,7 @@ define i1 @fcmp_oeq_neginf_or_ugt_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_neginf_or_ugt_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xHFC00 -; CHECK-NEXT: [[CMP_UGT_ZERO:%.*]] = fcmp ugt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_UGT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 903) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xHFC00 @@ -2051,9 +2038,7 @@ define i1 @fcmp_ueq_posinf_or_ole_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_posinf_or_ole_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_OLE_ZERO:%.*]] = fcmp ole half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OLE_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 639) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xH7C00 @@ -2064,9 +2049,7 @@ define i1 @fcmp_oeq_posinf_or_ole_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_posinf_or_ole_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_OLE_ZERO:%.*]] = fcmp ole half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OLE_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 636) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xH7C00 @@ -2103,9 +2086,7 @@ define i1 @fcmp_oeq_posinf_or_olt_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_posinf_or_olt_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_OLT_ZERO:%.*]] = fcmp olt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OLT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 540) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xH7C00 @@ -2129,9 +2110,7 @@ define i1 @fcmp_ueq_posinf_or_ult_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_posinf_or_ult_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_ULT_ZERO:%.*]] = fcmp ult half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_ULT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 543) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xH7C00 @@ -2142,9 +2121,7 @@ define i1 @fcmp_oeq_posinf_or_ult_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_oeq_posinf_or_ult_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_ULT_ZERO:%.*]] = fcmp ult half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_ULT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 543) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp oeq half %x, 0xH7C00 @@ -2181,9 +2158,7 @@ define i1 @fcmp_ueq_posinf_or_ule_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_posinf_or_ule_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_ULE_ZERO:%.*]] = fcmp ule half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_ULE_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 639) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xH7C00 @@ -2220,9 +2195,7 @@ define i1 @fcmp_ueq_posinf_or_olt_zero_f16(half %x) { ; CHECK-LABEL: @fcmp_ueq_posinf_or_olt_zero_f16( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMP_OLT_ZERO:%.*]] = fcmp olt half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_OLT_ZERO]], [[CMPINF]] +; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 543) ; CHECK-NEXT: ret i1 [[CLASS]] ; %cmpinf = fcmp ueq half %x, 0xH7C00