summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Analysis/LazyValueInfo.cpp52
-rw-r--r--llvm/test/Transforms/CorrelatedValuePropagation/basic.ll22
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:
OpenPOWER on IntegriCloud