Skip to content

Commit 50e80e0

Browse files
dtcxzywarsenm
andauthored
[ValueTracking] Merge cannotBeOrderedLessThanZeroImpl into computeKnownFPClass (#76360)
This patch merges the logic of `cannotBeOrderedLessThanZeroImpl` into `computeKnownFPClass` to improve the signbit inference. --------- Co-authored-by: Matt Arsenault <[email protected]>
1 parent 942cc9a commit 50e80e0

File tree

8 files changed

+140
-242
lines changed

8 files changed

+140
-242
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,12 @@ struct KnownFPClass {
358358

359359
void knownNot(FPClassTest RuleOut) {
360360
KnownFPClasses = KnownFPClasses & ~RuleOut;
361+
if (isKnownNever(fcNan) && !SignBit) {
362+
if (isKnownNever(fcNegative))
363+
SignBit = false;
364+
else if (isKnownNever(fcPositive))
365+
SignBit = true;
366+
}
361367
}
362368

363369
void fneg() {
@@ -393,6 +399,12 @@ struct KnownFPClass {
393399
SignBit = false;
394400
}
395401

402+
/// Assume the sign bit is one.
403+
void signBitMustBeOne() {
404+
KnownFPClasses &= (fcNegative | fcNan);
405+
SignBit = true;
406+
}
407+
396408
void copysign(const KnownFPClass &Sign) {
397409
// Don't know anything about the sign of the source. Expand the possible set
398410
// to its opposite sign pair.
@@ -579,15 +591,18 @@ inline bool isKnownNeverNaN(const Value *V, const DataLayout &DL,
579591
return Known.isKnownNeverNaN();
580592
}
581593

582-
/// Return true if we can prove that the specified FP value's sign bit is 0.
583-
///
584-
/// NaN --> true/false (depending on the NaN's sign bit)
585-
/// +0 --> true
586-
/// -0 --> false
587-
/// x > +0 --> true
588-
/// x < -0 --> false
589-
bool SignBitMustBeZero(const Value *V, const DataLayout &DL,
590-
const TargetLibraryInfo *TLI);
594+
/// Return false if we can prove that the specified FP value's sign bit is 0.
595+
/// Return true if we can prove that the specified FP value's sign bit is 1.
596+
/// Otherwise return std::nullopt.
597+
inline std::optional<bool> computeKnownFPSignBit(
598+
const Value *V, const DataLayout &DL,
599+
const TargetLibraryInfo *TLI = nullptr, unsigned Depth = 0,
600+
AssumptionCache *AC = nullptr, const Instruction *CtxI = nullptr,
601+
const DominatorTree *DT = nullptr, bool UseInstrInfo = true) {
602+
KnownFPClass Known = computeKnownFPClass(V, DL, fcAllFlags, Depth, TLI, AC,
603+
CtxI, DT, UseInstrInfo);
604+
return Known.SignBit;
605+
}
591606

592607
/// If the specified value can be set by repeating the same byte in memory,
593608
/// return the i8 value that it is represented with. This is true for all i8

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5762,9 +5762,9 @@ static Value *simplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
57625762
return ConstantFP::getZero(Op0->getType());
57635763

57645764
// +normal number * (-)0.0 --> (-)0.0
5765-
if (isKnownNeverInfOrNaN(Op0, Q.DL, Q.TLI, 0, Q.AC, Q.CxtI, Q.DT) &&
5766-
// TODO: Check SignBit from computeKnownFPClass when it's more complete.
5767-
SignBitMustBeZero(Op0, Q.DL, Q.TLI))
5765+
KnownFPClass Known = computeKnownFPClass(
5766+
Op0, FMF, Q.DL, fcInf | fcNan, /*Depth=*/0, Q.TLI, Q.AC, Q.CxtI, Q.DT);
5767+
if (Known.SignBit == false && Known.isKnownNever(fcInf | fcNan))
57685768
return Op1;
57695769
}
57705770

@@ -6217,7 +6217,8 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
62176217
Value *X;
62186218
switch (IID) {
62196219
case Intrinsic::fabs:
6220-
if (SignBitMustBeZero(Op0, Q.DL, Q.TLI))
6220+
if (computeKnownFPSignBit(Op0, Q.DL, Q.TLI, /*Depth=*/0, Q.AC, Q.CxtI,
6221+
Q.DT) == false)
62216222
return Op0;
62226223
break;
62236224
case Intrinsic::bswap:

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 39 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -3706,205 +3706,6 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(const CallBase &CB,
37063706
return Intrinsic::not_intrinsic;
37073707
}
37083708

3709-
/// Deprecated, use computeKnownFPClass instead.
3710-
///
3711-
/// If \p SignBitOnly is true, test for a known 0 sign bit rather than a
3712-
/// standard ordered compare. e.g. make -0.0 olt 0.0 be true because of the sign
3713-
/// bit despite comparing equal.
3714-
static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
3715-
const DataLayout &DL,
3716-
const TargetLibraryInfo *TLI,
3717-
bool SignBitOnly, unsigned Depth) {
3718-
// TODO: This function does not do the right thing when SignBitOnly is true
3719-
// and we're lowering to a hypothetical IEEE 754-compliant-but-evil platform
3720-
// which flips the sign bits of NaNs. See
3721-
// https://llvm.org/bugs/show_bug.cgi?id=31702.
3722-
3723-
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
3724-
return !CFP->getValueAPF().isNegative() ||
3725-
(!SignBitOnly && CFP->getValueAPF().isZero());
3726-
}
3727-
3728-
// Handle vector of constants.
3729-
if (auto *CV = dyn_cast<Constant>(V)) {
3730-
if (auto *CVFVTy = dyn_cast<FixedVectorType>(CV->getType())) {
3731-
unsigned NumElts = CVFVTy->getNumElements();
3732-
for (unsigned i = 0; i != NumElts; ++i) {
3733-
auto *CFP = dyn_cast_or_null<ConstantFP>(CV->getAggregateElement(i));
3734-
if (!CFP)
3735-
return false;
3736-
if (CFP->getValueAPF().isNegative() &&
3737-
(SignBitOnly || !CFP->getValueAPF().isZero()))
3738-
return false;
3739-
}
3740-
3741-
// All non-negative ConstantFPs.
3742-
return true;
3743-
}
3744-
}
3745-
3746-
if (Depth == MaxAnalysisRecursionDepth)
3747-
return false;
3748-
3749-
const Operator *I = dyn_cast<Operator>(V);
3750-
if (!I)
3751-
return false;
3752-
3753-
switch (I->getOpcode()) {
3754-
default:
3755-
break;
3756-
// Unsigned integers are always nonnegative.
3757-
case Instruction::UIToFP:
3758-
return true;
3759-
case Instruction::FDiv:
3760-
// X / X is always exactly 1.0 or a NaN.
3761-
if (I->getOperand(0) == I->getOperand(1) &&
3762-
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
3763-
return true;
3764-
3765-
// Set SignBitOnly for RHS, because X / -0.0 is -Inf (or NaN).
3766-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3767-
SignBitOnly, Depth + 1) &&
3768-
cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
3769-
/*SignBitOnly*/ true, Depth + 1);
3770-
case Instruction::FMul:
3771-
// X * X is always non-negative or a NaN.
3772-
if (I->getOperand(0) == I->getOperand(1) &&
3773-
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
3774-
return true;
3775-
3776-
[[fallthrough]];
3777-
case Instruction::FAdd:
3778-
case Instruction::FRem:
3779-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3780-
SignBitOnly, Depth + 1) &&
3781-
cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
3782-
SignBitOnly, Depth + 1);
3783-
case Instruction::Select:
3784-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
3785-
SignBitOnly, Depth + 1) &&
3786-
cannotBeOrderedLessThanZeroImpl(I->getOperand(2), DL, TLI,
3787-
SignBitOnly, Depth + 1);
3788-
case Instruction::FPExt:
3789-
case Instruction::FPTrunc:
3790-
// Widening/narrowing never change sign.
3791-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3792-
SignBitOnly, Depth + 1);
3793-
case Instruction::ExtractElement:
3794-
// Look through extract element. At the moment we keep this simple and skip
3795-
// tracking the specific element. But at least we might find information
3796-
// valid for all elements of the vector.
3797-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3798-
SignBitOnly, Depth + 1);
3799-
case Instruction::Call:
3800-
const auto *CI = cast<CallInst>(I);
3801-
Intrinsic::ID IID = getIntrinsicForCallSite(*CI, TLI);
3802-
switch (IID) {
3803-
default:
3804-
break;
3805-
case Intrinsic::canonicalize:
3806-
case Intrinsic::arithmetic_fence:
3807-
case Intrinsic::floor:
3808-
case Intrinsic::ceil:
3809-
case Intrinsic::trunc:
3810-
case Intrinsic::rint:
3811-
case Intrinsic::nearbyint:
3812-
case Intrinsic::round:
3813-
case Intrinsic::roundeven:
3814-
case Intrinsic::fptrunc_round:
3815-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3816-
SignBitOnly, Depth + 1);
3817-
case Intrinsic::maxnum: {
3818-
Value *V0 = I->getOperand(0), *V1 = I->getOperand(1);
3819-
auto isPositiveNum = [&](Value *V) {
3820-
if (SignBitOnly) {
3821-
// With SignBitOnly, this is tricky because the result of
3822-
// maxnum(+0.0, -0.0) is unspecified. Just check if the operand is
3823-
// a constant strictly greater than 0.0.
3824-
const APFloat *C;
3825-
return match(V, m_APFloat(C)) &&
3826-
*C > APFloat::getZero(C->getSemantics());
3827-
}
3828-
3829-
// -0.0 compares equal to 0.0, so if this operand is at least -0.0,
3830-
// maxnum can't be ordered-less-than-zero.
3831-
return isKnownNeverNaN(V, DL, TLI) &&
3832-
cannotBeOrderedLessThanZeroImpl(V, DL, TLI, false, Depth + 1);
3833-
};
3834-
3835-
// TODO: This could be improved. We could also check that neither operand
3836-
// has its sign bit set (and at least 1 is not-NAN?).
3837-
return isPositiveNum(V0) || isPositiveNum(V1);
3838-
}
3839-
3840-
case Intrinsic::maximum:
3841-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3842-
SignBitOnly, Depth + 1) ||
3843-
cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
3844-
SignBitOnly, Depth + 1);
3845-
case Intrinsic::minnum:
3846-
case Intrinsic::minimum:
3847-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3848-
SignBitOnly, Depth + 1) &&
3849-
cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI,
3850-
SignBitOnly, Depth + 1);
3851-
case Intrinsic::exp:
3852-
case Intrinsic::exp2:
3853-
case Intrinsic::fabs:
3854-
return true;
3855-
case Intrinsic::copysign:
3856-
// Only the sign operand matters.
3857-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), DL, TLI, true,
3858-
Depth + 1);
3859-
case Intrinsic::sqrt:
3860-
// sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0.
3861-
if (!SignBitOnly)
3862-
return true;
3863-
return CI->hasNoNaNs() &&
3864-
(CI->hasNoSignedZeros() ||
3865-
cannotBeNegativeZero(CI->getOperand(0), DL, TLI));
3866-
3867-
case Intrinsic::powi:
3868-
if (ConstantInt *Exponent = dyn_cast<ConstantInt>(I->getOperand(1))) {
3869-
// powi(x,n) is non-negative if n is even.
3870-
if (Exponent->getBitWidth() <= 64 && Exponent->getSExtValue() % 2u == 0)
3871-
return true;
3872-
}
3873-
// TODO: This is not correct. Given that exp is an integer, here are the
3874-
// ways that pow can return a negative value:
3875-
//
3876-
// pow(x, exp) --> negative if exp is odd and x is negative.
3877-
// pow(-0, exp) --> -inf if exp is negative odd.
3878-
// pow(-0, exp) --> -0 if exp is positive odd.
3879-
// pow(-inf, exp) --> -0 if exp is negative odd.
3880-
// pow(-inf, exp) --> -inf if exp is positive odd.
3881-
//
3882-
// Therefore, if !SignBitOnly, we can return true if x >= +0 or x is NaN,
3883-
// but we must return false if x == -0. Unfortunately we do not currently
3884-
// have a way of expressing this constraint. See details in
3885-
// https://llvm.org/bugs/show_bug.cgi?id=31702.
3886-
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), DL, TLI,
3887-
SignBitOnly, Depth + 1);
3888-
3889-
case Intrinsic::fma:
3890-
case Intrinsic::fmuladd:
3891-
// x*x+y is non-negative if y is non-negative.
3892-
return I->getOperand(0) == I->getOperand(1) &&
3893-
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()) &&
3894-
cannotBeOrderedLessThanZeroImpl(I->getOperand(2), DL, TLI,
3895-
SignBitOnly, Depth + 1);
3896-
}
3897-
break;
3898-
}
3899-
return false;
3900-
}
3901-
3902-
bool llvm::SignBitMustBeZero(const Value *V, const DataLayout &DL,
3903-
const TargetLibraryInfo *TLI) {
3904-
// FIXME: Use computeKnownFPClass and pass all arguments
3905-
return cannotBeOrderedLessThanZeroImpl(V, DL, TLI, true, 0);
3906-
}
3907-
39083709
/// Return true if it's possible to assume IEEE treatment of input denormals in
39093710
/// \p F for \p Val.
39103711
static bool inputDenormalIsIEEE(const Function &F, const Type *Ty) {
@@ -4489,7 +4290,6 @@ static void computeKnownFPClassForFPTrunc(const Operator *Op,
44894290
// Infinity needs a range check.
44904291
}
44914292

4492-
// TODO: Merge implementation of cannotBeOrderedLessThanZero into here.
44934293
void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
44944294
FPClassTest InterestedClasses, KnownFPClass &Known,
44954295
unsigned Depth, const SimplifyQuery &Q) {
@@ -4514,6 +4314,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
45144314
const Constant *CV = dyn_cast<Constant>(V);
45154315
if (VFVTy && CV) {
45164316
Known.KnownFPClasses = fcNone;
4317+
bool SignBitAllZero = true;
4318+
bool SignBitAllOne = true;
45174319

45184320
// For vectors, verify that each element is not NaN.
45194321
unsigned NumElts = VFVTy->getNumElements();
@@ -4531,10 +4333,15 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
45314333
return;
45324334
}
45334335

4534-
KnownFPClass KnownElt{CElt->getValueAPF().classify(), CElt->isNegative()};
4535-
Known |= KnownElt;
4336+
const APFloat &C = CElt->getValueAPF();
4337+
Known.KnownFPClasses |= C.classify();
4338+
if (C.isNegative())
4339+
SignBitAllZero = false;
4340+
else
4341+
SignBitAllOne = false;
45364342
}
4537-
4343+
if (SignBitAllOne != SignBitAllZero)
4344+
Known.SignBit = SignBitAllOne;
45384345
return;
45394346
}
45404347

