[llvm-dev] sret read after unwind

Nikita Popov via llvm-dev llvm-dev at lists.llvm.org
Sat Dec 4 02:39:18 PST 2021


Hi,

Consider the following IR:

declare void @may_unwind()
define void @test(i32* noalias sret(i32) %out) {
    store i32 0, i32* %out
    call void @may_unwind()
    store i32 1, i32* %out
    ret void
}

Currently, we can't remove the first store as dead, because the
@may_unwind() call may unwind, and the caller might read %out at that
point, making the first store visible.

Similarly, it prevents call slot optimization in the following example,
because the call may unwind and make an early write to the sret argument
visible:

declare void @may_unwind(i32*)
declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i1)
define void @test(i32* noalias sret(i32) %arg) {
    %tmp = alloca i32
    call void @may_unwind(i32* nocapture %tmp)
    %tmp.8 = bitcast i32* %tmp to i8*
    %arg.8 = bitcast i32* %arg to i8*
    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %arg.8, i8* align 4
%tmp.8, i64 4, i1 false)
    ret void
}

I would like to address this in some form. The easiest way would be to
change LangRef to specify that sret arguments cannot be read on unwind
paths. I think that matches how sret arguments are generally used.

Alternatively, this could be handled using a separate attribute that can be
applied to any argument, something along the lines of "i32* nounwindread
sret(i32) %arg". The benefit would be that this is decoupled from sret ABI
semantics and could potentially be inferred (e.g. if the function is only
ever used with call and not invoke, this should be a given).

Any thoughts on this? Is this a problem worth solving, and if yes, would a
new attribute be preferred over restricting sret semantics?

Regards,
Nikita
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211204/c830a34c/attachment.html>


More information about the llvm-dev mailing list