summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp10
-rw-r--r--test/Analysis/BasicAA/nocapture.ll21
2 files changed, 26 insertions, 5 deletions
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index 131b9d65e6..4bb93ee88a 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -58,12 +58,12 @@ static bool isNonEscapingLocalObject(const Value *V) {
// then it has not escaped before entering the function. Check if it escapes
// inside the function.
if (const Argument *A = dyn_cast<Argument>(V))
- if (A->hasByValAttr() || A->hasNoAliasAttr()) {
- // Don't bother analyzing arguments already known not to escape.
- if (A->hasNoCaptureAttr())
- return true;
+ if (A->hasByValAttr() || A->hasNoAliasAttr())
+ // Note even if the argument is marked nocapture we still need to check
+ // for copies made inside the function. The nocapture attribute only
+ // specifies that there are no copies made that outlive the function.
return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true);
- }
+
return false;
}
diff --git a/test/Analysis/BasicAA/nocapture.ll b/test/Analysis/BasicAA/nocapture.ll
index a8658ec801..ffc0a09a07 100644
--- a/test/Analysis/BasicAA/nocapture.ll
+++ b/test/Analysis/BasicAA/nocapture.ll
@@ -13,3 +13,24 @@ define i32 @test2() {
ret i32 %c
}
+declare void @test3(i32** %p, i32* %q) nounwind
+
+define i32 @test4(i32* noalias nocapture %p) nounwind {
+; CHECK: call void @test3
+; CHECK: store i32 0, i32* %p
+; CHECK: store i32 1, i32* %x
+; CHECK: %y = load i32* %p
+; CHECK: ret i32 %y
+entry:
+ %q = alloca i32*
+ ; Here test3 might store %p to %q. This doesn't violate %p's nocapture
+ ; attribute since the copy doesn't outlive the function.
+ call void @test3(i32** %q, i32* %p) nounwind
+ store i32 0, i32* %p
+ %x = load i32** %q
+ ; This store might write to %p and so we can't eliminate the subsequent
+ ; load
+ store i32 1, i32* %x
+ %y = load i32* %p
+ ret i32 %y
+}