@@ -4673,7 +4480,6 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
46734480
computeKnownFPClass(II->getArgOperand(2), DemandedElts, InterestedClasses,
46744481
KnownAddend, Depth + 1, Q);
46754482

4676-
// TODO: Known sign bit with no nans
46774483
if (KnownAddend.cannotBeOrderedLessThanZero())
46784484
Known.knownNot(fcNegative);
46794485
break;
@@ -4707,7 +4513,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
47074513
(F && KnownSrc.isKnownNeverLogicalNegZero(*F, II->getType()))) {
47084514
Known.knownNot(fcNegZero);
47094515
if (KnownSrc.isKnownNeverNaN())
4710-
Known.SignBit = false;
4516+
Known.signBitMustBeZero();
47114517
}
47124518

47134519
break;
@@ -4777,7 +4583,6 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
47774583
// subtargets on AMDGPU the min/max instructions would not flush the
47784584
// output and return the original value.
47794585
//
4780-
// TODO: This could be refined based on the sign
47814586
if ((Known.KnownFPClasses & fcZero) != fcNone &&
47824587
!Known.isKnownNeverSubnormal()) {
47834588
const Function *Parent = II->getFunction();
@@ -4790,6 +4595,26 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
47904595
Known.KnownFPClasses |= fcZero;
47914596
}
47924597

