Skip to content

Commit

Permalink
[funcattrs] Consistently treat calling a function pointer as a non-ca…
Browse files Browse the repository at this point in the history
…pturing read

We were being wildly inconsistent about what memory access was implied by an indirect function call. Depending on the call site attributes, you could get anything from a read, to unknown, to none at all. (The last was a miscompile.)

We were also always traversing the uses of a readonly indirect call. This is entirely unneeded as the indirect call does not capture. The callee might capture itself internally, but that has no implications for this caller. (See the nice explanation in the CaptureTracking comments if that case is confusing.)

Note that elsewhere in the same file, we were correctly computing the nocapture attribute for indirect calls. The changed case only resulted in conservatism when computing memory attributes if say the return value was written to.

Differential Revision: https://reviews.llvm.org/D115916
  • Loading branch information
preames committed Dec 17, 2021
1 parent 7e44eb0 commit 33cbaab
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 10 deletions.
4 changes: 2 additions & 2 deletions clang/test/CodeGen/arm-cmse-attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ void f4() __attribute__((cmse_nonsecure_entry))
{
}

// CHECK: define{{.*}} void @f1(void ()* nocapture %fptr) {{[^#]*}}#0 {
// CHECK: define{{.*}} void @f1(void ()* nocapture readonly %fptr) {{[^#]*}}#0 {
// CHECK: call void %fptr() #2
// CHECK: define{{.*}} void @f2(void ()* nocapture %fptr) {{[^#]*}}#0 {
// CHECK: define{{.*}} void @f2(void ()* nocapture readonly %fptr) {{[^#]*}}#0 {
// CHECK: call void %fptr() #2
// CHECK: define{{.*}} void @f3() {{[^#]*}}#1 {
// CHECK: define{{.*}} void @f4() {{[^#]*}}#1 {
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Transforms/IPO/FunctionAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,11 @@ determinePointerAccessAttrs(Argument *A,
};

CallBase &CB = cast<CallBase>(*I);
if (CB.isCallee(U)) {
IsRead = true;
Captures = false; // See comment in CaptureTracking for context
continue;
}
if (CB.doesNotAccessMemory()) {
AddUsersToWorklistIfCapturing();
continue;
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/Transforms/FunctionAttrs/nocapture.ll
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ define void @nc2(i32* %p, i32* %q) {
}


; FNATTR: define void @nc3(void ()* nocapture %p)
; FNATTR: define void @nc3(void ()* nocapture readonly %p)
define void @nc3(void ()* %p) {
call void %p()
ret void
Expand All @@ -141,7 +141,7 @@ define void @nc4(i8* %p) {
ret void
}

; FNATTR: define void @nc5(void (i8*)* nocapture %f, i8* nocapture %p)
; FNATTR: define void @nc5(void (i8*)* nocapture readonly %f, i8* nocapture %p)
define void @nc5(void (i8*)* %f, i8* %p) {
call void %f(i8* %p) readonly nounwind
call void %f(i8* nocapture %p)
Expand Down Expand Up @@ -319,21 +319,21 @@ define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x)

declare void @capture(i8*)

; FNATTR: define void @nocapture_fptr(i8* (i8*)* nocapture %f, i8* %p)
; FNATTR: define void @nocapture_fptr(i8* (i8*)* nocapture readonly %f, i8* %p)
define void @nocapture_fptr(i8* (i8*)* %f, i8* %p) {
%res = call i8* %f(i8* %p)
call void @capture(i8* %res)
ret void
}

; FNATTR: define void @recurse_fptr(i8* (i8*)* nocapture %f, i8* %p)
; FNATTR: define void @recurse_fptr(i8* (i8*)* nocapture readonly %f, i8* %p)
define void @recurse_fptr(i8* (i8*)* %f, i8* %p) {
%res = call i8* %f(i8* %p)
store i8 0, i8* %res
ret void
}

; FNATTR: define void @readnone_indirec(void (i8*)* nocapture readnone %f, i8* readnone %p)
; FNATTR: define void @readnone_indirec(void (i8*)* nocapture readonly %f, i8* readnone %p)
define void @readnone_indirec(void (i8*)* %f, i8* %p) {
call void %f(i8* %p) readnone
ret void
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/FunctionAttrs/writeonly.ll
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,19 @@ define void @direct3(i8* %p) {
ret void
}

; CHECK: define void @fptr_test1(i8* %p, void (i8*)* nocapture %f)
; CHECK: define void @fptr_test1(i8* %p, void (i8*)* nocapture readonly %f)
define void @fptr_test1(i8* %p, void (i8*)* %f) {
call void %f(i8* %p)
ret void
}

; CHECK: define void @fptr_test2(i8* %p, void (i8*)* nocapture %f)
; CHECK: define void @fptr_test2(i8* %p, void (i8*)* nocapture readonly %f)
define void @fptr_test2(i8* %p, void (i8*)* %f) {
call void %f(i8* writeonly %p)
ret void
}

; CHECK: define void @fptr_test3(i8* %p, void (i8*)* nocapture %f)
; CHECK: define void @fptr_test3(i8* %p, void (i8*)* nocapture readonly %f)
define void @fptr_test3(i8* %p, void (i8*)* %f) {
call void %f(i8* %p) writeonly
ret void
Expand Down

0 comments on commit 33cbaab

Please sign in to comment.