* SmallProjectionPath: we don't need special handling for index elements anymore
* WalkUtils: only treat `index_addr` with the `projection` flag as index projections
* AccessUtils: remove the special treatment of `index_addr`, except handling `pointer_to_address` - `index_addr` pairs
The `projection` flag indicates that `index_addr` projects an element address from an array base address, as opposed to being used for general pointer arithmetic.
When this flag is set, the result address can only reach the single element at the given index — it is not possible to chain multiple `index_addr` instructions to reach other array elements from the result.
Without this flag, the result may be used as the base of another `index_addr`, allowing arithmetic across element boundaries (e.g. an `index_addr` with index 1 followed by an `index_addr` with index 2 reaches the element at offset 3).
An `index_addr [projection]` is mandatory to go from an array base address to an element - even if it's the first element, i.e. the index is zero.
This means that the optimizer must not remove `index_addr [projection]` with a zero index.
Handle a protocol that has a default implementation that returns a ~Escapable
value and also has a typed throw that defaults to Never.
I believe this "regression" appeared when typed throws were adopted in more
APIs.
Fixes rdar://178685863 (CxxIterableIterator escapes its scope)
When the operand was changed by a pass but has a different type from
what the undef type should be, pass the correct type to killOperand
so that an undef with the right type is emitted.
When trying to pop a specific element from a SmallProjectionPath, skip `index_addr` with a non-constant index, because the index could be 0.
Otherwise `pop` would return nil which lets escape analysis think that there is no match and no escape.
Fixes a mis-compile caused by invalid escape analysis.
https://github.com/swiftlang/swift/issues/89178
rdar://177183914
The C++ `SILFunctionType` exposes both `getResults()` (formal results only)
and `getResultsWithError()` (formal + error). The Swift mirror previously
only had `results`, bridging to the with-error variant. Add `formalResults`
for the formal-only view, matching the C++ split.
Switch PackSpecialization's three result-iteration sites to `formalResults`.
The bridged `createSpecializedFunctionDeclaration` preserves the error
result on its own, so iterating with-error included it twice in the new
function's signature.
Also forward the original apply's `nothrow`/`noasync` flags to the
specialized apply, required for SIL verification of a plain apply calling
a function with an error result.
Fixes a miscompile when the index of `index_addr` is a negative integer constant. In this case two access paths were considered overlapping while in reality they reference two different array elements.
The miscompile manifested in the dead-store-elimination pass, but could potentially also show up in other passes, which use this utility.
https://github.com/swiftlang/swift/issues/77558
rdar://176820188
This is especially important for Embedded Swift because non de-virtualized deinits result in IRGen crashes.
Fixes a compiler crash in embedded
rdar://175984319
Rather than doing a standard swift runtime cast to an existential, explicitly check for the conforming instruction classes, which is much faster.
The new `isFullApplySite` and `isReturnInstruction` casting utilities are used in the (very few) time critical places in the optimizer.
After toolchain builders are upgraded to a compiler version which includes the fix for this problem (https://github.com/swiftlang/swift/pull/88270), we don't need this workaround anymore and the regular `as`/`is` casts can be used again.
Now the runtime casts doesn't show up prominently in compile-time profiling data anymore - even with a host compiler which doesn't implement fast type checks, yet.
rdar://173916206
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:
- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
projection. It is only allowed for enums whose projection operation is
nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
invalidating the enum and leaving the payload to be further consumed.
This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
The instruction takes a second operand for "scratch" space, which the
enum representation may be copied into in order to avoid invalidating the
enum value, so the result is dependent on the lifetime of both the
original enum and the scratch buffer. This allows for borrowing switches
over resilient enums.
`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.
Fixes rdar://174952822.
Now that we have generalized existentials in Embedded Swift, we also
have all of the infrastructure for metatypes. They're lazily
constructed on an as-needed basis, but otherwise work the same way as
in non-Embedded Swift.
Fixes rdar://145706221.
The original implementation of `mayAccessPointer` did look through `address_to_pointer` - `pointer_to_address` pairs and therefore not detect such pointers.
Fixes a miscompile
rdar://174268466
Conformance entries are used for fast conformance lookup, which doesn't need to query the runtime's conformance lookup table.
A conformance entry specifies if the class conforms or does not conform to a protocol.
At runtime, a type cast instruction to an existential can directly load the witness table pointer from the VTable.
If null, the class does not conform to the protocol.
This optimization replaces (the very inefficient) RawRepresentable comparison to a simple compare of enum tags.
However if the raw type is a custom type we don't know how the comparison is implemented.
A custom raw type can implement the case comparison in a way that comparing different cases will return `true`.
Therefore only do the optimization for known stdlib raw value types.
Fixes a mis-compile
https://github.com/swiftlang/swift/issues/87906
rdar://172746003
Support folding `differentiable_function_extract` of
`differentiable_function` in presence of borrowed scopes. Such folding
is crucial for VJP inlining, which is required for AutoDiff closure
specialization (ADCS) pass working properly.
Such handling was not required previously, but now ADCS runs in presence
of OSSA, making handling of borrowed scopes essential.
The folding logic is based on similar logic for
`struct`/`struct_extract` simplification.
Note that the `AutoDiff/SILOptimizer/licm_context.swift` test needs to
be modified since it relies on specific inlining behavior. Particularly,
we need to force inlining of the implicitly generated VJP of `B.a()`
into the VJP of `q()`. Without `@inline(__always)`, this particular
inlining decision stops happening on MacOS because the SIL combiner
changes from this patch affect the inlining decisions.
The changes from this patch make some new inlining decisions possible to
be taken befor attempting to inline the VJP of `B.a()` into the VJP of
`q()`. As a result, the VJP of `B.a()` becomes bigger because of other
VJPs being inlined into that, and the inlining cost of `B.a()` VJP
becomes too high when trying to perform inlining inside the VJP of
`q()`.
Depends on #87859 to allow force-inlining in
`AutoDiff/SILOptimizer/licm_context.swift`.
For very large functions this optimization can run into noticeable quadratic behavior.
Therefore, ignore functions with more than 100000 SIL instructions.
This limit is large enough to not affect most of real-world SIL functions.
* All SIL modifications must go through a `MutatingContext`. Therefore replace the simple setter for `isNested` with `set(isNested:, context)`
* It's better to add a `isNested` parameter for `Builder.createPartialApply` than to set it after each construction of a `partial_apply`, which can easily be missed.