Following up on the discussion in https://groups.google.com/g/llvm-dev/c/i0Z1FC51KVI, this updates sret semantics to specify that the sret memory cannot be read after unwinding. This enables optimizations like the following:
declare void @may_unwind() define void @src(i32* noalias sret(i32) %out) { store i32 0, i32* %out call void @may_unwind() store i32 1, i32* %out ret void } define void @tgt(i32* noalias sret(i32) %out) { call void @may_unwind() store i32 1, i32* %out ret void }
Without the guarantee, the memory state of %out could be observed if @may_unwind() unwinds, and the first store would not be dead.
Rather than making accesses after unwind UB, this instead specifies that the memory is filled with poison. This gives us the necessary optimization guarantees without preventing accesses entirely (e.g. "lifetime.end" on unwind must remain legal, and is currently modeled as an access.)