diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index 6877e44813f56..1eb4f2efb5a38 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -1732,7 +1732,7 @@ bool CallAnalyzer::isKnownNonNullInCallee(Value *V) { // parameter attribute, but that's a less interesting case because hopefully // the callee would already have been simplified based on that. if (Argument *A = dyn_cast(V)) - if (paramHasAttr(A, Attribute::NonNull)) + if (paramHasAttr(A, Attribute::NonNull) || paramHasAttr(A, Attribute::Dereferenceable)) return true; // Is this an alloca in the caller? This is distinct from the attribute case diff --git a/llvm/test/Transforms/Inline/nonnull.ll b/llvm/test/Transforms/Inline/nonnull.ll index 5f8af7f78fde7..658ae47954ee1 100644 --- a/llvm/test/Transforms/Inline/nonnull.ll +++ b/llvm/test/Transforms/Inline/nonnull.ll @@ -99,10 +99,11 @@ define void @caller3(ptr %arg) { ret void } +; Positive test - arg is known non null define void @caller4(ptr dereferenceable(8) %arg) { ; CHECK-LABEL: define void @caller4 ; CHECK-SAME: (ptr dereferenceable(8) [[ARG:%.*]]) { -; CHECK-NEXT: call void @callee(ptr dereferenceable(8) [[ARG]]) +; CHECK-NEXT: call void @bar() ; CHECK-NEXT: ret void ; call void @callee(ptr dereferenceable(8) %arg) @@ -122,7 +123,24 @@ define void @caller5(ptr dereferenceable(8) %arg) { define void @caller6(ptr %arg) { ; CHECK-LABEL: define void @caller6 ; CHECK-SAME: (ptr [[ARG:%.*]]) { -; CHECK-NEXT: call void @callee(ptr dereferenceable(8) [[ARG]]) +; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[ARG]], null +; CHECK-NEXT: br i1 [[CMP_I]], label [[EXPENSIVE_I:%.*]], label [[DONE_I:%.*]] +; CHECK: expensive.i: +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: call void @foo() +; CHECK-NEXT: br label [[CALLEE_EXIT:%.*]] +; CHECK: done.i: +; CHECK-NEXT: call void @bar() +; CHECK-NEXT: br label [[CALLEE_EXIT]] +; CHECK: callee.exit: ; CHECK-NEXT: ret void ; call void @callee(ptr dereferenceable(8) %arg)