Skip to content

Commit

Permalink
Merge isKnownNonNull into isKnownNonZero
Browse files Browse the repository at this point in the history
It now knows the tricks of both functions.
Also, fix a bug that considered allocas of non-zero address space to be always non null

Differential Revision: https://reviews.llvm.org/D37628

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312869 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
nunoplopes committed Sep 9, 2017
1 parent a22f9f2 commit fe353a0
Show file tree
Hide file tree
Showing 17 changed files with 142 additions and 149 deletions.
13 changes: 0 additions & 13 deletions include/llvm/Analysis/ValueTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,19 +367,6 @@ class Value;
/// operands are not memory dependent.
bool mayBeMemoryDependent(const Instruction &I);

/// Return true if this pointer couldn't possibly be null by its definition.
/// This returns true for allocas, non-extern-weak globals, and byval
/// arguments.
bool isKnownNonNull(const Value *V);

/// Return true if this pointer couldn't possibly be null. 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.
bool isKnownNonNullAt(const Value *V,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr);

/// Return true if it is valid to use the assumptions provided by an
/// assume intrinsic, I, at the point in the control-flow identified by the
/// context instruction, CxtI.
Expand Down
16 changes: 10 additions & 6 deletions lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2063,13 +2063,14 @@ static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
static Constant *
computePointerICmp(const DataLayout &DL, const TargetLibraryInfo *TLI,
const DominatorTree *DT, CmpInst::Predicate Pred,
const Instruction *CxtI, Value *LHS, Value *RHS) {
AssumptionCache *AC, const Instruction *CxtI,
Value *LHS, Value *RHS) {
// First, skip past any trivial no-ops.
LHS = LHS->stripPointerCasts();
RHS = RHS->stripPointerCasts();

// A non-null pointer is not equal to a null pointer.
if (llvm::isKnownNonNull(LHS) && isa<ConstantPointerNull>(RHS) &&
if (llvm::isKnownNonZero(LHS, DL) && isa<ConstantPointerNull>(RHS) &&
(Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE))
return ConstantInt::get(GetCompareTy(LHS),
!CmpInst::isTrueWhenEqual(Pred));
Expand Down Expand Up @@ -2224,9 +2225,11 @@ computePointerICmp(const DataLayout &DL, const TargetLibraryInfo *TLI,
// cannot be elided. We cannot fold malloc comparison to null. Also, the
// dynamic allocation call could be either of the operands.
Value *MI = nullptr;
if (isAllocLikeFn(LHS, TLI) && llvm::isKnownNonNullAt(RHS, CxtI, DT))
if (isAllocLikeFn(LHS, TLI) &&
llvm::isKnownNonZero(RHS, DL, 0, nullptr, CxtI, DT))
MI = LHS;
else if (isAllocLikeFn(RHS, TLI) && llvm::isKnownNonNullAt(LHS, CxtI, DT))
else if (isAllocLikeFn(RHS, TLI) &&
llvm::isKnownNonZero(LHS, DL, 0, nullptr, CxtI, DT))
MI = RHS;
// FIXME: We should also fold the compare when the pointer escapes, but the
// compare dominates the pointer escape
Expand Down Expand Up @@ -3313,15 +3316,16 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// Simplify comparisons of related pointers using a powerful, recursive
// GEP-walk when we have target data available..
if (LHS->getType()->isPointerTy())
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.CxtI, LHS, RHS))
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI, LHS,
RHS))
return C;
if (auto *CLHS = dyn_cast<PtrToIntOperator>(LHS))
if (auto *CRHS = dyn_cast<PtrToIntOperator>(RHS))
if (Q.DL.getTypeSizeInBits(CLHS->getPointerOperandType()) ==
Q.DL.getTypeSizeInBits(CLHS->getType()) &&
Q.DL.getTypeSizeInBits(CRHS->getPointerOperandType()) ==
Q.DL.getTypeSizeInBits(CRHS->getType()))
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.CxtI,
if (auto *C = computePointerICmp(Q.DL, Q.TLI, Q.DT, Pred, Q.AC, Q.CxtI,
CLHS->getPointerOperand(),
CRHS->getPointerOperand()))
return C;
Expand Down
12 changes: 6 additions & 6 deletions lib/Analysis/LazyValueInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,12 +817,12 @@ bool LazyValueInfoImpl::solveBlockValueImpl(LVILatticeVal &Res,
// definition. We could easily extend this to look through geps, bitcasts,
// and the like to prove non-nullness, but it's not clear that's worth it
// compile time wise. The context-insensitive value walk done inside
// isKnownNonNull gets most of the profitable cases at much less expense.
// isKnownNonZero gets most of the profitable cases at much less expense.
// This does mean that we have a sensativity to where the defining
// instruction is placed, even if it could legally be hoisted much higher.
// That is unfortunate.
PointerType *PT = dyn_cast<PointerType>(BBI->getType());
if (PT && isKnownNonNull(BBI)) {
if (PT && isKnownNonZero(BBI, DL)) {
Res = LVILatticeVal::getNot(ConstantPointerNull::get(PT));
return true;
}
Expand Down Expand Up @@ -901,7 +901,7 @@ bool LazyValueInfoImpl::solveBlockValueNonLocal(LVILatticeVal &BBLV,
// Before giving up, see if we can prove the pointer non-null local to
// this particular block.
if (Val->getType()->isPointerTy() &&
(isKnownNonNull(Val) || isObjectDereferencedInBlock(Val, BB))) {
(isKnownNonZero(Val, DL) || isObjectDereferencedInBlock(Val, BB))) {
PointerType *PTy = cast<PointerType>(Val->getType());
Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy));
} else {
Expand Down Expand Up @@ -1886,17 +1886,17 @@ LazyValueInfo::Tristate
LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI) {
// Is or is not NonNull are common predicates being queried. If
// isKnownNonNull can tell us the result of the predicate, we can
// isKnownNonZero can tell us the result of the predicate, we can
// return it quickly. But this is only a fastpath, and falling
// through would still be correct.
const DataLayout &DL = CxtI->getModule()->getDataLayout();
if (V->getType()->isPointerTy() && C->isNullValue() &&
isKnownNonNull(V->stripPointerCasts())) {
isKnownNonZero(V->stripPointerCasts(), DL)) {
if (Pred == ICmpInst::ICMP_EQ)
return LazyValueInfo::False;
else if (Pred == ICmpInst::ICMP_NE)
return LazyValueInfo::True;
}
const DataLayout &DL = CxtI->getModule()->getDataLayout();
LVILatticeVal Result = getImpl(PImpl, AC, &DL, DT).getValueAt(V, CxtI);
Tristate Ret = getPredicateResult(Pred, C, Result, DL, TLI);
if (Ret != Unknown)
Expand Down
2 changes: 1 addition & 1 deletion lib/Analysis/Loads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static bool isDereferenceableAndAlignedPointer(
V->getPointerDereferenceableBytes(DL, CheckForNonNull));
if (KnownDerefBytes.getBoolValue()) {
if (KnownDerefBytes.uge(Size))
if (!CheckForNonNull || isKnownNonNullAt(V, CtxI, DT))
if (!CheckForNonNull || isKnownNonZero(V, DL, 0, nullptr, CtxI, DT))
return isAligned(V, Align, DL);
}

Expand Down
182 changes: 85 additions & 97 deletions lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,58 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
return false;
}

static bool isKnownNonNullFromDominatingCondition(const Value *V,
const Instruction *CtxI,
const DominatorTree *DT) {
assert(V->getType()->isPointerTy() && "V must be pointer type");
assert(!isa<ConstantData>(V) && "Did not expect ConstantPointerNull");

if (!CtxI || !DT)
return false;

unsigned NumUsesExplored = 0;
for (auto *U : V->users()) {
// Avoid massive lists
if (NumUsesExplored >= DomConditionsMaxUses)
break;
NumUsesExplored++;

// If the value is used as an argument to a call or invoke, then argument
// attributes may provide an answer about null-ness.
if (auto CS = ImmutableCallSite(U))
if (auto *CalledFunc = CS.getCalledFunction())
for (const Argument &Arg : CalledFunc->args())
if (CS.getArgOperand(Arg.getArgNo()) == V &&
Arg.hasNonNullAttr() && DT->dominates(CS.getInstruction(), CtxI))
return true;

// Consider only compare instructions uniquely controlling a branch
CmpInst::Predicate Pred;
if (!match(const_cast<User *>(U),
m_c_ICmp(Pred, m_Specific(V), m_Zero())) ||
(Pred != ICmpInst::ICMP_EQ && Pred != ICmpInst::ICMP_NE))
continue;

for (auto *CmpU : U->users()) {
if (const BranchInst *BI = dyn_cast<BranchInst>(CmpU)) {
assert(BI->isConditional() && "uses a comparison!");

BasicBlock *NonNullSuccessor =
BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
return true;
} else if (Pred == ICmpInst::ICMP_NE &&
match(CmpU, m_Intrinsic<Intrinsic::experimental_guard>()) &&
DT->dominates(cast<Instruction>(CmpU), CtxI)) {
return true;
}
}
}

return false;
}

/// Does the 'Range' metadata (which must be a valid MD_range operand list)
/// ensure that the value it's attached to is never Value? 'RangeType' is
/// is the type of the value described by the range.
Expand Down Expand Up @@ -1794,7 +1846,15 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
return true;
}

