These will never appear in the source language, but can arise
after substitution when the original type is a tuple type with
a pack expansion type.
Two examples:
- original type: (Int, T...), substitution T := {}
- original type: (T...), substitution T := {Int}
We need to model these correctly to maintain invariants.
Callers that previously used to rely on TupleType::get()
returning a ParenType now explicitly check for the one-element
case instead.
Arguments whose lifetimes are not lexical should be hoisted without
respect to deinit barriers. On the other hand, inout arguments
explicitly annotated @_lexical should respect deinit barriers.
Previously, whenever an alloc_stack [lexical] was seen, optimization
bailed conservatively.
In the fullness of time, we should optimize an alloc_stack [lexical] so
long as:
(1) the root of the source of the store/copy_addr is lexical
(2) the range in which the alloc_stack [lexical] contains the value
store'd/copy_addr'd into it (i.e. the range ending at
destroy_addr/etc) is contained within the live range of that lexical
root
Here, an incremental step in that direction is taken: if the base of the
accessed storage of the source of a copy_addr is a guaranteed function
argument, then we know
(1) the base is lexical--guaranteed function arguments are always
lexical
(2) the range in which the alloc_stack contains the value copy_addr'd in
is trivially contained within the range of that lexical root--the
live range of a guaranteed function argument is the whole function
Added TODOs for the full optimization.
Previously, whenever an alloc_box that was promoted to an alloc_stack,
the new alloc_stack would be lexical. The result was that alloc_boxes
which didn't need (or explicitly didn't want, in the case of eager move
vars) received lexical alloc_stacks.
Here, only add the lexical flag to the new alloc_stack instruction if
any of the box's uses are `begin_borrow [lexical]`. That way,
alloc_boxes end up having lexical alloc_stacks only if they were
"lexical alloc_boxes".
With the change to include `SmallVector.h` directly in `LLVM.h` rather
than forward declaring in the only case it matters (ie. Clang <= 5),
these fixes are no longer needed. Since defaulted version is preferred
when there's no better choice (which is presumably the case if that's
how they were originally added), use it instead. Some uses were instead
changed to add `llvm::` so remove that too.
Andy some time ago already created the new API but didn't go through and update
the old occurences. I did that in this PR and then deprecated the old API. The
tree is clean, so I could just remove it, but I decided to be nicer to
downstream people by deprecating it first.
Previously, for the BridgedProperty pattern, there were two flavors of
outlined function that would be formed, varying on the ownership of the
instance whose field is being access:
(1) guaranteed_in -- for use by addresses
(2) unowned -- for use by values which were not destroyed until some
time after the pattern of interest is matched
Now that the lifetime of the instance may be shortened to just after the
call to the objc method, the latter of these is not appropriate for
values. We would have to re-extend the lifetime until after the method
returns.
Instead, here, we add a new variant
(3) owned -- for use by values which were destroyed just after the objc
method call
Doing so requires new mangling.
Thanks to CopyPropagation canonicalizing all values, not just those for
which there is a copy_value instruction, the lifetime of the value that
is loaded in the BridgedProperty pattern is shortened and the
destroy_value appears right after its use rather than after the full CFG
for the bridged property. Updated the BridgedProperty pattern to match
that newly hoisted instruction.
Previously, the lifetimes of only values which were copied were
canonicalized during the non-mandatory CopyPropagation pass. The
mandatory pass (i.e. MandatoryCopyPropagation) has been disabled,
meaning that non-copied values lifetimes were never canonicalized. So
enable canonicalization of all lifetimes during regular CopyPropagation.
rdar://54335055
Previously, the match failed to find the larger sequence that began with
load [copy] and ended with destroy_value because the iterator advanced
after finding the load [copy]. Advanced the iterator here.
Enables reverting the test outlining test changes introduced in
a52b8966c6.
In case of a borrowed `alloc_box`, the optimization didn't look through the `begin_borrow` when calculating the final release of the box.
This resulted in inserting the destroy of the inserted `alloc_stack` too early.
rdar://97087762
This was missing. It's not a big problem, but should be done correctly.
I noticed this because changes didn't get printed when I used `-sil-print-function`.
The new intrinsic, exposed via static functions on Task<T, Never> and
Task<T, Error> (rethrowing), begins an asynchronous context within a
synchronous caller's context. This is only available for use under the
task-to-thread concurrency model, and even then only under SPI.
Co-routines (called by `begin_apply`) may allocate and therefore it’s important to always inline them.
Also, refactor the code a bit to fix the if-changed-then-return-true logic.
rdar://94833845
This bug triggered a "instruction isn't dominated by its operand" verifier crash.
Or - if the verifier doesn't run - a crash later in IRGen.
rdar://94376582
IterableBackwardReachability just requires an iterable list of gens.
ShrinkBorrowScope, LexicalDestroyHoisting, and SSADestroyHoisting all
need to be able to check whether a given instruction is scope ending
quickly. Use a SmallSetVector rather than a SmallVector for the gens in
all three.
Instead of doing one or two non-iterative BackwardReachability runs,
do a single run of IterativeBackwardReachability. During that, pause
after discovery/local dataflow and use VisitBarrierAccessScopes to
determine which end_access instructions in the discovered region are
barriers. Add those instructions as kills to the dataflow. Finally run
the global dataflow.
Enables SSADestroyHoisting to hoist destroys over loops.
Addresses a correctness issue where access scopes which were open at
barrier blocks were not promoted to barriers, resulting in destroy_addrs
getting hoisted into unrelated access scopes.
We must no pre-specialize imported code (except if this was explicitly
called for by the importing module).
Therefore, don't pre-specialize `shared` definitions based on their
pre-specialization attributes.
Rather, only pre-specialize if the pre-specialization is called for
using a `target: "theFunctionToSpecialize"` parameter.
Run OnonePrespecializations before serialization so that module native functions
are not yet marked `shared` and can be identified as native.
rdar://92337361
Jump threading in an unreachable CFG region can lead to a crash (in an assert compiler) or hang (in an no-assert compiler) in `ValueBase::replaceAllUsesWith`.
Unfortunately I couldn't come up with an isolated SIL test case.
rdar://92267349