This change allows us to infer access attributes (readnone, readonly) on arguments passed to vararg functions. Since there isn't a formal argument corresponding to the parameter, they'll never be considered part of the speculative SCC, but they can still benefit from attributes on the call site or the callee function. The main motivation here is just to simplify the code, and remove some special casing. Previously, an indirect vararg call could return more precise results than an direct vararg call which is just weird. Differential Revision: https://reviews.llvm.org/D115964
44 lines
1.2 KiB
LLVM
44 lines
1.2 KiB
LLVM
; RUN: opt -function-attrs -S < %s | FileCheck %s
|
|
; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
|
|
|
|
; This checks for a previously existing iterator wraparound bug in
|
|
; FunctionAttrs, and in the process covers corner cases with varargs.
|
|
|
|
declare void @llvm.va_start(i8*)
|
|
declare void @llvm.va_end(i8*)
|
|
|
|
define void @va_func(i32* readonly %b, ...) readonly nounwind {
|
|
; CHECK-LABEL: define void @va_func(i32* nocapture readonly %b, ...)
|
|
entry:
|
|
%valist = alloca i8
|
|
call void @llvm.va_start(i8* %valist)
|
|
call void @llvm.va_end(i8* %valist)
|
|
%x = call i32 @caller(i32* %b)
|
|
ret void
|
|
}
|
|
|
|
define i32 @caller(i32* %x) {
|
|
; CHECK-LABEL: define i32 @caller(i32* nocapture readonly %x)
|
|
entry:
|
|
call void(i32*,...) @va_func(i32* null, i32 0, i32 0, i32 0, i32* %x)
|
|
ret i32 42
|
|
}
|
|
|
|
define void @va_func2(i32* readonly %b, ...) {
|
|
; CHECK-LABEL: define void @va_func2(i32* nocapture readonly %b, ...)
|
|
entry:
|
|
%valist = alloca i8
|
|
call void @llvm.va_start(i8* %valist)
|
|
call void @llvm.va_end(i8* %valist)
|
|
%x = call i32 @caller(i32* %b)
|
|
ret void
|
|
}
|
|
|
|
define i32 @caller2(i32* %x, i32* %y) {
|
|
; CHECK-LABEL: define i32 @caller2(i32* nocapture readonly %x, i32* %y)
|
|
entry:
|
|
call void(i32*,...) @va_func2(i32* %x, i32 0, i32 0, i32 0, i32* %y)
|
|
ret i32 42
|
|
}
|
|
|