return false;
// 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;
} else
return false;
}

if (auto *I = dyn_cast<Instruction>(V)) {
Expand All @@ -1809,14 +1869,36 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
}
}

// Check for pointer simplifications.
if (V->getType()->isPointerTy()) {
// Alloca never returns null, malloc might.
if (isa<AllocaInst>(V) && Q.DL.getAllocaAddrSpace() == 0)
return true;

// A byval, inalloca, or nonnull argument is never null.
if (const Argument *A = dyn_cast<Argument>(V))
if (A->hasByValOrInAllocaAttr() || A->hasNonNullAttr())
return true;

// A Load tagged with nonnull metadata is never null.
if (const LoadInst *LI = dyn_cast<LoadInst>(V))
if (LI->getMetadata(LLVMContext::MD_nonnull))
return true;

if (auto CS = ImmutableCallSite(V))
if (CS.isReturnNonNull())
return true;
}

// The remaining tests are all recursive, so bail out if we hit the limit.
if (Depth++ >= MaxDepth)
return false;

// Check for pointer simplifications.
// Check for recursive pointer simplifications.
if (V->getType()->isPointerTy()) {
if (isKnownNonNullAt(V, Q.CxtI, Q.DT))
if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
return true;

if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V))
if (isGEPKnownNonNull(GEP, Depth, Q))
return true;
Expand Down Expand Up @@ -3482,100 +3564,6 @@ bool llvm::mayBeMemoryDependent(const Instruction &I) {
return I.mayReadOrWriteMemory() || !isSafeToSpeculativelyExecute(&I);
}