4598+
if (Known.isKnownNeverNaN()) {
4599+
if (KnownLHS.SignBit && KnownRHS.SignBit &&
4600+
*KnownLHS.SignBit == *KnownRHS.SignBit) {
4601+
if (*KnownLHS.SignBit)
4602+
Known.signBitMustBeOne();
4603+
else
4604+
Known.signBitMustBeZero();
4605+
} else if ((IID == Intrinsic::maximum || IID == Intrinsic::minimum) ||
4606+
((KnownLHS.isKnownNeverNegZero() ||
4607+
KnownRHS.isKnownNeverPosZero()) &&
4608+
(KnownLHS.isKnownNeverPosZero() ||
4609+
KnownRHS.isKnownNeverNegZero()))) {
4610+
if ((IID == Intrinsic::maximum || IID == Intrinsic::maxnum) &&
4611+
(KnownLHS.SignBit == false || KnownRHS.SignBit == false))
4612+
Known.signBitMustBeZero();
4613+
else if ((IID == Intrinsic::minimum || IID == Intrinsic::minnum) &&
4614+
(KnownLHS.SignBit == true || KnownRHS.SignBit == true))
4615+
Known.signBitMustBeOne();
4616+
}
4617+
}
47934618
break;
47944619
}
47954620
case Intrinsic::canonicalize: {
@@ -4889,7 +4714,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
48894714
KnownSrc, Depth + 1, Q);
48904715
if (KnownSrc.isKnownNeverNaN()) {
48914716
Known.knownNot(fcNan);
4892-
Known.SignBit = false;
4717+
Known.signBitMustBeZero();
48934718
}
48944719

48954720
break;
@@ -5139,6 +4964,13 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
51394964
if (!KnownLHS.isKnownNeverNaN())
51404965
break;
51414966

4967+
if (KnownLHS.SignBit && KnownRHS.SignBit) {
4968+
if (*KnownLHS.SignBit == *KnownRHS.SignBit)
4969+
Known.signBitMustBeZero();
4970+
else
4971+
Known.signBitMustBeOne();
4972+
}
4973+
51424974
// If 0 * +/-inf produces NaN.
51434975
if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) {
51444976
Known.knownNot(fcNan);

0 commit comments

Comments
 (0)