diff options
-rw-r--r-- | llvm/lib/Analysis/LazyValueInfo.cpp | 52 | ||||
-rw-r--r-- | llvm/test/Transforms/CorrelatedValuePropagation/basic.ll | 22 |
2 files changed, 48 insertions, 26 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index beb621a2311..0e8ad93fe9b 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -729,37 +729,36 @@ static bool InstructionDereferencesPointer(Instruction *I, Value *Ptr) { return false; } +/// Return true if the allocation associated with Val is ever dereferenced +/// within the given basic block. This establishes the fact Val is not null, +/// but does not imply that the memory at Val is dereferenceable. (Val may +/// point off the end of the dereferenceable part of the object.) +static bool isObjectDereferencedInBlock(Value *Val, BasicBlock *BB) { + assert(Val->getType()->isPointerTy()); + + const DataLayout &DL = BB->getModule()->getDataLayout(); + Value *UnderlyingVal = GetUnderlyingObject(Val, DL); + // If 'GetUnderlyingObject' didn't converge, skip it. It won't converge + // inside InstructionDereferencesPointer either. + if (UnderlyingVal == GetUnderlyingObject(UnderlyingVal, DL, 1)) + for (Instruction &I : *BB) + if (InstructionDereferencesPointer(&I, UnderlyingVal)) + return true; + return false; +} + bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, Value *Val, BasicBlock *BB) { LVILatticeVal Result; // Start Undefined. - // If this is a pointer, and there's a load from that pointer in this BB, - // then we know that the pointer can't be NULL. - bool NotNull = false; - if (Val->getType()->isPointerTy()) { - if (isKnownNonNull(Val)) { - NotNull = true; - } else { - const DataLayout &DL = BB->getModule()->getDataLayout(); - Value *UnderlyingVal = GetUnderlyingObject(Val, DL); - // If 'GetUnderlyingObject' didn't converge, skip it. It won't converge - // inside InstructionDereferencesPointer either. - if (UnderlyingVal == GetUnderlyingObject(UnderlyingVal, DL, 1)) { - for (Instruction &I : *BB) { - if (InstructionDereferencesPointer(&I, UnderlyingVal)) { - NotNull = true; - break; - } - } - } - } - } - // If this is the entry block, we must be asking about an argument. The // value is overdefined. if (BB == &BB->getParent()->getEntryBlock()) { assert(isa<Argument>(Val) && "Unknown live-in to the entry block"); - if (NotNull) { + // Bofore 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))) { PointerType *PTy = cast<PointerType>(Val->getType()); Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); } else { @@ -785,9 +784,10 @@ bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, if (Result.isOverdefined()) { DEBUG(dbgs() << " compute BB '" << BB->getName() << "' - overdefined because of pred (non local).\n"); - // If we previously determined that this is a pointer that can't be null - // then return that rather than giving up entirely. - if (NotNull) { + // Bofore giving up, see if we can prove the pointer non-null local to + // this particular block. + if (Val->getType()->isPointerTy() && + isObjectDereferencedInBlock(Val, BB)) { PointerType *PTy = cast<PointerType>(Val->getType()); Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll index d0a17306c6b..9836c7f8077 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -200,6 +200,28 @@ next: ret void } +define i1 @arg_attribute(i8* nonnull %a) { +; CHECK-LABEL: @arg_attribute( +; CHECK: ret i1 false + %cmp = icmp eq i8* %a, null + br label %exit + +exit: + ret i1 %cmp +} + +declare nonnull i8* @return_nonnull() +define i1 @call_attribute() { +; CHECK-LABEL: @call_attribute( +; CHECK: ret i1 false + %a = call i8* @return_nonnull() + %cmp = icmp eq i8* %a, null + br label %exit + +exit: + ret i1 %cmp +} + define i1 @umin(i32 %a, i32 %b) { ; CHECK-LABEL: @umin( entry: |