It hoists `destroy_value` instructions without shrinking an object's lifetime.
This is done if it can be proved that another copy of a value (either in an SSA value or in memory) keeps the referenced object(s) alive until the original position of the `destroy_value`.
```
%1 = copy_value %0
...
last_use_of %0
// other instructions
destroy_value %0 // %1 is still alive here
```
->
```
%1 = copy_value %0
...
last_use_of %0
destroy_value %0
// other instructions
```
The benefit of this optimization is that it can enable copy-propagation by moving destroys above deinit barries and access scopes.
It can happen that the SSAUpdater inserts a phi-argument with all incoming values being the same.
If a value is requested in the phi-block we must not use the unique incoming value, but we have to re-use the phi argument, because the lifetime of the incoming values end at in the predecessor blocks.
rdar://129859331
It removes a `copy_value` where the source is a guaranteed value, if possible:
```
%1 = copy_value %0 // %0 = a guaranteed value
// uses of %1
destroy_value %1 // borrow scope of %0 is still valid here
```
->
```
// uses of %0
```
This optimization is very similar to the LoadCopyToBorrow optimization.
Therefore I merged both optimizations into a single file and renamed it to "CopyToBorrowOptimization".
DCE deletes ownership forwarding instructions when it doesn’t have useful users.
It inserts destroy_value/end_borrow for its operands to compensate their lifetimes.
DCE also deletes branches when its successor blocks does not have useful instructions.
It deletes blocks and creates a jump to the nearest post dominating block.
When DCE needs to delete a forwarding instruction in a dead block, it cannot just create
lifetime ends of its operands at its position. Use LifetimeCompletion utility in such cases.
rdar://140428721
ConditionForwarding is able to handle owned values and non-local guaranteed values.
Remove incorrect assertion about enum trivialiaty
Fixes rdar://140977875
This patch adds false positive detection to sil-stats-lost-variables.
We will now only detect a debug_value as lost if there is a real
instruction which belongs to the same scope or a child scope of the
scope of the debug_value and if they are both inline at the same
location.
//a
Because discovery of defs walks into reborrows and borrowed-from
instructions, copies may be seen whose underlying value is a guaranteed
value (namely, a reborrow or a borrowed-from instruction). Such copies
may be used beyond the lifetime end of such guaranteed values, so it's
not allowed to sink copies to their consuming uses. Such
canonicalization is the responsibility of the OSSACanonicalizeGuaranteed
utility.
rdar://139842132
The utility performs two def-use traversals. The first determines
liveness from uses. The second rewrites copies.
Previously, the defs whose uses were analyzed were discovered twice,
once during each traversal. The non-triviality of the discovery logic
(i.e. the logic determining when to walk into the values produced by the
instructions which were the users of visited uses) opened the
possibility for a divergence between the two discoveries. This
possibility had indeed been realized--the two traversals didn't visit
exactly the same uses, and issues ensue.
Here, the defs whose uses are analyzed are discovered only once (and not
discarded as their uses are analyzed) during the first traversal. The
second traversal reuses the defs discovered in the first traversal,
eliminating the possibility of a def discovery difference.
The second traversal is now done in a different order. This results in
perturbing the SIL in certain cases.
In preparation for only recording the defs once, replace the
GraphNodeWorklist of defs with a SetVector. Preserve the current
visitation order by creating a worklist of indices to be visited.
When rewriting uses, determine how that rewriting should proceed based
on the kind of def whose use is being visited. Direct uses of reborrows
and borrowed-froms never need to be rewritten because every such use is
a use of a guaranteed value and can never require a copy.
Add a type which distinguishes among the types of defs that are pushed
onto the "def-use worklist". Note that it's not possible to rely on the
kind of value because the root may itself be a copy_value. For now, the
distinction is discarded as soon as the def is visited.
As autodiff happens on function types it is not in general possible to determine the real expansion context of the function being differentiated. Use of minimal context is a conservative approach that should work even when libraty evolution mode is enabled.
Fixes#55179
In terms of the test suite the only difference is that we allow for non-Sendable
types to be returned from nonisolated functions. This is safe due to the rules
of rbi. We do still error when we return non-Sendable functions across isolation
boundaries though.
The reason that I am doing this now is that I am implementing a prototype that
allows for nonisolated functions to inherit isolation from their caller. This
would have required me to implement support both in Sema for results and
arguments in SIL. Rather than implement results in Sema, I just finished the
work of transitioning the result checking out of Sema and into SIL. The actual
prototype will land in a subsequent change.
rdar://127477211
It replaces `DeclAttr::getUnavailable()` and `AvailableAttr::isUnavailable()`
as the designated way to query for the attribute that makes a decl unavailable.
Unfortunately, importing them as is results in ambiguous call sites.
E.g., std::vector::push_back has overloads for lvalue reference and
rvalue reference and we have no way to distinguish them at the call site
in Swift. To overcome this issue, functions with rvalue reference
parameters are imported with 'consuming:' argument labels.
Note that, in general, move only types and consuming is not properly
supported in Swift yet. We do not invoke the dtor for the moved-from
objects. This is a preexisting problem that can be observed with move
only types before this PR, so the fix will be done in a separate PR.
Fortunately, for most types, the moved-from objects do not require
additional cleanups.
rdar://125816354
Propagating array element values is done by load-simplification and redundant-load-elimination.
So ArrayElementPropagation is not needed anymore.
ArrayElementPropagation also replaced `Array.append(contentsOf:)` with individual `Array.append` calls.
This optimization is removed, because the benefit is questionably, anyway.
In most cases it resulted in a code size increase.
Some terminator instructions can have type-dependent operands.
Therefore we need to use `getNumRealOperands` instead of `getNumOperands`.
Fixes a compiler crash.
When performance diagnostics were introduced, typed throws didn't exist
so it was not generally possible to have throws anywhere without
triggering performance diagnostics. As a short term hack, we disabled
checking of `throw` instructions and the basic blocks that terminate
in a `throw`.
Now that typed throws is available and can be used to eliminate
allocations with error handling, remove all of the hacks. We'll now
diagnose attempts to throw or catch existential values (e.g., the `any
Error` used for untyped throws), but typed throws are fine.
Increase inlining benefits for functions with more than 5 arguments and / or results.
We assume that each argument beyond these 5 would be passed on stack and therefore would incur a pair of load and store.