Index: llvm/include/llvm/IR/PatternMatch.h =================================================================== --- llvm/include/llvm/IR/PatternMatch.h +++ llvm/include/llvm/IR/PatternMatch.h @@ -621,18 +621,36 @@ struct is_inf { bool isValue(const APFloat &C) { return C.isInfinity(); } }; + +struct is_pos_inf { + bool isValue(const APFloat &C) { return C.isInfinity() && !C.isNegative(); } +}; + /// Match a positive or negative infinity FP constant. /// For vectors, this includes constants with undefined elements. inline cstfp_pred_ty m_Inf() { return cstfp_pred_ty(); } +inline cstfp_pred_ty m_PosInf() { + return cstfp_pred_ty(); +} struct is_smallest_normalized { bool isValue(const APFloat &C) { return C.isSmallestNormalized(); } }; +struct is_pos_smallest_normalized { + bool isValue(const APFloat &C) { + return !C.isNegative() && C.isSmallestNormalized(); + } +}; + inline cstfp_pred_ty m_SmallestNormalized() { return cstfp_pred_ty(); } +inline cstfp_pred_ty m_PosSmallestNormalized() { + return cstfp_pred_ty(); +} + struct is_noninf { bool isValue(const APFloat &C) { return !C.isInfinity(); } }; Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1205,6 +1205,86 @@ return Builder.CreateICmp(NewPred, NewV, ConstantInt::get(Ty, NewC)); } +/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the +/// same result as an fcmp with the given operands. +static std::pair fcmpToClassTest(FCmpInst::Predicate Pred, + Value *LHS, Value *RHS) { + if (Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_UGE) { + // fcmp olt fabs(x), smallest_normal -> fcSubnormal|fcZero + // fcmp uge fabs(x), smallest_normal -> ~(fcSubnormal|fcZero) + // fcmp olt fabs(x), +inf -> fcFinite + // fcmp uge fabs(x), +inf -> ~fcFinite + + unsigned Mask = 0; + if (match(RHS, m_PosInf())) + Mask = fcFinite; + else if (match(RHS, m_PosSmallestNormalized())) + Mask = fcZero | fcSubnormal; + else + return {nullptr, 0}; + + Value *Src = LHS; + if (match(LHS, m_FAbs(m_Value(Src)))) { + if (Pred == FCmpInst::FCMP_UGE) + Mask = ~Mask & fcAllFlags; + return {Src, Mask}; + } + + return {nullptr, 0}; + } + + if (!FCmpInst::isEquality(Pred)) + return {nullptr, 0}; + + if (match(RHS, m_AnyZeroFP())) { + switch (Pred) { + case FCmpInst::FCMP_OEQ: // Match x == 0.0 + return {LHS, fcZero}; + case FCmpInst::FCMP_UEQ: // match !(x != 0.0) + return {LHS, fcZero | fcNan}; + case FCmpInst::FCMP_UNE: + return {LHS, (~fcZero & fcAllFlags) | fcNan}; + case FCmpInst::FCMP_ONE: + return {LHS, ~fcNan & ~fcZero & fcAllFlags}; + default: + llvm_unreachable("not fcmp equality"); + } + } + + // Match __builtin_isinf patterns + // + // fcmp oeq x, +inf -> is_fpclass x, fcPosInf + // fcmp ueq x, +inf -> is_fpclass x, fcPosInf|fcNan + // + // fcmp oeq (fabs x), +inf -> is_fpclass x, fcInf + // fcmp ueq (fabs x), +inf -> is_fpclass x, fcInf|fcNan + // + // TODO: Handle -inf + if (match(RHS, m_PosInf())) { + // TODO: Peek through fneg (fabs x) + unsigned InfMask = fcPosInf; + Value *Src = LHS; + if (match(LHS, m_FAbs(m_Value(Src)))) + InfMask |= fcNegInf; + + unsigned Class; + if (Pred == FCmpInst::FCMP_OEQ) + Class = InfMask; + else if (Pred == FCmpInst::FCMP_UEQ) + Class = InfMask | fcNan; + else if (Pred == FCmpInst::FCMP_UNE) + Class = fcNan | (~InfMask & fcAllFlags); + else if (Pred == FCmpInst::FCMP_ONE) + Class = ~(fcNan | InfMask) & fcAllFlags; + else + llvm_unreachable("not fcmp equality"); + + return {Src, Class}; + } + + return {nullptr, 0}; +} + Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd, bool IsLogicalSelect) { Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1); @@ -1263,6 +1343,25 @@ return Builder.CreateFCmp(PredL, LHS0, RHS0); } + // Turn at least two fcmps with constants into llvm.is.fpclass. + // + // If we can represent a combined value test with one class call, we can + // potentially eliminate 4-6 instructions. If we can represent a test with a + // single fcmp with fneg and fabs, that's likely a better canonical form. + if (LHS->hasOneUse() && RHS->hasOneUse()) { + auto [ClassValLHS, ClassMaskLHS] = fcmpToClassTest(PredL, LHS0, LHS1); + if (ClassValLHS) { + auto [ClassValRHS, ClassMaskRHS] = fcmpToClassTest(PredR, RHS0, RHS1); + if (ClassValLHS == ClassValRHS) { + unsigned CombinedMask = IsAnd ? (ClassMaskLHS & ClassMaskRHS) + : (ClassMaskLHS | ClassMaskRHS); + return Builder.CreateIntrinsic( + Intrinsic::is_fpclass, {ClassValLHS->getType()}, + {ClassValLHS, Builder.getInt32(CombinedMask)}); + } + } + } + return nullptr; } 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 @@ -10,11 +10,8 @@ ; Base pattern !isfinite(x) || x == 0.0 define i1 @not_isfinite_or_zero_f16(half %x) { ; CHECK-LABEL: @not_isfinite_or_zero_f16( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 615) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -26,11 +23,8 @@ ; Base pattern x == 0.0 || !isfinite(x) define i1 @not_isfinite_or_zero_f16_commute_or(half %x) { ; CHECK-LABEL: @not_isfinite_or_zero_f16_commute_or( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPINF]], [[CMPZERO]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 615) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -42,11 +36,8 @@ ; Base pattern !isfinite(x) || x == -0.0 define i1 @not_isfinite_or_zero_f16_negzero(half %x) { ; CHECK-LABEL: @not_isfinite_or_zero_f16_negzero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 615) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -57,11 +48,8 @@ define i1 @not_isfinite_or_fabs_oeq_zero_f16(half %x) { ; CHECK-LABEL: @not_isfinite_or_fabs_oeq_zero_f16( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 615) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -73,11 +61,8 @@ ; Base pattern !isfinite(x) || x == 0.0 define <2 x i1> @not_isfinite_or_zero_v2f16(<2 x half> %x) { ; CHECK-LABEL: @not_isfinite_or_zero_v2f16( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq <2 x half> [[FABS]], -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq <2 x half> [[X]], zeroinitializer -; CHECK-NEXT: [[CLASS:%.*]] = or <2 x i1> [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret <2 x i1> [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 615) +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) %cmpinf = fcmp ueq <2 x half> %fabs, @@ -89,11 +74,8 @@ ; Base pattern !isfinite(x) || x == <0.0, -0.0> define <2 x i1> @not_isfinite_or_zero_v2f16_pos0_neg0_vec(<2 x half> %x) { ; CHECK-LABEL: @not_isfinite_or_zero_v2f16_pos0_neg0_vec( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq <2 x half> [[FABS]], -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq <2 x half> [[X]], zeroinitializer -; CHECK-NEXT: [[CLASS:%.*]] = or <2 x i1> [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret <2 x i1> [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 615) +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) %cmpinf = fcmp ueq <2 x half> %fabs, @@ -105,11 +87,8 @@ ; Base pattern x == 0.0 || !isfinite(x) define <2 x i1> @not_isfinite_or_zero_v2f16_commute_or(<2 x half> %x) { ; CHECK-LABEL: @not_isfinite_or_zero_v2f16_commute_or( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq <2 x half> [[FABS]], -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq <2 x half> [[X]], zeroinitializer -; CHECK-NEXT: [[CLASS:%.*]] = or <2 x i1> [[CMPINF]], [[CMPZERO]] -; CHECK-NEXT: ret <2 x i1> [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 615) +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) %cmpinf = fcmp ueq <2 x half> %fabs, @@ -121,11 +100,8 @@ ; Positive test define i1 @oeq_isinf_or_oeq_zero(half %x) { ; CHECK-LABEL: @oeq_isinf_or_oeq_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 612) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -137,10 +113,8 @@ ; Missing fabs for infinity check define i1 @ueq_inf_or_oeq_zero(half %x) { ; CHECK-LABEL: @ueq_inf_or_oeq_zero( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 611) +; CHECK-NEXT: ret i1 [[TMP1]] ; %cmpinf = fcmp ueq half %x, 0xH7C00 %cmpzero = fcmp oeq half %x, 0xH0000 @@ -151,11 +125,8 @@ ; Extra fabs. define i1 @oeq_isinf_or_fabs_oeq_zero(half %x) { ; CHECK-LABEL: @oeq_isinf_or_fabs_oeq_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 612) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -167,10 +138,8 @@ ; Positive test define i1 @ueq_0_or_oeq_inf(half %x) { ; CHECK-LABEL: @ueq_0_or_oeq_inf( -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[X:%.*]], 0xH0000 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH7C00 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 611) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH0000 @@ -194,11 +163,8 @@ ; Positive test define i1 @ueq_inf_or_ueq_zero(half %x) { ; CHECK-LABEL: @ueq_inf_or_ueq_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp ueq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 615) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -210,11 +176,7 @@ ; Positive test define i1 @not_isfinite_and_zero_f16(half %x) { ; CHECK-LABEL: @not_isfinite_and_zero_f16( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp ueq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp oeq half [[X]], 0xH0000 -; CHECK-NEXT: [[CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: ret i1 false ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp ueq half %fabs, 0xH7C00 @@ -362,11 +324,8 @@ ; Negation of base pattern, isfinite(x) && !(x == 0.0) define i1 @negated_isfinite_or_zero_f16(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 408) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp one half %fabs, 0xH7C00 @@ -378,11 +337,8 @@ ; Commuted !(x == 0.0) && isfinite(x) define i1 @negated_isfinite_or_zero_f16_commute_and(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16_commute_and( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPINF]], [[CMPZERO]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 408) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp one half %fabs, 0xH7C00 @@ -394,11 +350,8 @@ ; isfinite(x) && !(x == -0.0) define i1 @negated_isfinite_or_zero_f16_negzero(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16_negzero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 408) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp one half %fabs, 0xH7C00 @@ -410,11 +363,8 @@ ; Negated pattern define <2 x i1> @negated_isfinite_or_zero_v2f16(<2 x half> %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_v2f16( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one <2 x half> [[FABS]], -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une <2 x half> [[X]], zeroinitializer -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and <2 x i1> [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret <2 x i1> [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 408) +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) %cmpinf = fcmp one <2 x half> %fabs, @@ -426,11 +376,8 @@ ; Negated pattern, commuted vector and define <2 x i1> @negated_isfinite_or_zero_v2f16_comumte(<2 x half> %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_v2f16_comumte( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one <2 x half> [[FABS]], -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une <2 x half> [[X]], zeroinitializer -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and <2 x i1> [[CMPINF]], [[CMPZERO]] -; CHECK-NEXT: ret <2 x i1> [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 408) +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) %cmpinf = fcmp one <2 x half> %fabs, @@ -442,11 +389,8 @@ ; Positive test define i1 @negated_isfinite_or_zero_f16_not_une_zero(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16_not_une_zero( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp one half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 408) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp one half %fabs, 0xH7C00 @@ -458,11 +402,7 @@ ; Positive test define i1 @negated_isfinite_and_zero_f16(half %x) { ; CHECK-LABEL: @negated_isfinite_and_zero_f16( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp one half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: ret i1 true ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp one half %fabs, 0xH7C00 @@ -474,10 +414,8 @@ ; Negative test define i1 @negated_isfinite_or_zero_f16_swapped_constants(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16_swapped_constants( -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp one half [[X:%.*]], 0xH0000 -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[X]], 0xH7C00 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 412) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpzero = fcmp one half %fabs, 0xH0000 @@ -525,11 +463,8 @@ ; Negative test define i1 @negated_isfinite_or_zero_f16_multi_use_cmp0_not_one_inf(half %x) { ; CHECK-LABEL: @negated_isfinite_or_zero_f16_multi_use_cmp0_not_one_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[NOT_CLASS:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT_CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 411) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp une half %fabs, 0xH7C00 @@ -560,10 +495,7 @@ define i1 @fcmp_une_0_or_fcmp_une_inf(half %x) { ; CHECK-LABEL: @fcmp_une_0_or_fcmp_une_inf( -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X:%.*]], 0xH0000 -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[X]], 0xH7C00 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: ret i1 true ; %cmpzero = fcmp une half %x, 0.0 %cmpinf = fcmp une half %x, 0xH7C00 @@ -573,11 +505,8 @@ define i1 @fcmp_one_0_and_fcmp_une_fabs_inf(half %x) { ; CHECK-LABEL: @fcmp_one_0_and_fcmp_une_fabs_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp one half [[X]], 0xH0000 -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 408) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpzero = fcmp one half %x, 0.0 @@ -588,11 +517,8 @@ define i1 @fcmp_une_0_and_fcmp_une_fabs_inf(half %x) { ; CHECK-LABEL: @fcmp_une_0_and_fcmp_une_fabs_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPZERO:%.*]] = fcmp une half [[X]], 0xH0000 -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMPZERO]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 411) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpzero = fcmp une half %x, 0.0 @@ -616,11 +542,8 @@ define i1 @issubnormal_or_inf(half %x) { ; CHECK-LABEL: @issubnormal_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 756) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -646,11 +569,8 @@ define i1 @not_issubnormal_or_inf(half %x) { ; CHECK-LABEL: @not_issubnormal_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp une half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp uge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[NOT:%.*]] = and i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[NOT]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 267) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp une half %fabs, 0xH7C00 @@ -661,11 +581,8 @@ define i1 @issubnormal_uge_or_inf(half %x) { ; CHECK-LABEL: @issubnormal_uge_or_inf( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp oeq half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp uge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[CLASS:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[CLASS]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 783) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp oeq half %fabs, 0xH7C00 @@ -721,11 +638,8 @@ define i1 @issubnormal_or_finite_olt(half %x) { ; CHECK-LABEL: @issubnormal_or_finite_olt( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp olt half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp olt half %fabs, 0xH7C00 @@ -737,11 +651,8 @@ ; inf | nan | zero | subnormal define i1 @issubnormal_or_finite_uge(half %x) { ; CHECK-LABEL: @issubnormal_or_finite_uge( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp uge half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 759) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp uge half %fabs, 0xH7C00 @@ -752,11 +663,8 @@ define i1 @issubnormal_and_finite_olt(half %x) { ; CHECK-LABEL: @issubnormal_and_finite_olt( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp olt half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[AND]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 240) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp olt half %fabs, 0xH7C00 @@ -767,11 +675,8 @@ define i1 @not_zero_and_subnormal(half %x) { ; CHECK-LABEL: @not_zero_and_subnormal( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMP_ZERO:%.*]] = fcmp one half [[X]], 0xH0000 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMP_ZERO]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = fcmp ord half [[X:%.*]], 0xH0000 +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmp.zero = fcmp one half %fabs, 0.0 @@ -782,11 +687,8 @@ define i1 @fcmp_fabs_uge_inf_or_fabs_uge_smallest_norm(half %x) { ; CHECK-LABEL: @fcmp_fabs_uge_inf_or_fabs_uge_smallest_norm( -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]]) -; CHECK-NEXT: [[CMPINF:%.*]] = fcmp uge half [[FABS]], 0xH7C00 -; CHECK-NEXT: [[CMP_SMALLEST_NORMAL:%.*]] = fcmp uge half [[FABS]], 0xH0400 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_SMALLEST_NORMAL]], [[CMPINF]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 783) +; CHECK-NEXT: ret i1 [[TMP1]] ; %fabs = call half @llvm.fabs.f16(half %x) %cmpinf = fcmp uge half %fabs, 0xH7C00