This flag is important for following optimizations. Therefore such `end_cow_mutation` instructions must not be removed.
Also, keep the flag in a SILCombine transformation.
rdar://119178823
* add `NominalTypeDecl.isResilient`
* make the return type of `Type.getNominalFields` optional and return nil in case the nominal type is resilient.
This forces users of this API to think about what to do in case the nominal type is resilient.
Try to replace a begin_borrow with its owned operand.
This is either possible if the borrowed value (or a forwarded value if it) is copied:
```
%1 = begin_borrow %0
%2 = struct_extract %1 // a chain of forwarding instructions
%3 = copy_value %1
// ... uses of %3
end_borrow %1
```
->
```
%1 = copy_value %0
%3 = destructure_struct %0 // owned version of the forwarding instructions
// ... uses of %3
```
Or if the borrowed value is destroyed immediately after the borrow scope:
```
%1 = begin_borrow %0
%2 = struct_extract %1 // a chain of forwarding instructions
// ... uses of %2
end_borrow %1
destroy_value %1 // the only other use of %0 beside begin_borrow
```
->
```
%2 = destructure_struct %0 // owned version of the forwarding instructions
// ... uses of %2
destroy_value %2
```
Make filter APIs for UseList chainable by adding them to Sequence where Element == Operand
For example, it allows to write:
```
let singleUse = value.uses.ignoreDebugUses.ignoreUsers(ofType: EndAccessInst.self).singleUse
```
Also, add `UseList.getSingleUser(notOfType:)`
Introduce two modes of bridging:
* inline mode: this is basically how it worked so far. Using full C++ interop which allows bridging functions to be inlined.
* pure mode: bridging functions are not inlined but compiled in a cpp file. This allows to reduce the C++ interop requirements to a minimum. No std/llvm/swift headers are imported.
This change requires a major refactoring of bridging sources. The implementation of bridging functions go to two separate files: SILBridgingImpl.h and OptimizerBridgingImpl.h.
Depending on the mode, those files are either included in the corresponding header files (inline mode), or included in the c++ file (pure mode).
The mode can be selected with the BRIDGING_MODE cmake variable. By default it is set to the inline mode (= existing behavior). The pure mode is only selected in certain configurations to work around C++ interop issues:
* In debug builds, to workaround a problem with LLDB's `po` command (rdar://115770255).
* On windows to workaround a build problem.
All SILArgument types are "block arguments". There are three kinds:
1. Function arguments
2. Phis
3. Terminator results
In every situation where the source of the block argument matters, we
need to distinguish between these three. Accidentally failing to
handle one of the cases is an perpetual source of compiler
bugs. Attempting to handle both phis and terminator results uniformly
is *always* a bug, especially once OSSA has phi flags. Even when all
cases are handled correctly, the code that deals with data flow across
blocks is incomprehensible without giving each case a type. This
continues to be a massive waste of time literally every time I review
code that involves cross-block control flow.
Unfortunately, we don't have these C++ types yet (nothing big is
blocking that, it just wasn't done). That's manageable because we can
use wrapper types on the Swift side for now. Wrapper types don't
create any more complexity than protocols, but they do sacrifice some
usability in switch cases.
There is no reason for a BlockArgument type. First, a function
argument is a block argument just as much as any other. BlockArgument
provides no useful information beyond Argument. And it is nearly
always a mistake to care about whether a value is a function argument
and not care whether it is a phi or terminator result.
Although empty blocks are cleaned up at the end of every Simplification pass, it's not legal SIL to have empty blocks and subsequent simplification passes may crash because of this.
rdar://115169880
For a redundant pair of pointer-address conversions, e.g.
%2 = address_to_pointer %1
%3 = pointer_to_address %2 [strict]
replace all uses of %3 with %1.
It is necessary for opaque values where for casts that will newly start
out as checked_cast_brs and be lowered to checked_cast_addr_brs, since
the latter has the source formal type, IRGen relies on being able to
access it, and there's no way in general to obtain the source formal
type from the source lowered type.
`ownership` is a bad name in `LoadInst`, because it hides `Value.ownership`.
Therefore rename it to `loadOwnership`.
Do the same for ownership in StoreInst to be consistent.
Look through `upcast` and `init_existential_ref` instructions and replace the operand of this cast instruction with the original value.
For example:
```
%2 = upcast %1 : $Derived to $Base
%3 = init_existential_ref %2 : $Base : $Base, $AnyObject
checked_cast_br %3 : $AnyObject to Derived, bb1, bb2
```
This makes it more likely that the cast can be constant folded because the source operand's type is more accurate.
In the example above, the cast reduces to
```
checked_cast_br %1 : $Derived to Derived, bb1, bb2
```
which can be trivially folded to always-succeeds.
Found while looking at `_SwiftDeferredNSDictionary.bridgeValues()`
Optimize the sequence
```
%1 = init_enum_data_addr %enum_addr, #someCaseWithPayload
store %payload to %1
inject_enum_addr %enum_addr, #someCaseWithPayload
```
to
```
%1 = enum $E, #someCaseWithPayload, %payload
store %1 to %enum_addr
```
This sequence of three instructions must appear in consecutive order.
But usually this is the case, because it's generated this way by SILGen.
This comes up in the code for constructing an empty string literal.
With this optimization it's possible to statically initialize empty string global variables.
* add the StaticInitCloner utility
* remove bridging of `copyStaticInitializer` and `createStaticInitializer`
* add `Context.mangleOutlinedVariable` and `Context.createGlobalVariable`
* move the apply of partial_apply transformation from simplify-apply to simplify-partial_apply
* delete dead partial_apply instructions
* devirtualize apply, try_apply and begin_apply
Eliminate the redundant instruction pair
```
%t = tuple (%0, %1, %2)
(%3, %4, %5) = destructure_tuple %t
```
and replace the results %3, %4, %5 with %0, %1, %2, respectively.
The same for structs.
A type (mostly classes) can be attributed with `@_semantics("arc.immortal")`.
ARC operations on values of such types are eliminated.
This is useful for the bridged SIL objects in the swift compiler sources.
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
* begin_cow_mutation
* global_value
* strong_retain and strong_release
So far, those simplifications did only run in SILCombine. Now they are also considered in the swift Simplification pass.