Although nonescaping closures are representationally trivial pointers to their
on-stack context, it is useful to model them as borrowing their captures, which
allows for checking correct use of move-only values across the closure, and
lets us model the lifetime dependence between a closure and its captures without
an ad-hoc web of `mark_dependence` instructions.
During ownership elimination, We eliminate copy/destroy_value instructions and
end the partial_apply's lifetime with an explicit dealloc_stack as before,
for compatibility with existing IRGen and non-OSSA aware passes.
The instance type of a metatype instruction is not necessarily a legal lowered SIL Type.
Lower the type before converting it to a SILType.
rdar://105502403
Some guaranteed forwarding instructions have multiple operands:
mark_dependence, ref_to_bridge_object.
The corresponding instruction types checked here already have
documentation that the forwarded operand is the first operand. The
assert is overly cautious, and checking for indiviudal opcodes would be
tedious maintenance.
Encapsulate all the complexity of reborrows and guaranteed phi in 3
ownership liveness interfaces:
LinerLiveness, InteriorLiveness, and ExtendedLiveness.
This instruction can be inserted by Onone optimizations as a replacement for deleted instructions to
ensure that it's possible to single step on its location.
This allows dynamically indexing into tuples. IRGen not yet
implemented.
I think I'm going to need a type_refine_addr instruction in
order to handle substitutions into the operand type that
eliminate the outer layer of tuple-ness. Gonna handle that
in a follow-up commit.
This will let the non-field sensitive version use a more performant
implementation internally. This is important since PrunedLiveBlocks is used in
the hot path when working with Ownership SSA, while the field sensitive version
is only used for certain diagnostics.
NOTE: I did not refactor PrunedLiveness to use the faster implementation... this
is just a quick pass over the code to prepare for that change.
This API is the inverse of visitEnclosingDefs when called on a phi.
This replaces the visitAdjacentReborrowsOfPhi algorithm with a small
loop that simply checks all the phis in the current block.
This should all be fairly efficient once SILArgument has a "reborrow"
flag.
Having added these, I'm not entirely sure we couldn't just use
alloc_stack and dealloc_stack. Well, if we find ourselves adding
a lot of redundancy with those instructions (e.g. around DI), we
can always go back and rip these out.
- SILPackType carries whether the elements are stored directly
in the pack, which we're not currently using in the lowering,
but it's probably something we'll want in the final ABI.
Having this also makes it clear that we're doing the right
thing with substitution and element lowering. I also toyed
with making this a scalar type, which made it necessary in
various places, although eventually I pulled back to the
design where we always use packs as addresses.
- Pack boundaries are a core ABI concept, so the lowering has
to wrap parameter pack expansions up as packs. There are huge
unimplemented holes here where the abstraction pattern will
need to tell us how many elements to gather into the pack,
but a naive approach is good enough to get things off the
ground.
- Pack conventions are related to the existing parameter and
result conventions, but they're different on enough grounds
that they deserve to be separated.
Recognize lexical borrows as nested when their borrowee's guaranteed
reference roots are all lexical borrows.
Addresses the following regressions
Breadcrumbs.MutatedUTF16ToIdx.Mixed 188 882 +369.1% **0.21x**
Breadcrumbs.MutatedIdxToUTF16.Mixed 230 926 +302.6% **0.25x**
seen when enabling lexical lifetimes in the standard library.
In preparation for adding OwnershipLiveness.
Rename Simple LiveRangeSummary to LiveRangeSummary.
Add initializeDefNode helpers to avoid confusion about the argument
type.
Add defBegin/defEnd iterators in MultiDefPrunedLiveness.
Specifically:
1. I added to the documentation at the top of the file that our representation
allows for partial init/reinit of structs/tuples from parts.
2. I renamed SubElementNumber to SubElementOffset. This I think fits the actual
use case better and makes it clearer what one is working with (the offset inside
a type of a subelement of the type).
3. I added some small helpers to TypeSubElementCount and SubElementOffset for
adding/subtracting from them.
4. I added the ability to iterate over just consuming/nonconsuming users in
FieldSensitivePrunedLiveness. Just a useful little helper.
Specifically, I forgot that when asserts are disabled I made
FieldSensitivePrunedLivenessBoundary::getNumLastUsersAndDeadDefs() assert to
make sure that callers were sure to place it within a #ifndef block since it is
rather expensive and not actual used in the computation. Funnily, I forgot to
end.
rdar://104107922