[llvm] d1dc3e1 - Revert "ValueTracking: Delete body of isKnownNeverInfinity"
Alina Sbirlea via llvm-commits
llvm-commits at lists.llvm.org
Thu May 18 23:32:22 PDT 2023
Author: Alina Sbirlea
Date: 2023-05-18T23:31:51-07:00
New Revision: d1dc3e13a791fe1b99a341406b5dafec64750cb1
URL: https://github.com/llvm/llvm-project/commit/d1dc3e13a791fe1b99a341406b5dafec64750cb1
DIFF: https://github.com/llvm/llvm-project/commit/d1dc3e13a791fe1b99a341406b5dafec64750cb1.diff
LOG: Revert "ValueTracking: Delete body of isKnownNeverInfinity"
This reverts commit 73925ef8b0eacc6792f0e3ea21a3e6d51f5ee8b0.
Introduces test failures, mismatch inf/nan
Added:
Modified:
llvm/include/llvm/Analysis/ValueTracking.h
llvm/lib/Analysis/ValueTracking.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index b6e7ac3ed1eef..b6ff2ef4dd9a5 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -461,18 +461,13 @@ bool CannotBeOrderedLessThanZero(const Value *V, const DataLayout &DL,
/// Return true if the floating-point scalar value is not an infinity or if
/// the floating-point vector value has no infinities. Return false if a value
/// could ever be infinity.
-inline bool isKnownNeverInfinity(const Value *V, const DataLayout &DL,
- const TargetLibraryInfo *TLI = nullptr,
- unsigned Depth = 0,
- AssumptionCache *AC = nullptr,
- const Instruction *CtxI = nullptr,
- const DominatorTree *DT = nullptr,
- OptimizationRemarkEmitter *ORE = nullptr,
- bool UseInstrInfo = true) {
- KnownFPClass Known = computeKnownFPClass(V, DL, fcInf, Depth, TLI, AC, CtxI,
- DT, ORE, UseInstrInfo);
- return Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfinity(const Value *V, const DataLayout &DL,
+ const TargetLibraryInfo *TLI = nullptr,
+ unsigned Depth = 0, AssumptionCache *AC = nullptr,
+ const Instruction *CtxI = nullptr,
+ const DominatorTree *DT = nullptr,
+ OptimizationRemarkEmitter *ORE = nullptr,
+ bool UseInstrInfo = true);
/// Return true if the floating-point value can never contain a NaN or infinity.
inline bool isKnownNeverInfOrNaN(
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6a008c2737945..4cbba93b50057 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4037,6 +4037,150 @@ bool llvm::CannotBeOrderedLessThanZero(const Value *V, const DataLayout &DL,
return cannotBeOrderedLessThanZeroImpl(V, DL, TLI, false, 0);
}
+bool llvm::isKnownNeverInfinity(const Value *V, const DataLayout &DL,
+ const TargetLibraryInfo *TLI, unsigned Depth,
+ AssumptionCache *AC, const Instruction *CtxI,
+ const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE,
+ bool UseInstrInfo) {
+ assert(V->getType()->isFPOrFPVectorTy() && "Querying for Inf on non-FP type");
+
+ // If we're told that infinities won't happen, assume they won't.
+ if (auto *FPMathOp = dyn_cast<FPMathOperator>(V))
+ if (FPMathOp->hasNoInfs())
+ return true;
+
+ if (const auto *Arg = dyn_cast<Argument>(V)) {
+ if ((Arg->getNoFPClass() & fcInf) == fcInf)
+ return true;
+ }
+
+ // TODO: Use fpclass like API for isKnown queries and distinguish +inf from
+ // -inf.
+ if (const auto *CB = dyn_cast<CallBase>(V)) {
+ if ((CB->getRetNoFPClass() & fcInf) == fcInf)
+ return true;
+ }
+
+ // Handle scalar constants.
+ if (auto *CFP = dyn_cast<ConstantFP>(V))
+ return !CFP->isInfinity();
+
+ if (Depth == MaxAnalysisRecursionDepth)
+ return false;
+
+ if (auto *Inst = dyn_cast<Instruction>(V)) {
+ switch (Inst->getOpcode()) {
+ case Instruction::Select: {
+ return isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(2), DL, TLI, Depth + 1);
+ }
+ case Instruction::SIToFP:
+ case Instruction::UIToFP: {
+ // Get width of largest magnitude integer (remove a bit if signed).
+ // This still works for a signed minimum value because the largest FP
+ // value is scaled by some fraction close to 2.0 (1.0 + 0.xxxx).
+ int IntSize = Inst->getOperand(0)->getType()->getScalarSizeInBits();
+ if (Inst->getOpcode() == Instruction::SIToFP)
+ --IntSize;
+
+ // If the exponent of the largest finite FP value can hold the largest
+ // integer, the result of the cast must be finite.
+ Type *FPTy = Inst->getType()->getScalarType();
+ return ilogb(APFloat::getLargest(FPTy->getFltSemantics())) >= IntSize;
+ }
+ case Instruction::FNeg:
+ case Instruction::FPExt: {
+ // Peek through to source op. If it is not infinity, this is not infinity.
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
+ }
+ case Instruction::FPTrunc: {
+ // Need a range check.
+ return false;
+ }
+ default:
+ break;
+ }
+
+ if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::sin:
+ case Intrinsic::cos:
+ // Return NaN on infinite inputs.
+ return true;
+ case Intrinsic::fabs:
+ case Intrinsic::sqrt:
+ case Intrinsic::canonicalize:
+ case Intrinsic::copysign:
+ case Intrinsic::arithmetic_fence:
+ case Intrinsic::trunc:
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
+ case Intrinsic::floor:
+ case Intrinsic::ceil:
+ case Intrinsic::rint:
+ case Intrinsic::nearbyint:
+ case Intrinsic::round:
+ case Intrinsic::roundeven:
+ // PPC_FP128 is a special case.
+ if (V->getType()->isMultiUnitFPType())
+ return false;
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1);
+ case Intrinsic::fptrunc_round:
+ // Requires knowing the value range.
+ return false;
+ case Intrinsic::minnum:
+ case Intrinsic::maxnum:
+ case Intrinsic::minimum:
+ case Intrinsic::maximum:
+ return isKnownNeverInfinity(Inst->getOperand(0), DL, TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(1), DL, TLI, Depth + 1);
+ case Intrinsic::log:
+ case Intrinsic::log10:
+ case Intrinsic::log2:
+ // log(+inf) -> +inf
+ // log([+-]0.0) -> -inf
+ // log(-inf) -> nan
+ // log(-x) -> nan
+ // TODO: We lack API to check the == 0 case.
+ return false;
+ case Intrinsic::exp:
+ case Intrinsic::exp2:
+ case Intrinsic::pow:
+ case Intrinsic::powi:
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd:
+ // These can return infinities on overflow cases, so it's hard to prove
+ // anything about it.
+ return false;
+ default:
+ break;
+ }
+ }
+ }
+
+ // try to handle fixed width vector constants
+ auto *VFVTy = dyn_cast<FixedVectorType>(V->getType());
+ if (VFVTy && isa<Constant>(V)) {
+ // For vectors, verify that each element is not infinity.
+ unsigned NumElts = VFVTy->getNumElements();
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *Elt = cast<Constant>(V)->getAggregateElement(i);
+ if (!Elt)
+ return false;
+ if (isa<UndefValue>(Elt))
+ continue;
+ auto *CElt = dyn_cast<ConstantFP>(Elt);
+ if (!CElt || CElt->isInfinity())
+ return false;
+ }
+ // All elements were confirmed non-infinity or undefined.
+ return true;
+ }
+
+ // was not able to prove that V never contains infinity
+ return false;
+}
+
bool llvm::SignBitMustBeZero(const Value *V, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
return cannotBeOrderedLessThanZeroImpl(V, DL, TLI, true, 0);
More information about the llvm-commits
mailing list