Which consists of
* removing redundant `address_to_pointer`-`pointer_to_address` pairs
* optimize `index_raw_pointer` of a manually computed stride to `index_addr`
* remove or increase the alignment based on a "assumeAlignment" builtin
This is a big code cleanup but also has some functional differences for the `address_to_pointer`-`pointer_to_address` pair removal:
* It's not done if the resulting SIL would result in a (detectable) use-after-dealloc_stack memory lifetime failure.
* It's not done if `copy_value`s must be inserted or borrow-scopes must be extended to comply with ownership rules (this was the task of the OwnershipRAUWHelper).
Inserting copies is bad anyway.
Extending borrow-scopes would only be required if the original lifetime of the pointer extends a borrow scope - which shouldn't happen in save code. Therefore this is a very rare case which is not worth handling.
And move the implementation of `SIL.Type.canBeClass` to the AST Type. The SIL Type just calls the AST Type implementation.
Also rename `SIL.Type.canonicalASTType` -> `SIL.Type.astType`.
Canonicalize a `fix_lifetime` from an address to a `load` + `fix_lifetime`:
```
%1 = alloc_stack $T
...
fix_lifetime %1
```
->
```
%1 = alloc_stack $T
...
%2 = load %1
fix_lifetime %2
```
This transformation is done for `alloc_stack` and `store_borrow` (which always has an `alloc_stack` operand).
The benefit of this transformation is that it enables other optimizations, like mem2reg.
This peephole optimization was already done in SILCombine, but it didn't handle store_borrow.
A good opportunity to make an instruction simplification out of it.
This is part of fixing regressions when enabling OSSA modules:
rdar://140229560
* Remove dead `load_borrow` instructions (replaces the old peephole optimization in SILCombine)
* If the `load_borrow` is followed by a `copy_value`, combine both into a `load [copy]`
Replace destructure_tuple with tuple_extract instructions and destructure_struct with struct_extract instructions.
This canonicalization helps other optimizations to e.g. CSE tuple_extract/struct_extract.
As the optimizer uses more and more AST stuff, it's now time to create an "AST" module.
Initially it defines following AST datastructures:
* declarations: `Decl` + derived classes
* `Conformance`
* `SubstitutionMap`
* `Type` and `CanonicalType`
Some of those were already defined in the SIL module and are now moved to the AST module.
This change also cleans up a few things:
* proper definition of `NominalTypeDecl`-related APIs in `SIL.Type`
* rename `ProtocolConformance` to `Conformance`
* use `AST.Type`/`AST.CanonicalType` instead of `BridgedASTType` in SIL and the Optimizer
This makes ManagedBuffer available and usable in Embedded Swift, by:
- Removing an internal consistency check from ManagedBuffer that relies on metatypes.
- Making the .create() API transparent (to hoist the metatype to the callee).
- Adding a AllocRefDynamicInst simplification to convert `alloc_ref_dynamic` to `alloc_ref`, which removes a metatype use.
- Adding tests for the above.
We need to compare the not lowered types, because function types may differ in their original version but are equal in the lowered version, e.g.
```
((Int, Int) -> ())
(((Int, Int)) -> ())
```
Fixes a miscompile
The buffer of global arrays could already be statically initialized.
The missing piece was the array itself, which is basically a reference to the array buffer.
For example:
```
var a = [1, 2, 3]
```
ends up in two statically initialized globals:
1. the array buffer, which contains the elements
2. the variable `a` which is a single reference (= pointer) of the array buffer
This optimization removes the need for lazy initialization of such variables.
rdar://127757554
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
Enable KeyPath/AnyKeyPath/PartialKeyPath/WritableKeyPath in Embedded Swift, but
for compile-time use only:
- Add keypath optimizations into the mandatory optimizations pipeline
- Allow keypath optimizations to look through begin_borrow, to make them work
even in OSSA.
- If a use of a KeyPath doesn't optimize away, diagnose in PerformanceDiagnostics
- Make UnsafePointer.pointer(to:) transparent to allow the keypath optimization
to happen in the callers of UnsafePointer.pointer(to:).
We've been building up this exponential explosion of task-creation
builtins because it's not currently possible to overload builtins.
As long as all of the operands are scalar, though, it's pretty easy
to peephole optional injections in IRGen, which means we can at
least just use a single builtin in SIL and then break it apart in
IRGen to decide which options to set.
I also eliminated the metadata argument, which can easily be recreated
from the substitutions. I also added proper verification for the builtin,
which required (1) getting `@Sendable` right more consistently and (2)
updating a bunch of tests checking for things that are not actually
valid, like passing a function that returns an Int directly.
It notifies the pass manager that the optimization result of the current pass depends on the body (i.e. SIL instructions) of another function than the currently optimized one.
Optionally, the dependency to the initialization of the global can be specified with a dependency token `depends_on <token>`.
This is usually a `builtin "once"` which calls the initializer for the global variable.
The previous implementation just checked that a value's only uses besides the begin_borrow were destroys. That's insufficient to say the value is destroyed after the borrow (i.e. that all its destroys are dominated by the borrow). Add the relevant dominance check.
Fixes a compiler crash
rdar://119873930