When analyzing params/args for readnone/readonly, don't forget to consider that a pointer argument may be passed through a callsite to the return, and that we may need to analyze it. Fixes a bug reported on llvm-dev: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-May/073098.html

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209870 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky 2014-05-30 02:31:27 +00:00
parent 0997206ac4
commit a35be5ab67
3 changed files with 33 additions and 2 deletions

View File

@ -449,14 +449,29 @@ determinePointerReadAttrs(Argument *A,
case Instruction::Call: case Instruction::Call:
case Instruction::Invoke: { case Instruction::Invoke: {
bool Captures = true;
if (I->getType()->isVoidTy())
Captures = false;
auto AddUsersToWorklistIfCapturing = [&] {
if (Captures)
for (Use &UU : I->uses())
if (Visited.insert(&UU))
Worklist.push_back(&UU);
};
CallSite CS(I); CallSite CS(I);
if (CS.doesNotAccessMemory()) if (CS.doesNotAccessMemory()) {
AddUsersToWorklistIfCapturing();
continue; continue;
}
Function *F = CS.getCalledFunction(); Function *F = CS.getCalledFunction();
if (!F) { if (!F) {
if (CS.onlyReadsMemory()) { if (CS.onlyReadsMemory()) {
IsRead = true; IsRead = true;
AddUsersToWorklistIfCapturing();
continue; continue;
} }
return Attribute::None; return Attribute::None;
@ -471,6 +486,7 @@ determinePointerReadAttrs(Argument *A,
"More params than args in non-varargs call."); "More params than args in non-varargs call.");
return Attribute::None; return Attribute::None;
} }
Captures &= !CS.doesNotCapture(A - B);
if (SCCNodes.count(AI)) if (SCCNodes.count(AI))
continue; continue;
if (!CS.onlyReadsMemory() && !CS.onlyReadsMemory(A - B)) if (!CS.onlyReadsMemory() && !CS.onlyReadsMemory(A - B))
@ -479,6 +495,7 @@ determinePointerReadAttrs(Argument *A,
IsRead = true; IsRead = true;
} }
} }
AddUsersToWorklistIfCapturing();
break; break;
} }

View File

@ -68,7 +68,7 @@ define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind {
ret i1* %lookup ret i1* %lookup
} }
; CHECK: define i1 @c7(i32* readnone %q, i32 %bitno) ; CHECK: define i1 @c7(i32* readonly %q, i32 %bitno)
define i1 @c7(i32* %q, i32 %bitno) { define i1 @c7(i32* %q, i32 %bitno) {
%ptr = call i1* @lookup_bit(i32* %q, i32 %bitno) %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno)
%val = load i1* %ptr %val = load i1* %ptr

View File

@ -51,3 +51,17 @@ define void @test6_2(i8** %p, i8* %q) {
define void @test7_1(i32* inalloca %a) { define void @test7_1(i32* inalloca %a) {
ret void ret void
} }
; CHECK: define i32* @test8_1(i32* readnone %p)
define i32* @test8_1(i32* %p) {
entry:
ret i32* %p
}
; CHECK: define void @test8_2(i32* %p)
define void @test8_2(i32* %p) {
entry:
%call = call i32* @test8_1(i32* %p)
store i32 10, i32* %call, align 4
ret void
}