[llvm] 98b1072 - [ValueTracking] Extract isKnownNonZeroFromOperator() (NFC)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 21 06:51:37 PDT 2023


Author: Nikita Popov
Date: 2023-07-21T15:51:29+02:00
New Revision: 98b10727b101433b2d68ce4c72a91f49a5bb8486

URL: https://github.com/llvm/llvm-project/commit/98b10727b101433b2d68ce4c72a91f49a5bb8486
DIFF: https://github.com/llvm/llvm-project/commit/98b10727b101433b2d68ce4c72a91f49a5bb8486.diff

LOG: [ValueTracking] Extract isKnownNonZeroFromOperator() (NFC)

Split off the primary part of the isKnownNonZero() implementation,
in the same way it is done for computeKnownBits(). This makes it
easier to reorder different parts of isKnownNonZero().

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8940c2c344b1ca..62f7c542a11316 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2449,122 +2449,10 @@ static bool isNonZeroShift(const Operator *I, const APInt &DemandedElts,
   return false;
 }
 
-/// Return true if the given value is known to be non-zero when defined. For
-/// vectors, return true if every demanded element is known to be non-zero when
-/// defined. For pointers, if the context instruction and dominator tree are
-/// specified, perform context-sensitive analysis and return true if the
-/// pointer couldn't possibly be null at the specified instruction.
-/// Supports values with integer or pointer type and vectors of integers.
-bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
-                    const SimplifyQuery &Q) {
-
-#ifndef NDEBUG
-  Type *Ty = V->getType();
-  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
-
-  if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
-    assert(
-        FVTy->getNumElements() == DemandedElts.getBitWidth() &&
-        "DemandedElt width should equal the fixed vector number of elements");
-  } else {
-    assert(DemandedElts == APInt(1, 1) &&
-           "DemandedElt width should be 1 for scalars");
-  }
-#endif
-
-  if (auto *C = dyn_cast<Constant>(V)) {
-    if (C->isNullValue())
-      return false;
-    if (isa<ConstantInt>(C))
-      // Must be non-zero due to null test above.
-      return true;
-
-    // For constant vectors, check that all elements are undefined or known
-    // non-zero to determine that the whole vector is known non-zero.
-    if (auto *VecTy = dyn_cast<FixedVectorType>(C->getType())) {
-      for (unsigned i = 0, e = VecTy->getNumElements(); i != e; ++i) {
-        if (!DemandedElts[i])
-          continue;
-        Constant *Elt = C->getAggregateElement(i);
-        if (!Elt || Elt->isNullValue())
-          return false;
-        if (!isa<UndefValue>(Elt) && !isa<ConstantInt>(Elt))
-          return false;
-      }
-      return true;
-    }
-
-    // A global variable in address space 0 is non null unless extern weak
-    // or an absolute symbol reference. Other address spaces may have null as a
-    // valid address for a global, so we can't assume anything.
-    if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
-      if (!GV->isAbsoluteSymbolRef() && !GV->hasExternalWeakLinkage() &&
-          GV->getType()->getAddressSpace() == 0)
-        return true;
-    }
-
-    // For constant expressions, fall through to the Operator code below.
-    if (!isa<ConstantExpr>(V))
-      return false;
-  }
-
-  if (auto *I = dyn_cast<Instruction>(V)) {
-    if (MDNode *Ranges = Q.IIQ.getMetadata(I, LLVMContext::MD_range)) {
-      // If the possible ranges don't contain zero, then the value is
-      // definitely non-zero.
-      if (auto *Ty = dyn_cast<IntegerType>(V->getType())) {
-        const APInt ZeroValue(Ty->getBitWidth(), 0);
-        if (rangeMetadataExcludesValue(Ranges, ZeroValue))
-          return true;
-      }
-    }
-  }
-
-  if (!isa<Constant>(V) && isKnownNonZeroFromAssume(V, Q))
-    return true;
-
-  // Some of the tests below are recursive, so bail out if we hit the limit.
-  if (Depth++ >= MaxAnalysisRecursionDepth)
-    return false;
-
-  // Check for pointer simplifications.
-
-  if (PointerType *PtrTy = dyn_cast<PointerType>(V->getType())) {
-    // Alloca never returns null, malloc might.
-    if (isa<AllocaInst>(V) && PtrTy->getAddressSpace() == 0)
-      return true;
-
-    // A byval, inalloca may not be null in a non-default addres space. A
-    // nonnull argument is assumed never 0.
-    if (const Argument *A = dyn_cast<Argument>(V)) {
-      if (((A->hasPassPointeeByValueCopyAttr() &&
-            !NullPointerIsDefined(A->getParent(), PtrTy->getAddressSpace())) ||
-           A->hasNonNullAttr()))
-        return true;
-    }
-
-    // A Load tagged with nonnull metadata is never null.
-    if (const LoadInst *LI = dyn_cast<LoadInst>(V))
-      if (Q.IIQ.getMetadata(LI, LLVMContext::MD_nonnull))
-        return true;
-
-    if (const auto *Call = dyn_cast<CallBase>(V)) {
-      if (Call->isReturnNonNull())
-        return true;
-      if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true))
-        return isKnownNonZero(RP, Depth, Q);
-    }
-  }
-
-  if (!isa<Constant>(V) &&
-      isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
-    return true;
-
-  const Operator *I = dyn_cast<Operator>(V);
-  if (!I)
-    return false;
-
-  unsigned BitWidth = getBitWidth(V->getType()->getScalarType(), Q.DL);
+static bool isKnownNonZeroFromOperator(const Operator *I,
+                                       const APInt &DemandedElts,
+                                       unsigned Depth, const SimplifyQuery &Q) {
+  unsigned BitWidth = getBitWidth(I->getType()->getScalarType(), Q.DL);
   switch (I->getOpcode()) {
   case Instruction::GetElementPtr:
     if (I->getType()->isPointerTy())
@@ -2634,7 +2522,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
 
   case Instruction::Shl: {
     // shl nsw/nuw can't remove any non-zero bits.
-    const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(V);
+    const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(I);
     if (Q.IIQ.hasNoUnsignedWrap(BO) || Q.IIQ.hasNoSignedWrap(BO))
       return isKnownNonZero(I->getOperand(0), Depth, Q);
 
@@ -2650,7 +2538,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
   case Instruction::LShr:
   case Instruction::AShr: {
     // shr exact can only shift out zero bits.
-    const PossiblyExactOperator *BO = cast<PossiblyExactOperator>(V);
+    const PossiblyExactOperator *BO = cast<PossiblyExactOperator>(I);
     if (BO->isExact())
       return isKnownNonZero(I->getOperand(0), Depth, Q);
 
@@ -2689,7 +2577,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
 
     // If Add has nuw wrap flag, then if either X or Y is non-zero the result is
     // non-zero.
-    auto *BO = cast<OverflowingBinaryOperator>(V);
+    auto *BO = cast<OverflowingBinaryOperator>(I);
     if (Q.IIQ.hasNoUnsignedWrap(BO))
       return isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q) ||
              isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
@@ -2700,7 +2588,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
   case Instruction::Mul: {
     // If X and Y are non-zero then so is X * Y as long as the multiplication
     // does not overflow.
-    const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(V);
+    const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(I);
     if (Q.IIQ.hasNoSignedWrap(BO) || Q.IIQ.hasNoUnsignedWrap(BO))
       return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q) &&
              isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q);
@@ -2774,7 +2662,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
     });
   }
   case Instruction::ExtractElement:
