[llvm-branch-commits] [llvm] InstCombine: Handle minimum/maximum in SimplifyDemandedFPClass (PR #173897)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 29 10:04:48 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
---
Patch is 63.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/173897.diff
6 Files Affected:
- (modified) llvm/include/llvm/Support/KnownFPClass.h (+14)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+26-87)
- (modified) llvm/lib/Support/KnownFPClass.cpp (+92)
- (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp (+114-1)
- (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-maximum.ll (+37-56)
- (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-minimum.ll (+33-48)
``````````diff
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: ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/173897
More information about the llvm-branch-commits
mailing list