[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