[llvm] ValueTracking: Identify implied fp classes by general fcmp (PR #66505)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 15 05:40:37 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
<details>
<summary>Changes</summary>
None
--
Patch is 119.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66505.diff
5 Files Affected:
- (modified) llvm/include/llvm/Analysis/ValueTracking.h (+21)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+167-27)
- (modified) llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll (+160-160)
- (modified) llvm/test/Transforms/InstSimplify/assume-fcmp-constant-implies-class.ll (+90-180)
- (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+4-4)
<pre>
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 695f2fecae885b7..6a2fac1961070e4 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -235,6 +235,27 @@ std::pair<Value *, FPClassTest> fcmpToClassTest(CmpInst::Predicate Pred,
const APFloat *ConstRHS,
bool LookThroughSrc = true);
+/// Compute the possible floating-point classes that \p LHS could be based on an
+/// fcmp returning true. Returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
+///
+/// If the compare returns an exact class test, ClassesIfTrue == ~ClassesIfFalse
+///
+/// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
+/// only succeed for a test of x > 0 implies positive, but not x > 1).
+///
+/// If \p LookThroughSrc is true, consider the input value when computing the
+/// mask. This may look through sign bit operations.
+///
+/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
+/// element will always be LHS.
+///
+std::tuple<Value *, FPClassTest, FPClassTest>
+fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
+ const APFloat *ConstRHS, bool LookThroughSrc = true);
+std::tuple<Value *, FPClassTest, FPClassTest>
+fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
+ Value *RHS, bool LookThroughSrc = true);
+
struct KnownFPClass {
/// Floating-point classes the value could be one of.
FPClassTest KnownFPClasses = fcAllFlags;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c4153b824c37e0a..99be7c0c9e7e9c9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4008,7 +4008,7 @@ std::pair<Value *, FPClassTest> llvm::fcmpToClassTest(FCmpInst::Predicate Pred,
bool LookThroughSrc) {
const APFloat *ConstRHS;
if (!match(RHS, m_APFloatAllowUndef(ConstRHS)))
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
return fcmpToClassTest(Pred, F, LHS, ConstRHS, LookThroughSrc);
}
@@ -4030,7 +4030,7 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
// TODO: Handle DAZ by expanding masks to cover subnormal cases.
if (Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO &&
!inputDenormalIsIEEE(F, LHS->getType()))
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
switch (Pred) {
case FCmpInst::FCMP_OEQ: // Match x == 0.0
@@ -4067,7 +4067,7 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
break;
}
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
}
Value *Src = LHS;
@@ -4151,7 +4151,7 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
case FCmpInst::FCMP_OGE:
case FCmpInst::FCMP_ULT: {
if (ConstRHS->isNegative()) // TODO
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
// fcmp oge fabs(x), +inf -> fcInf
// fcmp oge x, +inf -> fcPosInf
@@ -4165,14 +4165,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
case FCmpInst::FCMP_OGT:
case FCmpInst::FCMP_ULE: {
if (ConstRHS->isNegative())
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
// No value is ordered and greater than infinity.
Mask = fcNone;
break;
}
default:
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
}
} else if (ConstRHS->isSmallestNormalized() && !ConstRHS->isNegative()) {
// Match pattern that's used in __builtin_isnormal.
@@ -4201,14 +4201,14 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
break;
}
default:
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
}
} else if (ConstRHS->isNaN()) {
// fcmp o__ x, nan -> false
// fcmp u__ x, nan -> true
Mask = fcNone;
} else
- return {nullptr, fcNone};
+ return {nullptr, fcAllFlags};
// Invert the comparison for the unordered cases.
if (FCmpInst::isUnordered(Pred))
@@ -4217,6 +4217,140 @@ llvm::fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
return {Src, Mask};
}
+std::tuple<Value *, FPClassTest, FPClassTest>
+llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
+ const APFloat *ConstRHS, bool LookThroughSrc) {
+ auto [Val, ClassMask] =
+ fcmpToClassTest(Pred, F, LHS, ConstRHS, LookThroughSrc);
+ if (Val)
+ return {Val, ClassMask, ~ClassMask};
+
+ FPClassTest RHSClass = ConstRHS->classify();
+ assert((RHSClass == fcPosNormal || RHSClass == fcNegNormal ||
+ RHSClass == fcPosSubnormal || RHSClass == fcNegSubnormal) &&
+ "should have been recognized as an exact class test");
+
+ const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
+ const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
+
+ assert(IsNegativeRHS == ConstRHS->isNegative());
+ assert(IsPositiveRHS == !ConstRHS->isNegative());
+
+ Value *Src = LHS;
+ const bool IsFabs = LookThroughSrc && match(LHS, m_FAbs(m_Value(Src)));
+
+ if (IsFabs)
+ RHSClass = llvm::inverse_fabs(RHSClass);
+
+ if (Pred == FCmpInst::FCMP_OEQ)
+ return {Src, RHSClass, fcAllFlags};
+
+ if (Pred == FCmpInst::FCMP_UEQ) {
+ FPClassTest Class = RHSClass | fcNan;
+ return {Src, Class, ~fcNan};
+ }
+
+ if (Pred == FCmpInst::FCMP_ONE)
+ return {Src, ~fcNan, RHSClass};
+
+ if (Pred == FCmpInst::FCMP_UNE)
+ return {Src, fcAllFlags, RHSClass};
+
+ if (IsNegativeRHS) {
+ // TODO: Handle fneg(fabs)
+ if (IsFabs) {
+ // fabs(x) o> -k -> fcmp ord x, x
+ // fabs(x) u> -k -> true
+ // fabs(x) o< -k -> false
+ // fabs(x) u< -k -> fcmp uno x, x
+ switch (Pred) {
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_OGE:
+ return {Src, ~fcNan, fcNan};
+ case FCmpInst::FCMP_UGT:
+ case FCmpInst::FCMP_UGE:
+ return {Src, fcAllFlags, fcNone};
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLE:
+ return {Src, fcNone, fcAllFlags};
+ case FCmpInst::FCMP_ULT:
+ case FCmpInst::FCMP_ULE:
+ return {Src, fcNan, ~fcNan};
+ default:
+ break;
+ }
+
+ return {nullptr, fcAllFlags, fcAllFlags};
+ }
+
+ FPClassTest ClassesLE = fcNegInf | fcNegNormal;
+ FPClassTest ClassesGE = fcPositive | fcNegZero | fcNegSubnormal;
+
+ if (ConstRHS->isDenormal())
+ ClassesLE |= fcNegSubnormal;
+ else
+ ClassesGE |= fcNegNormal;
+
+ switch (Pred) {
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_OGE:
+ return {Src, ClassesGE, ~ClassesGE | RHSClass};
+ case FCmpInst::FCMP_UGT:
+ case FCmpInst::FCMP_UGE:
+ return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLE:
+ return {Src, ClassesLE, ~ClassesLE | RHSClass};
+ case FCmpInst::FCMP_ULT:
+ case FCmpInst::FCMP_ULE:
+ return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
+ default:
+ break;
+ }
+ } else if (IsPositiveRHS) {
+ FPClassTest ClassesGE = fcPosNormal | fcPosInf;
+ FPClassTest ClassesLE = fcNegative | fcPosZero | fcPosNormal;
+ if (ConstRHS->isDenormal())
+ ClassesGE |= fcPosNormal;
+ else
+ ClassesLE |= fcPosSubnormal;
+
+ FPClassTest FalseClasses = RHSClass;
+ if (IsFabs) {
+ ClassesGE = llvm::inverse_fabs(ClassesGE);
+ ClassesLE = llvm::inverse_fabs(ClassesLE);
+ }
+
+ switch (Pred) {
+ case FCmpInst::FCMP_OGT:
+ case FCmpInst::FCMP_OGE:
+ return {Src, ClassesGE, ~ClassesGE | FalseClasses};
+ case FCmpInst::FCMP_UGT:
+ case FCmpInst::FCMP_UGE:
+ return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | FalseClasses};
+ case FCmpInst::FCMP_OLT:
+ case FCmpInst::FCMP_OLE:
+ return {Src, ClassesLE, ~ClassesLE | FalseClasses};
+ case FCmpInst::FCMP_ULT:
+ case FCmpInst::FCMP_ULE:
+ return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | FalseClasses};
+ default:
+ break;
+ }
+ }
+
+ return {nullptr, fcAllFlags, fcAllFlags};
+}
+
+std::tuple<Value *, FPClassTest, FPClassTest>
+llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
+ Value *RHS, bool LookThroughSrc) {
+ const APFloat *ConstRHS;
+ if (!match(RHS, m_APFloatAllowUndef(ConstRHS)))
+ return {nullptr, fcAllFlags, fcNone};
+ return fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
+}
+
static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
const SimplifyQuery &Q) {
FPClassTest KnownFromAssume = fcAllFlags;
@@ -4241,18 +4375,21 @@ static FPClassTest computeKnownFPClassFromAssumes(const Value *V,
Value *LHS, *RHS;
uint64_t ClassVal = 0;
if (match(I->getArgOperand(0), m_FCmp(Pred, m_Value(LHS), m_Value(RHS)))) {
- auto [TestedValue, TestedMask] =
- fcmpToClassTest(Pred, *F, LHS, RHS, true);
- // First see if we can fold in fabs/fneg into the test.
- if (TestedValue == V)
- KnownFromAssume &= TestedMask;
- else {
- // Try again without the lookthrough if we found a different source
- // value.
- auto [TestedValue, TestedMask] =
- fcmpToClassTest(Pred, *F, LHS, RHS, false);
- if (TestedValue == V)
- KnownFromAssume &= TestedMask;
+ const APFloat *CRHS;
+ if (match(RHS, m_APFloat(CRHS))) {
+ // First see if we can fold in fabs/fneg into the test.
+ auto [CmpVal, MaskIfTrue, MaskIfFalse] =
+ fcmpImpliesClass(Pred, *F, LHS, CRHS, true);
+ if (CmpVal == V)
+ KnownFromAssume &= MaskIfTrue;
+ else {
+ // Try again without the lookthrough if we found a different source
+ // value.
+ auto [CmpVal, MaskIfTrue, MaskIfFalse] =
+ fcmpImpliesClass(Pred, *F, LHS, CRHS, false);
+ if (CmpVal == V)
+ KnownFromAssume &= MaskIfTrue;
+ }
}
} else if (match(I->getArgOperand(0),
m_Intrinsic<Intrinsic::is_fpclass>(
@@ -4400,7 +4537,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
FPClassTest FilterRHS = fcAllFlags;
Value *TestedValue = nullptr;
- FPClassTest TestedMask = fcNone;
+ FPClassTest MaskIfTrue = fcAllFlags;
+ FPClassTest MaskIfFalse = fcAllFlags;
uint64_t ClassVal = 0;
const Function *F = cast<Instruction>(Op)->getFunction();
CmpInst::Predicate Pred;
@@ -4412,20 +4550,22 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
// TODO: In some degenerate cases we can infer something if we try again
// without looking through sign operations.
bool LookThroughFAbsFNeg = CmpLHS != LHS && CmpLHS != RHS;
- std::tie(TestedValue, TestedMask) =
- fcmpToClassTest(Pred, *F, CmpLHS, CmpRHS, LookThroughFAbsFNeg);
+ std::tie(TestedValue, MaskIfTrue, MaskIfFalse) =
+ fcmpImpliesClass(Pred, *F, CmpLHS, CmpRHS, LookThroughFAbsFNeg);
} else if (match(Cond,
m_Intrinsic<Intrinsic::is_fpclass>(
m_Value(TestedValue), m_ConstantInt(ClassVal)))) {
- TestedMask = static_cast<FPClassTest>(ClassVal);
+ FPClassTest TestedMask = static_cast<FPClassTest>(ClassVal);
+ MaskIfTrue = TestedMask;
+ MaskIfFalse = ~TestedMask;
}
if (TestedValue == LHS) {
// match !isnan(x) ? x : y
- FilterLHS = TestedMask;
- } else if (TestedValue == RHS) {
+ FilterLHS = MaskIfTrue;
+ } else if (TestedValue == RHS) { // && IsExactClass
// match !isnan(x) ? y : x
- FilterRHS = ~TestedMask;
+ FilterRHS = MaskIfFalse;
}
KnownFPClass Known2;
diff --git a/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll b/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll
index 396b8c84fc898c9..212a8eb2f2451f7 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll
@@ -11,7 +11,7 @@ declare void @llvm.assume(i1 noundef)
; can't be +inf
define float @clamp_is_ogt_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ogt_1_to_1(
+; CHECK-LABEL: define nofpclass(pinf) float @clamp_is_ogt_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: [[IS_OGT_1:%.*]] = fcmp ogt float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OGT_1]], float 1.000000e+00, float [[ARG]]
@@ -23,7 +23,7 @@ define float @clamp_is_ogt_1_to_1(float %arg) {
}
define float @clamp_is_ogt_1_to_1_commute(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ogt_1_to_1_commute(
+; CHECK-LABEL: define nofpclass(pinf) float @clamp_is_ogt_1_to_1_commute(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_ULE_1:%.*]] = fcmp ule float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ULE_1]], float [[ARG]], float 1.000000e+00
@@ -36,7 +36,7 @@ define float @clamp_is_ogt_1_to_1_commute(float %arg) {
; can't be +inf or nan
define float @clamp_is_ugt_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ugt_1_to_1(
+; CHECK-LABEL: define nofpclass(nan pinf) float @clamp_is_ugt_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_UGT_1:%.*]] = fcmp ugt float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_UGT_1]], float 1.000000e+00, float [[ARG]]
@@ -49,7 +49,7 @@ define float @clamp_is_ugt_1_to_1(float %arg) {
; can't be +inf or nan
define float @clamp_is_ugt_1_to_1_commute(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ugt_1_to_1_commute(
+; CHECK-LABEL: define nofpclass(nan pinf) float @clamp_is_ugt_1_to_1_commute(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_OLE_1:%.*]] = fcmp ole float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OLE_1]], float [[ARG]], float 1.000000e+00
@@ -62,7 +62,7 @@ define float @clamp_is_ugt_1_to_1_commute(float %arg) {
; can't be +inf
define float @clamp_is_oge_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_oge_1_to_1(
+; CHECK-LABEL: define nofpclass(pinf) float @clamp_is_oge_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_OGE_1:%.*]] = fcmp oge float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OGE_1]], float 1.000000e+00, float [[ARG]]
@@ -74,7 +74,7 @@ define float @clamp_is_oge_1_to_1(float %arg) {
}
define float @clamp_is_oge_1_to_1_commute(float %arg) {
-; CHECK-LABEL: define float @clamp_is_oge_1_to_1_commute(
+; CHECK-LABEL: define nofpclass(pinf) float @clamp_is_oge_1_to_1_commute(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_ULT_1:%.*]] = fcmp ult float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ULT_1]], float [[ARG]], float 1.000000e+00
@@ -87,7 +87,7 @@ define float @clamp_is_oge_1_to_1_commute(float %arg) {
; can't be +inf or nan
define float @clamp_is_uge_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_uge_1_to_1(
+; CHECK-LABEL: define nofpclass(nan pinf) float @clamp_is_uge_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_UGT_1:%.*]] = fcmp uge float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_UGT_1]], float 1.000000e+00, float [[ARG]]
@@ -100,7 +100,7 @@ define float @clamp_is_uge_1_to_1(float %arg) {
; can't be negative, zero, or denormal
define float @clamp_is_olt_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_olt_1_to_1(
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @clamp_is_olt_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_OLT_1:%.*]] = fcmp olt float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OLT_1]], float 1.000000e+00, float [[ARG]]
@@ -113,7 +113,7 @@ define float @clamp_is_olt_1_to_1(float %arg) {
; can't be negative, zero, or denormal
define float @clamp_is_olt_1_to_1_commute(float %arg) {
-; CHECK-LABEL: define float @clamp_is_olt_1_to_1_commute(
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @clamp_is_olt_1_to_1_commute(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_UGE_1:%.*]] = fcmp uge float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_UGE_1]], float [[ARG]], float 1.000000e+00
@@ -126,7 +126,7 @@ define float @clamp_is_olt_1_to_1_commute(float %arg) {
; can't be negative or zero, nan or denormal
define float @clamp_is_ult_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ult_1_to_1(
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @clamp_is_ult_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_ULT_1:%.*]] = fcmp ult float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ULT_1]], float 1.000000e+00, float [[ARG]]
@@ -139,7 +139,7 @@ define float @clamp_is_ult_1_to_1(float %arg) {
; can't be negative or zero, nan or denormal
define float @clamp_is_ult_1_to_1_commute(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ult_1_to_1_commute(
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @clamp_is_ult_1_to_1_commute(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_OGE_1:%.*]] = fcmp oge float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OGE_1]], float [[ARG]], float 1.000000e+00
@@ -152,7 +152,7 @@ define float @clamp_is_ult_1_to_1_commute(float %arg) {
; can't be negative, zero or denormal
define float @clamp_is_ole_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ole_1_to_1(
+; CHECK-LABEL: define nofpclass(ninf zero sub nnorm) float @clamp_is_ole_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_OLE_1:%.*]] = fcmp ole float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_OLE_1]], float 1.000000e+00, float [[ARG]]
@@ -165,7 +165,7 @@ define float @clamp_is_ole_1_to_1(float %arg) {
; can't be negative or zero, nan or denormal
define float @clamp_is_ule_1_to_1(float %arg) {
-; CHECK-LABEL: define float @clamp_is_ule_1_to_1(
+; CHECK-LABEL: define nofpclass(nan ninf zero sub nnorm) float @clamp_is_ule_1_to_1(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[IS_ULE_1:%.*]] = fcmp ule float [[ARG]], 1.000000e+00
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[IS_ULE_1]], float 1.000000e+00, float [[ARG]]
@@ -178,7 +178,7 @@ define float @clamp_is_ule_1_to_1(float %arg) {
; can't be negative or denormal
define float @clamp_is_olt_1_to_0(float %arg) {
-; CHECK-LABEL: define float @clamp_is_olt_1_to_0(
+; CHECK-LABEL: define nofpclass(ninf nzero sub nnorm) float @clamp_is_olt_1_to_0(
; CHECK-SAME: float [[ARG:%.*]]) #[[ATTR2]] {
; ...
<truncated>
</pre>
</details>
https://github.com/llvm/llvm-project/pull/66505
More information about the llvm-commits
mailing list