-    if (const auto *EEI = dyn_cast<ExtractElementInst>(V)) {
+    if (const auto *EEI = dyn_cast<ExtractElementInst>(I)) {
       const Value *Vec = EEI->getVectorOperand();
       const Value *Idx = EEI->getIndexOperand();
       auto *CIdx = dyn_cast<ConstantInt>(Idx);
@@ -2857,11 +2745,128 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
   }
 
   KnownBits Known(BitWidth);
-  computeKnownBits(V, DemandedElts, Known, Depth, Q);
+  computeKnownBits(I, DemandedElts, Known, Depth, Q);
   return Known.One != 0;
 }
 
-bool isKnownNonZero(const Value* V, unsigned Depth, const SimplifyQuery& Q) {
+/// Return true if the given value is known to be non-zero when defined. For
+/// vectors, return true if every demanded element is known to be non-zero when
+/// defined. For pointers, if the context instruction and dominator tree are
+/// specified, perform context-sensitive analysis and return true if the
+/// pointer couldn't possibly be null at the specified instruction.
+/// Supports values with integer or pointer type and vectors of integers.
+bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
+                    const SimplifyQuery &Q) {
+
+#ifndef NDEBUG
+  Type *Ty = V->getType();
+  assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+
+  if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
+    assert(
+        FVTy->getNumElements() == DemandedElts.getBitWidth() &&
+        "DemandedElt width should equal the fixed vector number of elements");
+  } else {
+    assert(DemandedElts == APInt(1, 1) &&
+           "DemandedElt width should be 1 for scalars");
+  }
+#endif
+
+  if (auto *C = dyn_cast<Constant>(V)) {
+    if (C->isNullValue())
+      return false;
+    if (isa<ConstantInt>(C))
+      // Must be non-zero due to null test above.
+      return true;
+
+    // For constant vectors, check that all elements are undefined or known
+    // non-zero to determine that the whole vector is known non-zero.
+    if (auto *VecTy = dyn_cast<FixedVectorType>(C->getType())) {
+      for (unsigned i = 0, e = VecTy->getNumElements(); i != e; ++i) {
+        if (!DemandedElts[i])
+          continue;
+        Constant *Elt = C->getAggregateElement(i);
+        if (!Elt || Elt->isNullValue())
+          return false;
+        if (!isa<UndefValue>(Elt) && !isa<ConstantInt>(Elt))
+          return false;
+      }
+      return true;
+    }
+
+    // A global variable in address space 0 is non null unless extern weak
+    // or an absolute symbol reference. Other address spaces may have null as a
+    // valid address for a global, so we can't assume anything.
+    if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+      if (!GV->isAbsoluteSymbolRef() && !GV->hasExternalWeakLinkage() &&
+          GV->getType()->getAddressSpace() == 0)
+        return true;
+    }
+
+    // For constant expressions, fall through to the Operator code below.
+    if (!isa<ConstantExpr>(V))
+      return false;
+  }
+
+  if (auto *I = dyn_cast<Instruction>(V)) {
+    if (MDNode *Ranges = Q.IIQ.getMetadata(I, LLVMContext::MD_range)) {
+      // If the possible ranges don't contain zero, then the value is
+      // definitely non-zero.
+      if (auto *Ty = dyn_cast<IntegerType>(V->getType())) {
+        const APInt ZeroValue(Ty->getBitWidth(), 0);
+        if (rangeMetadataExcludesValue(Ranges, ZeroValue))
+          return true;
+      }
+    }
+  }
+
+  if (!isa<Constant>(V) && isKnownNonZeroFromAssume(V, Q))
+    return true;
+
+  // Some of the tests below are recursive, so bail out if we hit the limit.
+  if (Depth++ >= MaxAnalysisRecursionDepth)
+    return false;
+
+  // Check for pointer simplifications.
+
+  if (PointerType *PtrTy = dyn_cast<PointerType>(V->getType())) {
+    // Alloca never returns null, malloc might.
+    if (isa<AllocaInst>(V) && PtrTy->getAddressSpace() == 0)
+      return true;
+
+    // A byval, inalloca may not be null in a non-default addres space. A
+    // nonnull argument is assumed never 0.
+    if (const Argument *A = dyn_cast<Argument>(V)) {
+      if (((A->hasPassPointeeByValueCopyAttr() &&
+            !NullPointerIsDefined(A->getParent(), PtrTy->getAddressSpace())) ||
+           A->hasNonNullAttr()))
+        return true;
+    }
+
+    // A Load tagged with nonnull metadata is never null.
+    if (const LoadInst *LI = dyn_cast<LoadInst>(V))
+      if (Q.IIQ.getMetadata(LI, LLVMContext::MD_nonnull))
+        return true;
+
+    if (const auto *Call = dyn_cast<CallBase>(V)) {
+      if (Call->isReturnNonNull())
+        return true;
+      if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true))
+        return isKnownNonZero(RP, Depth, Q);
+    }
+  }
+
+  if (!isa<Constant>(V) &&
+      isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
+    return true;
+
+  if (const auto *I = dyn_cast<Operator>(V))
+    return isKnownNonZeroFromOperator(I, DemandedElts, Depth, Q);
+
+  return false;
+}
+
+bool isKnownNonZero(const Value *V, unsigned Depth, const SimplifyQuery &Q) {
   auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
   APInt DemandedElts =
       FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);


        


More information about the llvm-commits mailing list