No need to bind to the StoreBorrowInst to get the source because it's
already bound to the local variable `stored`. And no need to bind to a
more specific type to find the next instruction.
Extend the definition of isGuaranteedLexicalValue--by means of which
Mem2Reg determines whether to borrow introducing a begin_borrow
[lexical] of a value which is store_borrow'd to an alloc_stack
[lexical]--to include every guaranteed lexical value.
Because lexical borrows are already avoided for store_borrows of lexical
values, the function is already misnamed: it's not that Mem2Reg should
necessarily _add_ a lexical lifetime, but rather that it should ensure
that there is one. Considering that we should do the same for owned
lexical values, the renaming will remain appropriate later. Finally,
name it so that it can switch from being a boolean to returning a
tristate (none, guaranteed, owned) when that becomes necessary (as it
will when we need to distinguish among the states to determine what phis
look like).
Now that StackAllocationPromoter::initializationPoints maps to either a
StoreInst or a StoreBorrowInst, there is no longer a subtype of
SILInstruction * at which the BlockToInstMap could be specialized, so
just eliminate the template argument and erase some angle brackets.
- 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.
Enables the outlining of the ContiguousArrayStorage<StaticString> used
when initializing a RawRepresentable enum whose RawValue is String into
a global value to continue even when ContiguousArrayStorage has a
lexical lifetime.
Addresses the following regressions
StringEnumRawValueInitialization 400 7680 +1820.0% **0.05x**
ArrayLiteral2 78 647 +729.5% **0.12x**
DataCreateSmallArray 1750 8850 +405.7% **0.20x**
seen when enabling lexical lifetimes in the standard library.
Given an aggregate addr `%agg` with trivial subobject addr `%triv` and
nontrivial subobject addr `%sub` which `%triv` is projected from,
```
Aggregate <- %agg
Subobject <- %sub
Trivial <- %triv
...
...
```
after `%sub` is destroyed, `%triv` is no longer initialized. As a
result, it's not valid to fold a destroy_addr of %agg into a sequence of
`load [copy]`s and `copy_addr`s if there's an access to `%triv` after
the `load [copy]`/`copy_addr` of `%sub` (or some intermediate
subobject).
In other words, transforming
```
copy_addr %sub
load [trivial] %triv
destroy_addr %agg
```
into
```
copy_addr [take] %sub
load [trivial] %triv
```
is invalid.
During destroy_addr folding, prevent that from happening by keeping
track of the trivial fields that have already been visited. If a
trivial field is seen more than once, then bail on folding. This is
the same as what is done for non-trivial fields except that there's no
requirement that all trivial fields be destroyed.
This attribute indicates that the given SILFunction has to be
added to "accessible functions" section and could be looked up
at runtime using a special API.
I am adding this to make it easy to determine if a SILFunction that is not inout
aliasable is captured. This is useful when emitting certain types of
diagnostics like I need to emit with move only.
I've also fixed this so that it should work on instructions that
define multiple values. Someday we'll change all the open_existential
instructions to produce different values for the type dependency and
the value result; today is not that day, though.
Remove dead `metatype` instructions which only have `debug_value` uses.
We lose debug info for such type variables, but this is a compromise we need to accept to get allocation/lock free code.
rdar://103270882
Add `deletableInstructions()` and `reverseDeletableInstructions()` in SILBasicBlock.
It allows deleting instructions while iterating over all instructions of the block.
This is a replacement for `InstructionDeleter::updatingRange()`.
It's a simpler implementation than the existing `UpdatingListIterator` and `UpdatingInstructionIteratorRegistry`, because it just needs to keep the prev/next pointers for "deleted" instructions instead of the iterator-registration machinery.
It's also safer, because it doesn't require to delete instructions via a specific instance of an InstructionDeleter (which can be missed easily).
Previously, findGuaranteedReferenceRoots always stopped searching when
finding a begin_borrow, because it's not an ownership-forwarding
instruction. Here, it is conditionally allowed to keep search through
the borrowee of that begin_borrow if it itself is guaranteed.
In performance-annotated functions optimize the pattern where a partial_apply is immediately applied.
This remove the partial apply and thus avoids an allocation.
Fixes an unnecessary performance violation error.
rdar://95155145