When checking whether an instruction is contained in a liveness
boundary, a pointer to a DeadEndBlocks instance must always be passed.
When the pointer is null, it is only checked that the instruction occurs
within the direct live region. When the pointer is non-null, it is
checked whether the instruction occurs within the region obtained by
extending the live region up to the availability boundary within
dead-end regions that are adjacent to the non-lifetime-ending portion of
the liveness boundary.
The areUsesWithinBoundary/areUsesOutsideBoundary methods take the
dead-ends because the region that they're checking for containment
within contains more than just (is a (non-strict) superset of) the
pruned live region. On the other hand, the region also contains _less_
than (is a (non-strict) subset of) the available region. Instructions
are in this extended region only if they're in a dead-end block which is
forwards reachable from the non-lifetime-ending liveness boundary.
A branch instruction that is both a lifetime-ending user and also a
non-lifetime-ending of a value should be regarded as a lifetime-ending
user.
Without this, utilities that rely on PrunedLiveness such as
`LinearLiveness` and `InteriorLiveness` both incorrectly report that a
branch featuring a value and also a reborrow or guaranteed phi are
non-ending.
rdar://130427564
This corresponds to the parameter-passing convention of the Itanium C++
ABI, in which the argument is passed indirectly and possibly modified,
but not destroyed, by the callee.
@in_cxx is handled the same way as @in in callers and @in_guaranteed in
callees. OwnershipModelEliminator emits the call to destroy_addr that is
needed to destroy the argument in the caller.
rdar://122707697
Now that the two known issues which resulted in invalid SIL being
provided to lifetime completion have been addressed, tighten up the
completion done on the availability boundary not to allow leaks.
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
When visiting consumes, also visit `extend_lifetime` instructions.
These instructions are not lifetime ending, but together with the
consumes, they enclose the users of a value.
Add a flag to LinearLiveness to control whether these instructions are
added so that the verifier can use verify that all such instructions
appear outside the linear lifetime boundary (not including them).
It indicates that the value's lifetime continues to at least this point.
The boundary formed by all consuming uses together with these
instructions will encompass all uses of the value.
An initializing store is not a copy and therefore doesn't perform ref counting operations
Fixes a false performance error when using non-copyable types.
https://github.com/apple/swift/issues/73582
The new boundary allows for invalid OSSA where values are not consumed
on paths leading to blocks that exit the function normally. In such
cases, the value is allowed to continue leaking as before.