/// Return true if we know that the specified value is never null.
bool llvm::isKnownNonNull(const Value *V) {
assert(V->getType()->isPointerTy() && "V must be pointer type");

// Alloca never returns null, malloc might.
if (isa<AllocaInst>(V)) return true;

// A byval, inalloca, or nonnull argument is never null.
if (const Argument *A = dyn_cast<Argument>(V))
return A->hasByValOrInAllocaAttr() || A->hasNonNullAttr();

// 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))
return !GV->isAbsoluteSymbolRef() && !GV->hasExternalWeakLinkage() &&
GV->getType()->getAddressSpace() == 0;

// A Load tagged with nonnull metadata is never null.
if (const LoadInst *LI = dyn_cast<LoadInst>(V))
return LI->getMetadata(LLVMContext::MD_nonnull);

if (auto CS = ImmutableCallSite(V))
if (CS.isReturnNonNull())
return true;

return false;
}

static bool isKnownNonNullFromDominatingCondition(const Value *V,
const Instruction *CtxI,
const DominatorTree *DT) {
assert(V->getType()->isPointerTy() && "V must be pointer type");
assert(!isa<ConstantData>(V) && "Did not expect ConstantPointerNull");
assert(CtxI && "Context instruction required for analysis");
assert(DT && "Dominator tree required for analysis");

unsigned NumUsesExplored = 0;
for (auto *U : V->users()) {
// Avoid massive lists
if (NumUsesExplored >= DomConditionsMaxUses)
break;
NumUsesExplored++;

// If the value is used as an argument to a call or invoke, then argument
// attributes may provide an answer about null-ness.
if (auto CS = ImmutableCallSite(U))
if (auto *CalledFunc = CS.getCalledFunction())
for (const Argument &Arg : CalledFunc->args())
if (CS.getArgOperand(Arg.getArgNo()) == V &&
Arg.hasNonNullAttr() && DT->dominates(CS.getInstruction(), CtxI))
return true;

// Consider only compare instructions uniquely controlling a branch
CmpInst::Predicate Pred;
if (!match(const_cast<User *>(U),
m_c_ICmp(Pred, m_Specific(V), m_Zero())) ||
(Pred != ICmpInst::ICMP_EQ && Pred != ICmpInst::ICMP_NE))
continue;

for (auto *CmpU : U->users()) {
if (const BranchInst *BI = dyn_cast<BranchInst>(CmpU)) {
assert(BI->isConditional() && "uses a comparison!");

BasicBlock *NonNullSuccessor =
BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
return true;
} else if (Pred == ICmpInst::ICMP_NE &&
match(CmpU, m_Intrinsic<Intrinsic::experimental_guard>()) &&
DT->dominates(cast<Instruction>(CmpU), CtxI)) {
return true;
}
}
}

return false;
}

