For most uses, some access scopes must be "respected"--if an extended
value's original lifetime originally extends beyond an access scope, its
canonicalized lifetime must not end _within_ such scopes (although
ending before them is fine). Currently, to be conservative, the utility
applies this behavior to all access scopes.
For move-only values, however, lifetimes end at final consumes without
regard to access scopes.
Allow this behavior to be controlled by whether or not a
NonLocalAccessBlockAnalysis is provided to the utility in its
constructor.
rdar://104635319
When encountering inside a borrow scope a non-lexical move_value or a
move_value [lexical] where the borrowed value is itself already lexical,
delete the move_value and regard its uses as uses of the moved-from
value.
To improve the debugging experience of values whose lifetimes are
canonicalized without compromising the semantics expressed in the source
language, when canonicalizing OSSA lifetimes at Onone, lengthen
lifetimes as much as possible without incurring copies that would be
eliminated at O.
rdar://99618502
Rather than having finding the boundary be a single combined step,
separate finding the original boundary from extending that boundary.
This enables inserting an optional step between those steps, namely to
extend unconsumed liveness to its original extent at Onone.
It is possible for phis to be marked live. With guaranteed phis, they
will be the last uses and be non-consuming. In this case, the
merge block will have multiple predecessors whose terminators are on the
boundary. When inserting destroys, track whether a merge point has been
visited previously.
To facilitate this, restructure the boundary extension and destroy
insertion code.
Previously, the extender was building up a list of places at which to
insert destroys. In particular it was using the "boundary edge"
collection for all blocks at the beginning of which a destroy should be
created. In particular, it would add merge blocks. Such blocks are not
boundary blocks.
Here, the extender produces a PrunedLivenessBoundary which doesn't
violate that invariant.
This required some changes to the destroy insertion code to find where
to insert destroys. It is now similar to
PrunedLivenessBoundary::visitInsertionPoints and could be used as a
template for a PrunedLivenessBoundary::visitBoundaryPoints through which
::visitInsertionPoints might be factored.