llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-llvm-analysis Author: Matt Arsenault (arsenm) <details> <summary>Changes</summary> Try to restrict the known range of the exponent result of llvm.frexp based on dominating conditions. Identify comparisons that imply the incoming value cannot introduce an overflow in a downstream ldexp use. This pattern appears in the implementation of some complex math functions and allows finite only math to prune out more edge case paths. One attributor test for ldexp regresses due to the switch from computeKnownBits to computeConstantRange. computeConstantRange does not try to handle non-splat vector constants for the binary operators. As a side effect, this also improves knowing that ldexp can't introduce overflow for the 0 case. --- Patch is 29.65 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/206927.diff 5 Files Affected: - (modified) llvm/include/llvm/Support/KnownFPClass.h (+10-4) - (modified) llvm/lib/Analysis/ValueTracking.cpp (+63-8) - (modified) llvm/lib/Support/KnownFPClass.cpp (+13-6) - (modified) llvm/test/Transforms/Attributor/nofpclass-ldexp.ll (+26-3) - (modified) llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll (+28-84) ``````````diff diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index 7e018d25d2d1d..0b948e799f6c5 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -448,10 +448,16 @@ struct KnownFPClass { static LLVM_ABI KnownFPClass frexp_mant( const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic()); - /// Propagate known class for ldexp - static LLVM_ABI KnownFPClass - ldexp(const KnownFPClass &Src, const KnownBits &N, const fltSemantics &Flt, - DenormalMode Mode = DenormalMode::getDynamic()); + /// Propagate known class for ldexp, assuming the exponent is known to be + /// within [\p ConstantRangeMin, \p ConstantRangeMax] + /// + // TODO: This really ought to use ConstantRange, but it's in IR not Support. + static LLVM_ABI KnownFPClass ldexp( + const KnownFPClass &Src, int ConstantRangeMin, int ConstantRangeMax, + const fltSemantics &Flt, DenormalMode Mode = DenormalMode::getDynamic()); + static LLVM_ABI KnownFPClass ldexp( + const KnownFPClass &Src, const KnownBits &ExpBits, + const fltSemantics &Flt, DenormalMode Mode = DenormalMode::getDynamic()); /// Propagate known class for powi static LLVM_ABI KnownFPClass powi(const KnownFPClass &Src, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 5cbf9f628867f..97948a15f9384 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4867,6 +4867,50 @@ static void computeKnownFPClassFromCond(const Value *V, Value *Cond, } } +/// Compute the minimum and maximum values (inclusive) for the exponent of \p V, +/// assuming it is not nan. +static std::pair<int, int> +computeKnownExponentRangeFromContext(const Value *V, const SimplifyQuery &Q) { + if (!Q.CxtI || !Q.DC || !Q.DT) + return {APFloat::IEK_NaN, APFloat::IEK_Inf}; + + for (CondBrInst *BI : Q.DC->conditionsFor(V)) { + const Value *A; + CmpPredicate Pred; + const APFloat *LimitC; + if (!match(BI->getCondition(), + m_FCmp(Pred, m_FAbs(m_Value(A)), m_Finite(LimitC)))) + continue; + + if (Pred == FCmpInst::FCMP_ORD || Pred == FCmpInst::FCMP_UNO || + Pred == FCmpInst::FCMP_TRUE || Pred == FCmpInst::FCMP_FALSE) + continue; + + APFloat::cmpResult CmpOne = + LimitC->compare(APFloat::getOne(LimitC->getSemantics())); + if (CmpOne > APFloat::cmpEqual) + continue; + + // If fabs(x) <= K, K <= 1.0 => exponent min exp range + // if fabs(x) >= K, K <= 1.0 swap the successor + bool IsLessEqual = + Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE || + Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE || + Pred == FCmpInst::FCMP_OEQ || Pred == FCmpInst::FCMP_UEQ; + + BasicBlockEdge Edge1(BI->getParent(), + BI->getSuccessor(IsLessEqual ? 0 : 1)); + if (Q.DT->dominates(Edge1, Q.CxtI->getParent())) { + int Exp = ilogb(*LimitC); + + // TODO: Figure out lower bound to detect no-underflow. + return {APFloat::IEK_NaN, Exp}; + } + } + + return {APFloat::IEK_NaN, APFloat::IEK_Inf}; +} + static KnownFPClass computeKnownFPClassFromContext(const Value *V, const SimplifyQuery &Q) { KnownFPClass KnownFromContext; @@ -4990,6 +5034,7 @@ static constexpr KnownFPClass::MinMaxKind getMinMaxKind(Intrinsic::ID IID) { static bool isAbsoluteValueULEOne(const Value *V) { // TODO: Handle frexp // TODO: Other rounding intrinsics? + // TODO: Try computeKnownExponentRangeFromContext // fabs(x - floor(x)) <= 1 const Value *SubFloorX; @@ -5507,11 +5552,11 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, // Can refine inf/zero handling based on the exponent operand. const FPClassTest ExpInfoMask = fcZero | fcSubnormal | fcInf; - KnownBits ExpBits; - if ((KnownSrc.KnownFPClasses & ExpInfoMask) != fcNone) { - const Value *ExpArg = II->getArgOperand(1); - ExpBits = computeKnownBits(ExpArg, DemandedElts, Q, Depth + 1); - } + const Value *ExpArg = II->getArgOperand(1); + ConstantRange ExpKnownRange = + ((KnownSrc.KnownFPClasses & ExpInfoMask) != fcNone) + ? computeConstantRange(ExpArg, /*ForSigned=*/true, Q, Depth + 1) + : ConstantRange::getFull(ExpArg->getType()->getIntegerBitWidth()); const fltSemantics &Flt = II->getType()->getScalarType()->getFltSemantics(); @@ -5520,7 +5565,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, DenormalMode Mode = F ? F->getDenormalMode(Flt) : DenormalMode::getDynamic(); - Known = KnownFPClass::ldexp(KnownSrc, ExpBits, Flt, Mode); + Known = KnownFPClass::ldexp( + KnownSrc, ExpKnownRange.getSignedMin().getSExtValue(), + ExpKnownRange.getSignedMax().getSExtValue(), Flt, Mode); break; } case Intrinsic::arithmetic_fence: { @@ -10473,9 +10520,17 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned, MinExp -= (APFloat::semanticsPrecision(FltSem) - 1); int MaxExp = APFloat::semanticsMaxExponent(FltSem) + 1; + + auto [AdjustedMin, AdjustedMax] = + computeKnownExponentRangeFromContext(FrexpSrc, SQ); + + MinExp = std::max(AdjustedMin, MinExp); + MaxExp = std::min(AdjustedMax, MaxExp); + CR = ConstantRange::getNonEmpty( - APInt(BitWidth, MinExp, /*isSigned=*/true), - APInt(BitWidth, MaxExp + 1, /*isSigned=*/true)); + APInt(BitWidth, static_cast<int64_t>(MinExp), /*isSigned=*/true), + APInt(BitWidth, static_cast<int64_t>(MaxExp) + 1, + /*isSigned=*/true)); } } } diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index 38762f05d74ac..c9f081482390b 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -789,7 +789,8 @@ KnownFPClass KnownFPClass::frexp_mant(const KnownFPClass &KnownSrc, } KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc, - const KnownBits &ExpBits, + int ConstantRangeExpMin, + int ConstantRangeExpMax, const fltSemantics &Flt, DenormalMode Mode) { KnownFPClass Known; Known.propagateNaN(KnownSrc, /*PropagateSign=*/true); @@ -807,20 +808,19 @@ KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc, unsigned Precision = APFloat::semanticsPrecision(Flt); const int MantissaBits = Precision - 1; - - if (ExpBits.getSignedMinValue().sge(static_cast<int64_t>(MantissaBits))) + if (ConstantRangeExpMin >= MantissaBits) Known.knownNot(fcSubnormal); - if (ExpBits.isConstant() && ExpBits.getConstant().isZero()) { + if (ConstantRangeExpMin == 0 && ConstantRangeExpMax == 0) { // ldexp(x, 0) -> x, so propagate everything. Known.propagateCanonicalizingSrc(KnownSrc, Mode); - } else if (ExpBits.isNegative()) { + } else if (ConstantRangeExpMax <= 0) { // If we know the power is <= 0, can't introduce inf if (KnownSrc.isKnownNeverPosInfinity()) Known.knownNot(fcPosInf); if (KnownSrc.isKnownNeverNegInfinity()) Known.knownNot(fcNegInf); - } else if (ExpBits.isNonNegative()) { + } else if (ConstantRangeExpMin >= 0) { // If we know the power is >= 0, can't introduce subnormal or zero if (KnownSrc.isKnownNeverPosSubnormal()) Known.knownNot(fcPosSubnormal); @@ -835,6 +835,13 @@ KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc, return Known; } +KnownFPClass KnownFPClass::ldexp(const KnownFPClass &KnownSrc, + const KnownBits &ExpBits, + const fltSemantics &Flt, DenormalMode Mode) { + return ldexp(KnownSrc, ExpBits.getSignedMinValue().getSExtValue(), + ExpBits.getSignedMaxValue().getSExtValue(), Flt, Mode); +} + KnownFPClass KnownFPClass::powi(const KnownFPClass &KnownSrc, const KnownBits &ExponentKnownBits) { KnownFPClass Known; diff --git a/llvm/test/Transforms/Attributor/nofpclass-ldexp.ll b/llvm/test/Transforms/Attributor/nofpclass-ldexp.ll index 1d8c7af63c4fe..630e510a12d72 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-ldexp.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-ldexp.ll @@ -701,12 +701,25 @@ define <2 x float> @ret_ldexp_v2f32_known_pos_exp_noinf(<2 x float> nofpclass(in ret <2 x float> %call } -define <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf(<2 x float> nofpclass(inf) %arg0, <2 x i32> %arg1) #0 { -; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf +define <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf_splat(<2 x float> nofpclass(inf) %arg0, <2 x i32> %arg1) #0 { +; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf_splat ; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[OR_ARG1:%.*]] = or <2 x i32> [[ARG1]], <i32 -16, i32 -32> +; CHECK-NEXT: [[OR_ARG1:%.*]] = or <2 x i32> [[ARG1]], splat (i32 -32) ; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> nofpclass(inf) [[ARG0]], <2 x i32> [[OR_ARG1]]) #[[ATTR10]] ; CHECK-NEXT: ret <2 x float> [[CALL]] +; + %or.arg1 = or <2 x i32> %arg1, splat (i32 -32) + %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> %or.arg1) + ret <2 x float> %call +} + +; TODO: computeConstantRange does not handle non-splat operator constants. +define <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf_nonsplat(<2 x float> nofpclass(inf) %arg0, <2 x i32> %arg1) #0 { +; CHECK-LABEL: define <2 x float> @ret_ldexp_v2f32_known_neg_exp_noinf_nonsplat +; CHECK-SAME: (<2 x float> nofpclass(inf) [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[OR_ARG1:%.*]] = or <2 x i32> [[ARG1]], <i32 -16, i32 -32> +; CHECK-NEXT: [[CALL:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> nofpclass(inf) [[ARG0]], <2 x i32> [[OR_ARG1]]) #[[ATTR10]] +; CHECK-NEXT: ret <2 x float> [[CALL]] ; %or.arg1 = or <2 x i32> %arg1, <i32 -16, i32 -32> %call = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %arg0, <2 x i32> %or.arg1) @@ -1035,6 +1048,16 @@ define float @ret_ldexp_f32_neg127(float %arg0) #0 { ret float %call } +define float @ret_ldexp_f32_noinf_exp_known_neg_or_0(float nofpclass(inf) %arg0, i32 range(i32 -256, 1) %arg1) #0 { +; CHECK-LABEL: define nofpclass(inf) float @ret_ldexp_f32_noinf_exp_known_neg_or_0 +; CHECK-SAME: (float nofpclass(inf) [[ARG0:%.*]], i32 range(i32 -256, 1) [[ARG1:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(inf) float @llvm.ldexp.f32.i32(float nofpclass(inf) [[ARG0]], i32 [[ARG1]]) #[[ATTR10]] +; CHECK-NEXT: ret float [[CALL]] +; + %call = call float @llvm.ldexp.f32.i32(float %arg0, i32 %arg1) + ret float %call +} + attributes #0 = { denormal_fpenv(ieee|ieee) } attributes #1 = { denormal_fpenv(preservesign) } attributes #2 = { denormal_fpenv(positivezero|positivezero) } diff --git a/llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll b/llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll index fda131f421c99..e1e2576b7aa10 100644 --- a/llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll +++ b/llvm/test/Transforms/InstCombine/frexp-implied-exponent-range-dominating-conditions.ll @@ -17,9 +17,7 @@ define float @frexp_fcmp_ogt_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -49,9 +47,7 @@ define float @frexp_fcmp_oge_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -81,9 +77,7 @@ define float @frexp_fcmp_ugt_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -113,9 +107,7 @@ define float @frexp_fcmp_uge_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -145,9 +137,7 @@ define float @frexp_fcmp_olt_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -177,9 +167,7 @@ define float @frexp_fcmp_ole_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -210,9 +198,7 @@ define float @frexp_fcmp_ult_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -242,9 +228,7 @@ define float @frexp_fcmp_ule_1(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -274,9 +258,7 @@ define float @frexp_cmp_ugt_0.5(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -306,9 +288,7 @@ define float @frexp_cmp_uge_0.5(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -338,9 +318,7 @@ define float @frexp_fcmp_ult_0.5(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -370,9 +348,7 @@ define float @frexp_fcmp_ule_0.5(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -402,9 +378,7 @@ define float @frexp_fcmp_ugt_0.5(float %x, float nofpclass(inf) %not.inf) { ; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]]) ; CHECK-NEXT: [[EXP:%.*]] = extractvalue { float, i32 } [[FREXP]], 1 ; CHECK-NEXT: [[SCALED:%.*]] = call float @llvm.ldexp.f32.i32(float [[NOT_INF]], i32 [[EXP]]) -; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq float [[SCALED]], +inf -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_INF]], float 0.000000e+00, float [[SCALED]] -; CHECK-NEXT: ret float [[SELECT]] +; CHECK-NEXT: ret float [[SCALED]] ; CHECK: [[LARGE]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -434,9 +408,7 @@ define float @frexp_fcmp_uge_0.5(float %x, float nofpclass(inf) %not.inf) { ;... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/206927 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
