https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/173897
>From 7deebfac928b9c411fda2424f704d860f890706c Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Wed, 24 Dec 2025 11:38:25 +0100 Subject: [PATCH] InstCombine: Handle minimum/maximum in SimplifyDemandedFPClass --- llvm/include/llvm/Support/KnownFPClass.h | 14 +++ llvm/lib/Analysis/ValueTracking.cpp | 113 ++++------------- llvm/lib/Support/KnownFPClass.cpp | 92 ++++++++++++++ .../InstCombineSimplifyDemanded.cpp | 115 +++++++++++++++++- .../simplify-demanded-fpclass-maximum.ll | 93 ++++++-------- .../simplify-demanded-fpclass-minimum.ll | 81 +++++------- 6 files changed, 316 insertions(+), 192 deletions(-) diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index 62df87ad8a67e..2db25eca66df4 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -173,6 +173,20 @@ struct KnownFPClass { signBitMustBeZero(); } + // Enum of min/max intrinsics to avoid dependency on IR. + enum class MinMaxKind { + minimum, + maximum, + minimumnum, + maximumnum, + minnum, + maxnum + }; + + LLVM_ABI static KnownFPClass + minMaxLike(const KnownFPClass &LHS, const KnownFPClass &RHS, MinMaxKind Kind, + DenormalMode DenormMode = DenormalMode::getDynamic()); + /// Apply the canonicalize intrinsic to this value. This is essentially a /// stronger form of propagateCanonicalizingSrc. LLVM_ABI static KnownFPClass diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index cddd6f9c25074..281c59f671250 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4909,6 +4909,25 @@ static void computeKnownFPClassForFPTrunc(const Operator *Op, // Infinity needs a range check. } +static constexpr KnownFPClass::MinMaxKind getMinMaxKind(Intrinsic::ID IID) { + switch (IID) { + case Intrinsic::minimum: + return KnownFPClass::MinMaxKind::minimum; + case Intrinsic::maximum: + return KnownFPClass::MinMaxKind::maximum; + case Intrinsic::minimumnum: + return KnownFPClass::MinMaxKind::minimumnum; + case Intrinsic::maximumnum: + return KnownFPClass::MinMaxKind::maximumnum; + case Intrinsic::minnum: + return KnownFPClass::MinMaxKind::minnum; + case Intrinsic::maxnum: + return KnownFPClass::MinMaxKind::maxnum; + default: + llvm_unreachable("not a floating-point min-max intrinsic"); + } +} + void computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, KnownFPClass &Known, const SimplifyQuery &Q, unsigned Depth) { @@ -5179,95 +5198,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, computeKnownFPClass(II->getArgOperand(1), DemandedElts, InterestedClasses, KnownRHS, Q, Depth + 1); - bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN(); - Known = KnownLHS | KnownRHS; - - // If either operand is not NaN, the result is not NaN. - if (NeverNaN && - (IID == Intrinsic::minnum || IID == Intrinsic::maxnum || - IID == Intrinsic::minimumnum || IID == Intrinsic::maximumnum)) - Known.knownNot(fcNan); - - if (IID == Intrinsic::maxnum || IID == Intrinsic::maximumnum) { - // If at least one operand is known to be positive, the result must be - // positive. - if ((KnownLHS.cannotBeOrderedLessThanZero() && - KnownLHS.isKnownNeverNaN()) || - (KnownRHS.cannotBeOrderedLessThanZero() && - KnownRHS.isKnownNeverNaN())) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - } else if (IID == Intrinsic::maximum) { - // If at least one operand is known to be positive, the result must be - // positive. - if (KnownLHS.cannotBeOrderedLessThanZero() || - KnownRHS.cannotBeOrderedLessThanZero()) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - } else if (IID == Intrinsic::minnum || IID == Intrinsic::minimumnum) { - // If at least one operand is known to be negative, the result must be - // negative. - if ((KnownLHS.cannotBeOrderedGreaterThanZero() && - KnownLHS.isKnownNeverNaN()) || - (KnownRHS.cannotBeOrderedGreaterThanZero() && - KnownRHS.isKnownNeverNaN())) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - } else if (IID == Intrinsic::minimum) { - // If at least one operand is known to be negative, the result must be - // negative. - if (KnownLHS.cannotBeOrderedGreaterThanZero() || - KnownRHS.cannotBeOrderedGreaterThanZero()) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - } else - llvm_unreachable("unhandled intrinsic"); - - // Fixup zero handling if denormals could be returned as a zero. - // - // As there's no spec for denormal flushing, be conservative with the - // treatment of denormals that could be flushed to zero. For older - // subtargets on AMDGPU the min/max instructions would not flush the - // output and return the original value. - // - if ((Known.KnownFPClasses & fcZero) != fcNone && - !Known.isKnownNeverSubnormal()) { - const Function *Parent = II->getFunction(); - if (!Parent) - break; + const Function *F = II->getFunction(); - DenormalMode Mode = Parent->getDenormalMode( - II->getType()->getScalarType()->getFltSemantics()); - if (Mode != DenormalMode::getIEEE()) - Known.KnownFPClasses |= fcZero; - } + DenormalMode Mode = + F ? F->getDenormalMode( + II->getType()->getScalarType()->getFltSemantics()) + : DenormalMode::getDynamic(); - if (Known.isKnownNeverNaN()) { - if (KnownLHS.SignBit && KnownRHS.SignBit && - *KnownLHS.SignBit == *KnownRHS.SignBit) { - if (*KnownLHS.SignBit) - Known.signBitMustBeOne(); - else - Known.signBitMustBeZero(); - } else if ((IID == Intrinsic::maximum || IID == Intrinsic::minimum || - IID == Intrinsic::maximumnum || - IID == Intrinsic::minimumnum) || - // FIXME: Should be using logical zero versions - ((KnownLHS.isKnownNeverNegZero() || - KnownRHS.isKnownNeverPosZero()) && - (KnownLHS.isKnownNeverPosZero() || - KnownRHS.isKnownNeverNegZero()))) { - // Don't take sign bit from NaN operands. - if (!KnownLHS.isKnownNeverNaN()) - KnownLHS.SignBit = std::nullopt; - if (!KnownRHS.isKnownNeverNaN()) - KnownRHS.SignBit = std::nullopt; - if ((IID == Intrinsic::maximum || IID == Intrinsic::maximumnum || - IID == Intrinsic::maxnum) && - (KnownLHS.SignBit == false || KnownRHS.SignBit == false)) - Known.signBitMustBeZero(); - else if ((IID == Intrinsic::minimum || IID == Intrinsic::minimumnum || - IID == Intrinsic::minnum) && - (KnownLHS.SignBit == true || KnownRHS.SignBit == true)) - Known.signBitMustBeOne(); - } - } + Known = KnownFPClass::minMaxLike(KnownLHS, KnownRHS, getMinMaxKind(IID), + Mode); break; } case Intrinsic::canonicalize: { diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index 125bee00c38ff..ee4114cf5a060 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -91,6 +91,98 @@ void KnownFPClass::propagateDenormal(const KnownFPClass &Src, } } +KnownFPClass KnownFPClass::minMaxLike(const KnownFPClass &LHS_, + const KnownFPClass &RHS_, MinMaxKind Kind, + DenormalMode Mode) { + KnownFPClass KnownLHS = LHS_; + KnownFPClass KnownRHS = RHS_; + + bool NeverNaN = KnownLHS.isKnownNeverNaN() || KnownRHS.isKnownNeverNaN(); + KnownFPClass Known = KnownLHS | KnownRHS; + + // If either operand is not NaN, the result is not NaN. + if (NeverNaN && + (Kind == MinMaxKind::minnum || Kind == MinMaxKind::maxnum || + Kind == MinMaxKind::minimumnum || Kind == MinMaxKind::maximumnum)) + Known.knownNot(fcNan); + + if (Kind == MinMaxKind::maxnum || Kind == MinMaxKind::maximumnum) { + // If at least one operand is known to be positive, the result must be + // positive. + if ((KnownLHS.cannotBeOrderedLessThanZero() && + KnownLHS.isKnownNeverNaN()) || + (KnownRHS.cannotBeOrderedLessThanZero() && KnownRHS.isKnownNeverNaN())) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + } else if (Kind == MinMaxKind::maximum) { + // If at least one operand is known to be positive, the result must be + // positive. + if (KnownLHS.cannotBeOrderedLessThanZero() || + KnownRHS.cannotBeOrderedLessThanZero()) + Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); + } else if (Kind == MinMaxKind::minnum || Kind == MinMaxKind::minimumnum) { + // If at least one operand is known to be negative, the result must be + // negative. + if ((KnownLHS.cannotBeOrderedGreaterThanZero() && + KnownLHS.isKnownNeverNaN()) || + (KnownRHS.cannotBeOrderedGreaterThanZero() && + KnownRHS.isKnownNeverNaN())) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); + } else if (Kind == MinMaxKind::minimum) { + // If at least one operand is known to be negative, the result must be + // negative. + if (KnownLHS.cannotBeOrderedGreaterThanZero() || + KnownRHS.cannotBeOrderedGreaterThanZero()) + Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); + } else + llvm_unreachable("unhandled intrinsic"); + + // Fixup zero handling if denormals could be returned as a zero. + // + // As there's no spec for denormal flushing, be conservative with the + // treatment of denormals that could be flushed to zero. For older + // subtargets on AMDGPU the min/max instructions would not flush the + // output and return the original value. + // + if ((Known.KnownFPClasses & fcZero) != fcNone && + !Known.isKnownNeverSubnormal()) { + if (Mode != DenormalMode::getIEEE()) + Known.KnownFPClasses |= fcZero; + } + + if (Known.isKnownNeverNaN()) { + if (KnownLHS.SignBit && KnownRHS.SignBit && + *KnownLHS.SignBit == *KnownRHS.SignBit) { + if (*KnownLHS.SignBit) + Known.signBitMustBeOne(); + else + Known.signBitMustBeZero(); + } else if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::minimum || + Kind == MinMaxKind::maximumnum || + Kind == MinMaxKind::minimumnum) || + // FIXME: Should be using logical zero versions + ((KnownLHS.isKnownNeverNegZero() || + KnownRHS.isKnownNeverPosZero()) && + (KnownLHS.isKnownNeverPosZero() || + KnownRHS.isKnownNeverNegZero()))) { + // Don't take sign bit from NaN operands. + if (!KnownLHS.isKnownNeverNaN()) + KnownLHS.SignBit = std::nullopt; + if (!KnownRHS.isKnownNeverNaN()) + KnownRHS.SignBit = std::nullopt; + if ((Kind == MinMaxKind::maximum || Kind == MinMaxKind::maximumnum || + Kind == MinMaxKind::maxnum) && + (KnownLHS.SignBit == false || KnownRHS.SignBit == false)) + Known.signBitMustBeZero(); + else if ((Kind == MinMaxKind::minimum || Kind == MinMaxKind::minimumnum || + Kind == MinMaxKind::minnum) && + (KnownLHS.SignBit == true || KnownRHS.SignBit == true)) + Known.signBitMustBeOne(); + } + } + + return Known; +} + KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc, DenormalMode DenormMode) { KnownFPClass Known; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 33ece6c2b69d8..762f7421631b3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2077,7 +2077,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V, } case Instruction::Call: { CallInst *CI = cast<CallInst>(I); - switch (CI->getIntrinsicID()) { + const Intrinsic::ID IID = CI->getIntrinsicID(); + switch (IID) { case Intrinsic::fabs: if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), Known, Depth + 1)) @@ -2111,6 +2112,118 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V, Known.copysign(KnownSign); break; } + case Intrinsic::maximum: + case Intrinsic::minimum: { + KnownFPClass KnownLHS, KnownRHS; + + // We can't tell much based on the demanded result without inspecting the + // operands (e.g., a known-positive result could have been clamped), but + // we can still prune known-nan inputs. + FPClassTest SrcDemandedMask = DemandedMask | ~fcNan; + + if (SimplifyDemandedFPClass(CI, 1, SrcDemandedMask, KnownRHS, + Depth + 1) || + SimplifyDemandedFPClass(CI, 0, SrcDemandedMask, KnownLHS, Depth + 1)) + return I; + + /// Propagate nnan-ness to simplify edge case checks. + if ((DemandedMask & fcNan) == fcNone) { + KnownLHS.knownNot(fcNan); + KnownRHS.knownNot(fcNan); + } + + if (IID == Intrinsic::maximum) { + // If at least one operand is known to be positive and the other + // negative, the result must be the positive (unless the other operand + // may be propagating a nan). + if (KnownLHS.isKnownNever(fcNegative) && + KnownRHS.isKnownNever(fcPositive | fcNan)) + return CI->getArgOperand(0); + + if (KnownRHS.isKnownNever(fcNegative) && + KnownLHS.isKnownNever(fcPositive | fcNan)) + return CI->getArgOperand(1); + + // If one value must be pinf, the result is pinf or a propagated nan. + if (KnownLHS.isKnownAlways(fcPosInf | fcNan) && + KnownRHS.isKnownNever(fcNan)) + return CI->getArgOperand(0); + + if (KnownRHS.isKnownAlways(fcPosInf | fcNan) && + KnownLHS.isKnownNever(fcNan)) + return CI->getArgOperand(1); + + // If one value must be ninf, the other value must be returned or a + // propagated nan. + if (KnownLHS.isKnownAlways(fcNegInf | fcNan) && + KnownRHS.isKnownNever(fcNan)) + return CI->getArgOperand(1); + + if (KnownRHS.isKnownAlways(fcNegInf | fcNan) && + KnownLHS.isKnownNever(fcNan)) + return CI->getArgOperand(0); + } else { + // If one operand is known to be negative, and the other positive, the + // result must be the negative (unless the other operand may be + // propagating a nan). + if (KnownLHS.isKnownNever(fcPositive) && + KnownRHS.isKnownNever(fcNegative | fcNan)) + return CI->getArgOperand(0); + + if (KnownRHS.isKnownNever(fcPositive) && + KnownLHS.isKnownNever(fcNegative | fcNan)) + return CI->getArgOperand(1); + + // If one value must be ninf, the result is ninf or a propagated nan. + if (KnownLHS.isKnownAlways(fcNegInf | fcNan) && + KnownRHS.isKnownNever(fcNan)) + return CI->getArgOperand(0); + + if (KnownRHS.isKnownAlways(fcNegInf | fcNan) && + KnownLHS.isKnownNever(fcNan)) + return CI->getArgOperand(1); + + // If one value must be pinf, the other value must be returned or a + // propagated nan. + if (KnownLHS.isKnownAlways(fcPosInf | fcNan) && + KnownRHS.isKnownNever(fcNan)) + return CI->getArgOperand(1); + + if (KnownRHS.isKnownAlways(fcPosInf | fcNan) && + KnownLHS.isKnownNever(fcNan)) + return CI->getArgOperand(0); + } + + Type *EltTy = VTy->getScalarType(); + DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics()); + Known = KnownFPClass::minMaxLike(KnownLHS, KnownRHS, + IID == Intrinsic::maximum + ? KnownFPClass::MinMaxKind::maximum + : KnownFPClass::MinMaxKind::minimum, + Mode); + + FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; + + if (Constant *SingleVal = + getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true)) + return SingleVal; + + auto *FPOp = cast<FPMathOperator>(CI); + + bool ChangedFlags = false; + + // TODO: Add NSZ flag if we know the result will not be sensitive on the + // sign of 0. + if (!FPOp->hasNoNaNs() && (ValidResults & fcNan) == fcNone) { + CI->setHasNoNaNs(true); + ChangedFlags = true; + } + + if (ChangedFlags) + return FPOp; + + return nullptr; + } case Intrinsic::exp: case Intrinsic::exp2: case Intrinsic::exp10: { diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll index 99e03f6b12e5c..b7c41ff6c3c64 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll @@ -25,8 +25,7 @@ declare nofpclass(inf norm sub zero) float @returns_nan() define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %result = call float @llvm.maximum.f32(float %x, float %y) ret float %result @@ -55,7 +54,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %x, float %y) @@ -83,7 +82,7 @@ define nofpclass(nan ninf norm sub zero) float @ret_only_pinf(float %x, float %y define nofpclass(inf nan norm sub) float @ret_only_zero(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %x, float %y) @@ -111,7 +110,7 @@ define nofpclass(inf nan norm sub pzero) float @ret_only_nzero(float %x, float % define nofpclass(nan) float @ret_no_nans(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %x, float %y) @@ -131,7 +130,7 @@ define nofpclass(inf) float @ret_no_infs(float %x, float %y) { define nofpclass(nan inf) float @ret_no_nans_no_infs(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nans_no_infs( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %x, float %y) @@ -143,8 +142,7 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_known_positive_or_nan__maximu ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_known_positive_or_nan__maximum__negative_or_nan___negative_or_nan() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN0:%.*]] = call float @returns_negative_or_nan() ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN1:%.*]] = call float @returns_negative_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE_OR_NAN0]], float [[MUST_BE_NEGATIVE_OR_NAN1]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %must.be.negative.or.nan0 = call float @returns_negative_or_nan() %must.be.negative.or.nan1 = call float @returns_negative_or_nan() @@ -157,8 +155,7 @@ define nofpclass(pinf pnorm psub pzero) float @ret_known_negative_or_nan__maximu ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_known_negative_or_nan__maximum__positive_or_nan___positive_or_nan() { ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN0:%.*]] = call float @returns_positive_or_nan() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN1:%.*]] = call float @returns_positive_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_NAN0]], float [[MUST_BE_POSITIVE_OR_NAN1]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %must.be.positive.or.nan0 = call float @returns_positive_or_nan() %must.be.positive.or.nan1 = call float @returns_positive_or_nan() @@ -196,8 +193,7 @@ define nofpclass(snan) float @known_positive_or_nan__maximum__known_negative() { ; CHECK-LABEL: define nofpclass(snan) float @known_positive_or_nan__maximum__known_negative() { ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() ; CHECK-NEXT: [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_POSITIVE_OR_NAN]] ; %must.be.positive.or.nan = call float @returns_positive_or_nan() %must.be.negative = call float @returns_negative() @@ -209,8 +205,7 @@ define nofpclass(snan) float @known_negative__maximum__known_positive_or_nan() { ; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximum__known_positive_or_nan() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE]], float [[MUST_BE_POSITIVE_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_POSITIVE_OR_NAN]] ; %must.be.negative = call float @returns_negative() %must.be.positive.or.nan = call float @returns_positive_or_nan() @@ -251,7 +246,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__select_a ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -265,7 +260,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__unknown_ ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -299,7 +294,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_negative__simplify ; CHECK-NEXT: [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]] ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative0 = call float @returns_negative() @@ -315,7 +310,7 @@ define nofpclass(nan) float @no_fold_select_always_negative_0(i1 %cond, float %u ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -329,7 +324,7 @@ define nofpclass(nan) float @no_fold_select_always_negative_1(i1 %cond, float %u ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -343,7 +338,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() ; CHECK-LABEL: define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %must.be.negative.or.zero = call float @returns_positive_or_zero() @@ -357,7 +352,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ; CHECK-LABEL: define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %must.be.negative.or.zero = call float @returns_positive_or_zero() @@ -389,7 +384,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_PINF]], float [[UNKNOWN]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %must.be.pinf, float %unknown) @@ -399,7 +394,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(n define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf( ; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float 0x7FF0000000000000) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %unknown, float %must.be.pinf) @@ -410,8 +405,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zer define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan ninf norm zero sub) %must.be.pinf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan( ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_PINF]], float [[NOT_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF0000000000000 ; %result = call float @llvm.maximum.f32(float %must.be.pinf, float %not.nan) ret float %result @@ -421,8 +415,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan( ; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NAN]], float [[MUST_BE_PINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF0000000000000 ; %result = call float @llvm.maximum.f32(float %not.nan, float %must.be.pinf) ret float %result @@ -451,8 +444,7 @@ define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(nan pinf norm zero sub) %must.be.ninf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NINF]], float [[UNKNOWN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[UNKNOWN]] ; %result = call float @llvm.maximum.f32(float %must.be.ninf, float %unknown) ret float %result @@ -461,8 +453,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(n define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float %unknown) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf( ; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[UNKNOWN]] ; %result = call float @llvm.maximum.f32(float %unknown, float %must.be.ninf) ret float %result @@ -473,8 +464,7 @@ define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zer define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan pinf norm zero sub) %must.be.ninf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan( ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NINF]], float [[NOT_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[NOT_NAN]] ; %result = call float @llvm.maximum.f32(float %must.be.ninf, float %not.nan) ret float %result @@ -484,8 +474,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan( ; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[NOT_NAN]], float [[MUST_BE_NINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[NOT_NAN]] ; %result = call float @llvm.maximum.f32(float %not.nan, float %must.be.ninf) ret float %result @@ -794,7 +783,7 @@ define nofpclass(snan) float @unknown__maximum__not_nan(float %x, float nofpclas define nofpclass(snan) float @not_nan__maximum__not_nan(float nofpclass(nan) %x, float nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(snan) float @not_nan__maximum__not_nan( ; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.maximum.f32(float %x, float %y) @@ -825,7 +814,7 @@ define nofpclass(snan) float @known_positive__maximum__only_zero() { ; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_zero() { ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() ; CHECK-NEXT: [[KNOWN_ZERO:%.*]] = call float @returns_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %known.positive = call float @returns_positive() @@ -838,7 +827,7 @@ define nofpclass(snan) float @only_zero__maximum__known_positive() { ; CHECK-LABEL: define nofpclass(snan) float @only_zero__maximum__known_positive() { ; CHECK-NEXT: [[KNOWN_ZERO:%.*]] = call float @returns_zero() ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]]) ; CHECK-NEXT: ret float [[RESULT]] ; %known.zero = call float @returns_zero() @@ -903,8 +892,7 @@ define nofpclass(snan) float @known_positive__maximum__only_nzero() { ; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_nzero() { ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() ; CHECK-NEXT: [[KNOWN_NZERO:%.*]] = call float @returns_nzero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_POSITIVE]] ; %known.positive = call float @returns_positive() %known.nzero = call float @returns_nzero() @@ -916,8 +904,7 @@ define nofpclass(snan) float @only_nzero__maximum__known_positive() { ; CHECK-LABEL: define nofpclass(snan) float @only_nzero__maximum__known_positive() { ; CHECK-NEXT: [[KNOWN_NZERO:%.*]] = call float @returns_nzero() ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_NZERO]], float [[KNOWN_POSITIVE]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_POSITIVE]] ; %known.nzero = call float @returns_nzero() %known.positive = call float @returns_positive() @@ -929,7 +916,7 @@ define nofpclass(snan) float @known_positive__maximum__only_pzero() { ; CHECK-LABEL: define nofpclass(snan) float @known_positive__maximum__only_pzero() { ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() ; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_PZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00) ; CHECK-NEXT: ret float [[RESULT]] ; %known.positive = call float @returns_positive() @@ -942,7 +929,7 @@ define nofpclass(snan) float @only_pzero__maximum__known_positive() { ; CHECK-LABEL: define nofpclass(snan) float @only_pzero__maximum__known_positive() { ; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero() ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_PZERO]], float [[KNOWN_POSITIVE]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[KNOWN_POSITIVE]], float 0.000000e+00) ; CHECK-NEXT: ret float [[RESULT]] ; %known.pzero = call float @returns_pzero() @@ -1081,8 +1068,7 @@ define nofpclass(snan) float @known_negative__maximum__only_pzero_or_nan() { ; CHECK-LABEL: define nofpclass(snan) float @known_negative__maximum__only_pzero_or_nan() { ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_PZERO_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_PZERO_OR_NAN]] ; %known.negative = call float @returns_negative() %known.pzero.or.nan = call float @returns_pzero_or_nan() @@ -1094,8 +1080,7 @@ define nofpclass(snan) float @only_pzero_or_nan__maximum__known_negative() { ; CHECK-LABEL: define nofpclass(snan) float @only_pzero_or_nan__maximum__known_negative() { ; CHECK-NEXT: [[KNOWN_PZERO_OR_NAN:%.*]] = call float @returns_pzero_or_nan() ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[KNOWN_PZERO_OR_NAN]], float [[KNOWN_NEGATIVE]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_PZERO_OR_NAN]] ; %known.pzero.or.nan = call float @returns_pzero_or_nan() %known.negative = call float @returns_negative() @@ -1176,8 +1161,7 @@ define nofpclass(nan) float @ret_nonan__known_negative_or_nan__maximum__known_po ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_negative_or_nan__maximum__known_positive_or_nan() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_POSITIVE_OR_NAN]] ; %must.be.negative.or.nan = call float @returns_negative_or_nan() %must.be.positive.or.nan = call float @returns_positive_or_nan() @@ -1189,8 +1173,7 @@ define nofpclass(nan) float @ret_nonan__known_positive_or_nan__maximum__known_ne ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_positive_or_nan__maximum__known_negative_or_nan() { ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_POSITIVE_OR_NAN]] ; %must.be.positive.or.nan = call float @returns_positive_or_nan() %must.be.negative.or.nan = call float @returns_negative_or_nan() @@ -1202,8 +1185,7 @@ define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__maximum__unknown( ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__maximum__unknown( ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NAN:%.*]] = call float @returns_nan() -; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NAN]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.nan = call float @returns_nan() @@ -1216,8 +1198,7 @@ define nofpclass(nan) float @ret_nonan__unknown__maximum__select_nan_or_unknown( ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__unknown__maximum__select_nan_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NAN:%.*]] = call float @returns_nan() -; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN0]], float [[ALWAYS_NAN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.maximum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.maximum.f32(float [[UNKNOWN1]], float [[UNKNOWN0]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.nan = call float @returns_nan() diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll index af7a255511e2d..33891dba88883 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll @@ -25,8 +25,7 @@ declare nofpclass(inf norm sub zero) float @returns_nan() define nofpclass(inf norm sub zero) float @ret_only_nan(float %x, float %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %result = call float @llvm.minimum.f32(float %x, float %y) ret float %result @@ -55,7 +54,7 @@ define nofpclass(inf norm sub zero snan) float @ret_only_qnan(float %x, float %y define nofpclass(nan norm sub zero) float @ret_only_inf(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) float @ret_only_inf( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %x, float %y) @@ -83,7 +82,7 @@ define nofpclass(nan ninf norm sub zero) float @ret_only_pinf(float %x, float %y define nofpclass(inf nan norm sub) float @ret_only_zero(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan inf sub norm) float @ret_only_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %x, float %y) @@ -111,7 +110,7 @@ define nofpclass(inf nan norm sub pzero) float @ret_only_nzero(float %x, float % define nofpclass(nan) float @ret_no_nans(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %x, float %y) @@ -131,7 +130,7 @@ define nofpclass(inf) float @ret_no_infs(float %x, float %y) { define nofpclass(nan inf) float @ret_no_nans_no_infs(float %x, float %y) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_nans_no_infs( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %x, float %y) @@ -143,8 +142,7 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_known_positive_or_nan__minimu ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_known_positive_or_nan__minimum__negative_or_nan___negative_or_nan() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN0:%.*]] = call float @returns_negative_or_nan() ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN1:%.*]] = call float @returns_negative_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_NEGATIVE_OR_NAN0]], float [[MUST_BE_NEGATIVE_OR_NAN1]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %must.be.negative.or.nan0 = call float @returns_negative_or_nan() %must.be.negative.or.nan1 = call float @returns_negative_or_nan() @@ -157,8 +155,7 @@ define nofpclass(pinf pnorm psub pzero) float @ret_known_negative_or_nan__minimu ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_known_negative_or_nan__minimum__positive_or_nan___positive_or_nan() { ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN0:%.*]] = call float @returns_positive_or_nan() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN1:%.*]] = call float @returns_positive_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_POSITIVE_OR_NAN0]], float [[MUST_BE_POSITIVE_OR_NAN1]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %must.be.positive.or.nan0 = call float @returns_positive_or_nan() %must.be.positive.or.nan1 = call float @returns_positive_or_nan() @@ -251,7 +248,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__select_a ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -265,7 +262,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_positive__unknown_ ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -299,7 +296,7 @@ define nofpclass(ninf nnorm nsub nzero nan) float @ret_always_negative__simplify ; CHECK-NEXT: [[ALWAYS_NEGATIVE1:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE0]], float [[UNKNOWN0]] ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN1]], float [[ALWAYS_NEGATIVE1]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT_LHS]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative0 = call float @returns_negative() @@ -315,7 +312,7 @@ define nofpclass(nan) float @no_fold_select_always_negative_0(i1 %cond, float %u ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -329,7 +326,7 @@ define nofpclass(nan) float @no_fold_select_always_negative_1(i1 %cond, float %u ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NEGATIVE]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.negative = call float @returns_negative() @@ -343,7 +340,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() ; CHECK-LABEL: define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_0() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[MUST_BE_NEGATIVE_OR_ZERO]], float [[MUST_BE_POSITIVE_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %must.be.negative.or.zero = call float @returns_positive_or_zero() @@ -357,7 +354,7 @@ define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() ; CHECK-LABEL: define nofpclass(snan) float @cannot_fold_negative_or_zero__positive_or_zero_1() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_ZERO:%.*]] = call float @returns_positive_or_zero() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_ZERO:%.*]] = call float @returns_negative_or_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[MUST_BE_POSITIVE_OR_ZERO]], float [[MUST_BE_NEGATIVE_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %must.be.negative.or.zero = call float @returns_positive_or_zero() @@ -389,8 +386,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf_or_nan(float nofpclass(ninf norm define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(nan ninf norm zero sub) %must.be.pinf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_PINF]], float [[UNKNOWN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[UNKNOWN]] ; %result = call float @llvm.minimum.f32(float %must.be.pinf, float %unknown) ret float %result @@ -399,8 +395,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf(float %unknown, float nofpclass(n define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float %unknown) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf( ; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN]], float [[MUST_BE_PINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[UNKNOWN]] ; %result = call float @llvm.minimum.f32(float %unknown, float %must.be.pinf) ret float %result @@ -410,8 +405,7 @@ define nofpclass(nsub) float @rhs_must_be_pinf(float nofpclass(nan ninf norm zer define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan ninf norm zero sub) %must.be.pinf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan( ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_PINF]], float [[NOT_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[NOT_NAN]] ; %result = call float @llvm.minimum.f32(float %must.be.pinf, float %not.nan) ret float %result @@ -421,8 +415,7 @@ define nofpclass(nsub) float @lhs_must_be_pinf_rhs_non_nan(float nofpclass(nan) define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan(float nofpclass(nan ninf norm zero sub) %must.be.pinf, float nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_pinf_lhs_non_nan( ; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[MUST_BE_PINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[NOT_NAN]], float [[MUST_BE_PINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[NOT_NAN]] ; %result = call float @llvm.minimum.f32(float %not.nan, float %must.be.pinf) ret float %result @@ -451,7 +444,7 @@ define nofpclass(nsub) float @rhs_must_be_ninf_or_nan(float nofpclass(pinf norm define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(nan pinf norm zero sub) %must.be.ninf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf( ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_NINF]], float [[UNKNOWN]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN]], float 0xFFF0000000000000) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %must.be.ninf, float %unknown) @@ -461,7 +454,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf(float %unknown, float nofpclass(n define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float %unknown) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf( ; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN]], float [[MUST_BE_NINF]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN]], float 0xFFF0000000000000) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %unknown, float %must.be.ninf) @@ -473,8 +466,7 @@ define nofpclass(nsub) float @rhs_must_be_ninf(float nofpclass(nan pinf norm zer define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) %not.nan, float nofpclass(nan pinf norm zero sub) %must.be.ninf) { ; CHECK-LABEL: define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan( ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_NINF]], float [[NOT_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0xFFF0000000000000 ; %result = call float @llvm.minimum.f32(float %must.be.ninf, float %not.nan) ret float %result @@ -484,8 +476,7 @@ define nofpclass(nsub) float @lhs_must_be_ninf_rhs_non_nan(float nofpclass(nan) define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan(float nofpclass(nan pinf norm zero sub) %must.be.ninf, float nofpclass(nan) %not.nan) { ; CHECK-LABEL: define nofpclass(nsub) float @rhs_must_be_ninf_lhs_non_nan( ; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[MUST_BE_NINF:%.*]], float nofpclass(nan) [[NOT_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[NOT_NAN]], float [[MUST_BE_NINF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0xFFF0000000000000 ; %result = call float @llvm.minimum.f32(float %not.nan, float %must.be.ninf) ret float %result @@ -794,7 +785,7 @@ define nofpclass(snan) float @unknown__minimum__not_nan(float %x, float nofpclas define nofpclass(snan) float @not_nan__minimum__not_nan(float nofpclass(nan) %x, float nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(snan) float @not_nan__minimum__not_nan( ; CHECK-SAME: float nofpclass(nan) [[X:%.*]], float nofpclass(nan) [[Y:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[X]], float [[Y]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.minimum.f32(float %x, float %y) @@ -825,7 +816,7 @@ define nofpclass(snan) float @known_positive__minimum__only_zero() { ; CHECK-LABEL: define nofpclass(snan) float @known_positive__minimum__only_zero() { ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() ; CHECK-NEXT: [[KNOWN_ZERO:%.*]] = call float @returns_zero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[KNOWN_POSITIVE]], float [[KNOWN_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %known.positive = call float @returns_positive() @@ -838,7 +829,7 @@ define nofpclass(snan) float @only_zero__minimum__known_positive() { ; CHECK-LABEL: define nofpclass(snan) float @only_zero__minimum__known_positive() { ; CHECK-NEXT: [[KNOWN_ZERO:%.*]] = call float @returns_zero() ; CHECK-NEXT: [[KNOWN_POSITIVE:%.*]] = call float @returns_positive() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[KNOWN_ZERO]], float [[KNOWN_POSITIVE]]) ; CHECK-NEXT: ret float [[RESULT]] ; %known.zero = call float @returns_zero() @@ -1003,7 +994,7 @@ define nofpclass(snan) float @known_negative__minimum__only_nzero() { ; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimum__only_nzero() { ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[KNOWN_NZERO:%.*]] = call float @returns_nzero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_NZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[KNOWN_NEGATIVE]], float -0.000000e+00) ; CHECK-NEXT: ret float [[RESULT]] ; %known.negative = call float @returns_negative() @@ -1016,7 +1007,7 @@ define nofpclass(snan) float @only_nzero__minimum__known_negative() { ; CHECK-LABEL: define nofpclass(snan) float @only_nzero__minimum__known_negative() { ; CHECK-NEXT: [[KNOWN_NZERO:%.*]] = call float @returns_nzero() ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_NZERO]], float [[KNOWN_NEGATIVE]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[KNOWN_NEGATIVE]], float -0.000000e+00) ; CHECK-NEXT: ret float [[RESULT]] ; %known.nzero = call float @returns_nzero() @@ -1055,8 +1046,7 @@ define nofpclass(snan) float @known_negative__minimum__only_pzero() { ; CHECK-LABEL: define nofpclass(snan) float @known_negative__minimum__only_pzero() { ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() ; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_NEGATIVE]], float [[KNOWN_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_NEGATIVE]] ; %known.negative = call float @returns_negative() %known.pzero = call float @returns_pzero() @@ -1068,8 +1058,7 @@ define nofpclass(snan) float @only_pzero__minimum__known_negative() { ; CHECK-LABEL: define nofpclass(snan) float @only_pzero__minimum__known_negative() { ; CHECK-NEXT: [[KNOWN_PZERO:%.*]] = call float @returns_pzero() ; CHECK-NEXT: [[KNOWN_NEGATIVE:%.*]] = call float @returns_negative() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[KNOWN_PZERO]], float [[KNOWN_NEGATIVE]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[KNOWN_NEGATIVE]] ; %known.pzero = call float @returns_pzero() %known.negative = call float @returns_negative() @@ -1176,8 +1165,7 @@ define nofpclass(nan) float @ret_nonan__known_negative_or_nan__minimum__known_po ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_negative_or_nan__minimum__known_positive_or_nan() { ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_NEGATIVE_OR_NAN]], float [[MUST_BE_POSITIVE_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_NEGATIVE_OR_NAN]] ; %must.be.negative.or.nan = call float @returns_negative_or_nan() %must.be.positive.or.nan = call float @returns_positive_or_nan() @@ -1189,8 +1177,7 @@ define nofpclass(nan) float @ret_nonan__known_positive_or_nan__minimum__known_ne ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__known_positive_or_nan__minimum__known_negative_or_nan() { ; CHECK-NEXT: [[MUST_BE_POSITIVE_OR_NAN:%.*]] = call float @returns_positive_or_nan() ; CHECK-NEXT: [[MUST_BE_NEGATIVE_OR_NAN:%.*]] = call float @returns_negative_or_nan() -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[MUST_BE_POSITIVE_OR_NAN]], float [[MUST_BE_NEGATIVE_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[MUST_BE_NEGATIVE_OR_NAN]] ; %must.be.positive.or.nan = call float @returns_positive_or_nan() %must.be.negative.or.nan = call float @returns_negative_or_nan() @@ -1202,8 +1189,7 @@ define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__minimum__unknown( ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__select_nan_or_unknown__minimum__unknown( ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NAN:%.*]] = call float @returns_nan() -; CHECK-NEXT: [[SELECT_LHS:%.*]] = select i1 [[COND]], float [[ALWAYS_NAN]], float [[UNKNOWN0]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[SELECT_LHS]], float [[UNKNOWN1]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[UNKNOWN0]], float [[UNKNOWN1]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.nan = call float @returns_nan() @@ -1216,8 +1202,7 @@ define nofpclass(nan) float @ret_nonan__unknown__minimum__select_nan_or_unknown( ; CHECK-LABEL: define nofpclass(nan) float @ret_nonan__unknown__minimum__select_nan_or_unknown( ; CHECK-SAME: i1 [[COND:%.*]], float [[UNKNOWN0:%.*]], float [[UNKNOWN1:%.*]]) { ; CHECK-NEXT: [[ALWAYS_NAN:%.*]] = call float @returns_nan() -; CHECK-NEXT: [[SELECT_RHS:%.*]] = select i1 [[COND]], float [[UNKNOWN0]], float [[ALWAYS_NAN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.minimum.f32(float [[UNKNOWN1]], float [[SELECT_RHS]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nnan float @llvm.minimum.f32(float [[UNKNOWN1]], float [[UNKNOWN0]]) ; CHECK-NEXT: ret float [[RESULT]] ; %always.nan = call float @returns_nan() _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