bool llvm::isKnownNonNullAt(const Value *V, const Instruction *CtxI,
const DominatorTree *DT) {
if (isa<ConstantPointerNull>(V) || isa<UndefValue>(V))
return false;

if (isKnownNonNull(V))
return true;

if (!CtxI || !DT)
return false;

return ::isKnownNonNullFromDominatingCondition(V, CtxI, DT);
}

OverflowResult llvm::computeOverflowForUnsignedMul(const Value *LHS,
const Value *RHS,
const DataLayout &DL,
Expand Down
4 changes: 3 additions & 1 deletion lib/Transforms/IPO/FunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,11 +884,13 @@ static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
FlowsToReturn.insert(Ret->getReturnValue());

auto &DL = F->getParent()->getDataLayout();

for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
Value *RetVal = FlowsToReturn[i];

// If this value is locally known to be non-null, we're good
if (isKnownNonNull(RetVal))
if (isKnownNonZero(RetVal, DL))
continue;

// Otherwise, we need to look upwards since we can't make any local
Expand Down
4 changes: 2 additions & 2 deletions lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3743,7 +3743,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
return replaceInstUsesWith(*II, ConstantPointerNull::get(PT));

// isKnownNonNull -> nonnull attribute
if (isKnownNonNullAt(DerivedPtr, II, &DT))
if (isKnownNonZero(DerivedPtr, DL, 0, &AC, II, &DT))
II->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
}

Expand Down Expand Up @@ -3932,7 +3932,7 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
for (Value *V : CS.args()) {
if (V->getType()->isPointerTy() &&
!CS.paramHasAttr(ArgNo, Attribute::NonNull) &&
isKnownNonNullAt(V, CS.getInstruction(), &DT))
isKnownNonZero(V, DL, 0, &AC, CS.getInstruction(), &DT))
ArgNos.push_back(ArgNo);
ArgNo++;
}
Expand Down
Loading

0 comments on commit fe353a0

Please sign in to comment.