https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/206927
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. >From 6c01d0862d475620ef035555cc8074cca5ed8e9f Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 12 Apr 2026 14:14:27 +0200 Subject: [PATCH] ValueTracking: Improve frexp known range from dominating conditions 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. --- llvm/include/llvm/Support/KnownFPClass.h | 14 ++- llvm/lib/Analysis/ValueTracking.cpp | 71 +++++++++-- llvm/lib/Support/KnownFPClass.cpp | 19 ++- .../Transforms/Attributor/nofpclass-ldexp.ll | 29 ++++- ...ed-exponent-range-dominating-conditions.ll | 112 +++++------------- 5 files changed, 140 insertions(+), 105 deletions(-) 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) { ; 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 ; @@ -466,9 +438,7 @@ define float @frexp_fcmp_oeq_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 ; @@ -498,9 +468,7 @@ define float @frexp_fcmp_ueq_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 ; @@ -530,9 +498,7 @@ define float @frexp_fcmp_one_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 ; @@ -562,9 +528,7 @@ define float @frexp_fcmp_une_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 ; @@ -594,9 +558,7 @@ define float @frexp_fcmp_oeq_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 ; @@ -626,9 +588,7 @@ define float @frexp_fcmp_ueq_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 ; @@ -658,9 +618,7 @@ define float @frexp_fcmp_one_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 ; @@ -690,9 +648,7 @@ define float @frexp_fcmp_une_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 ; @@ -906,9 +862,7 @@ define float @frexp_fcmp_ogt_nextdown1(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 ; @@ -939,9 +893,7 @@ define float @frexp_fcmp_ole_nextdown1(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 ; @@ -1074,9 +1026,7 @@ define float @frexp_fcmp_olt_1_multiple_conditions_wrong_constant(float %x, floa ; 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: [[EXIT]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -1115,9 +1065,7 @@ define float @frexp_fcmp_olt_1_multiple_conditions_nonfinite_constant(float %x, ; 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: [[EXIT]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -1154,9 +1102,7 @@ define float @frexp_fcmp_olt_1_multiple_conditions_edge_case_compare(float %x, f ; 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: [[EXIT]]: ; CHECK-NEXT: ret float 0.000000e+00 ; @@ -1194,9 +1140,7 @@ define float @frexp_fcmp_olt_1_multiple_conditions_other(float %x, float nofpcla ; 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: [[EXIT]]: ; CHECK-NEXT: ret float 0.000000e+00 ; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
