Commit Graph

2059 Commits

Author SHA1 Message Date
Erik Eckstein 541664237c Optimizer: add the MergeBorrowScopes pass
The pass merges to adjacent borrow scopes in a basic block.

```
  %2 = begin_borrow %1
  use(%2)
  end_borrow %2
  ...
  %6 = begin_borrow %1
  use(%6)
  end_borrow %6

```
->
```
  %2 = begin_borrow %1
  use(%2)
  ...
  use(%2)
  end_borrow %2
```

This helps other optimizations, like common-subexpression-elimination, because the borrow liveranges are larger and not split.
2026-06-10 08:18:51 +02:00
Andrew Trick 9e52c74283 Merge pull request #89778 from atrick/fix-deadend-escape
Fix LifetimeDependence scope analysis to recognize throws of Never.
2026-06-09 21:58:32 -07:00
Erik Eckstein 8949e1387e Optimizer: simplify index_addr and index_raw_pointer
Which replaces the old index_addr SIL combine optimization
2026-06-09 16:17:53 +02:00
Erik Eckstein 93a97200a5 SIL: correctly handle index_addr with the new projection flag in various SIL utilities
* 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
2026-06-09 16:17:53 +02:00
Erik Eckstein 7ea1b1b23e SIL: add a flag [projection] to index_addr
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.
2026-06-09 16:17:53 +02:00
Erik Eckstein db9833d1a9 Optimizer: move PointerToAddressInst.isResultOfUnsafeAddressor from AccessUtils.swift to LifetimeDependenceUtils.swift
Where it's used.
NFC
2026-06-09 16:17:52 +02:00
Andrew Trick 91046aff37 Fix LifetimeDependence scope analysis to recognize throws of Never.
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)
2026-06-08 21:28:08 -07:00
Anthony Latsis bdb420bac2 Merge pull request #89413 from swiftlang/jepa-rebranch2
SILOptimizer: Adjust to "[Support][NFCI] Store DomTree children as linked list (#176409)"
2026-06-06 03:03:02 +01:00
Emil Pedersen 27097e101c [DebugInfo] Add optional type argument to killOperand
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.
2026-06-04 16:08:48 +01:00
Emil Pedersen 019251f8b3 [DebugInfo] Salvage enums in SimplifyAllocStack
When the value of an enum discriminator is known but the payload unknown
(for example, an Optional that we know is non-nil), salvage the value
using a debug reconstruction block that recreates the enum using the
payload and the known discriminator.
2026-06-04 16:08:48 +01:00
Emil Pedersen 9e5925c483 [DebugInfo] Bridge debug block related functions to Swift
Add bridging for debug reconstruction blocks so Swift passes can have
access to them and can salvage instructions.

Assisted-by: Claude
2026-06-04 16:08:48 +01:00
Anthony Latsis 755e1787f6 SILOptimizer: Adjust to "[Support][NFCI] Store DomTree children as linked list (#176409)"
See https://github.com/llvm/llvm-project/pull/176409.
2026-06-04 08:52:56 +01:00
eeckstein 3b3c190702 Merge pull request #89656 from eeckstein/simplify-unchecked-ownership-conversion
Optimizer: add simplification for `unchecked_ownership_conversion`
2026-06-03 15:58:04 +02:00
Aidan Hall 17b9ba32f9 Merge pull request #89260 from aidan-hall/pack-opt-simplify-alloc-pack
Eliminate Unnecessary `alloc_pack` instructions
2026-06-03 10:20:49 +01:00
Erik Eckstein 40c3598cc3 Optimizer: add simplification for unchecked_ownership_conversion
Replaces a sequence which is commonly found in generated class destructors:

```
  %1 = some_owned_value
  %2 = begin_borrow %1                // the only use of %1
  %3 = unchecked_ref_cast %2 to $C
  %4 = unchecked_ownership_conversion %3, @guaranteed to @owned
  end_borrow %2
  end_lifetime %1
```
->
```
  %1 = some_owned_value
  %2 = begin_borrow %1                // now dead
  end_borrow %2
  %4 = unchecked_ref_cast %1 to $C
```
2026-06-03 07:06:58 +02:00
Erik Eckstein 0d8c89b2ef SIL: let UncheckedOwnershipConversionInst and SwitchEnumInst conform to UnaryInstruction 2026-06-03 07:06:58 +02:00
Erik Eckstein c588393f00 Optimizer: add hasOnlyUsers(ofType:) for Operand sequences 2026-06-03 07:06:35 +02:00
eeckstein 09dfb9b25b Merge pull request #89594 from eeckstein/fix-escape-analysis
SIL: fix handling of non-constant address indices in SmallProjectionPath
2026-06-01 21:52:32 +02:00
elsa be6322ed43 [CSE] Add missing call to completeLifetimes when needed (#89570)
Resolves rdar://177962122.

The new CSE pass rewrite failed to call completeLifetimes when needed,
which resulted in assertion crashes.
2026-06-01 12:11:33 -07:00
Erik Eckstein 1d0eacc4be SIL: fix handling of non-constant address indices in SmallProjectionPath
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
2026-06-01 12:39:03 +02:00
Erik Eckstein 5ea6e80da0 RedundantLoadElimination: insert a drop_deinit when splitting stores of types with a deinit
A `drop_deinit` is required to make the SIL verifier happy.

Fixes a SIL verifier crash
rdar://176373062
2026-06-01 08:13:28 +02:00
Erik Eckstein 841ad684a6 SIL: add Builder.createDropDeinit 2026-06-01 06:30:10 +02:00
Aidan Hall b112540676 Packs: Salvage debug info when eliminating alloc_pack 2026-05-29 10:50:25 +01:00
Aidan Hall 97bc328605 Simplification: Simplify alloc_pack 2026-05-29 10:42:36 +01:00
Andrew Trick a133bab977 Fix LifetimeDependenceDiagnostics - disable noescape function args
In LifetimeDependenceDiagnostics, disable diagnostics of function arguments that
have a noescape function type. Diagosing noescape function-type arguments is
meant to be handled by a separate pass, DiagnoseInvalidEscapingCaptures. In some
distant future, we could consider merging these diagnostics. For now, they
should be independent.

This fixes a bug introduced with:

commit e3d55f64c2
Date:   Wed Apr 29 10:37:32 2026 +0100

    Lifetimes: Treat noescape function types as ~Escapable

After that change, lifetime diagnostics inadvertantly kicked on for noescape
function-type arg. The diagnostic would then fail when importing ObjC API with
an optional noescape function such as:

+ (instancetype)takeNoEscapeBlock:(void(NS_NOESCAPE ^)(void))block;
// error: lifetime-dependent variable 'block' escapes its scope)

Here the compiler generates a thunk to unwrap the optional and generates a
mark_dependence on the Optional's inner value.

Fixes rdar://177381648 - error: lifetime-dependent variable escapes its scope
2026-05-28 16:21:43 -07:00
Meghana Gupta 6dc6206256 Merge pull request #89383 from meg-gupta/fixlicm
Fix LICM producing illegal load [trivial] on non-trivial address types
2026-05-26 10:51:56 -07:00
Meghana Gupta adf9b5c94b Fix LICM producing illegal load [trivial] on non-trivial address types
The LICM pass's hoistAndSinkLoadAndStore incorrectly determined load/store
ownership based on firstStore.storeOwnership rather than the address type.

This PR fixes it by determining ownership based on the address type's triviality:
2026-05-22 16:55:46 -07:00
Gábor Horváth fd83990fc4 Merge pull request #89350 from Xazax-hun/immortal-ref-fix
[cxx-interop] Fix invalid peephole optimization for immortal FRTs
2026-05-22 20:14:52 +01:00
Gabor Horvath dc6a14d06c [cxx-interop] Fix invalid peephole optimization for immortal FRTs
Immortal foreign reference types never need release or retain operations
in Swift, they are represented as trival types, i.e, they can be copied/loaded
without any refcount operations. Some peepholes introducing upcast or
unchecked_ref_cast on the archetype which is not trivial. As a result,
we ended up with SIL that failed to pass verification, we tried to do
trivial operations on a non-trivial type.

This PR disables the peephole optimizations when the triviality of the
address type differs from the triviality of the type after the
transformation.

rdar://177549159
2026-05-22 15:16:16 +01:00
Aidan Hall 7dcbf20dd7 Merge pull request #88914 from aidan-hall/pack-opt-substitution-cloner
- Canonicalize dynamic_pack_index and pack_pack_index to scalar_pack_index. 
- Replace opened Pack Element types with concrete types when statically known (i.e. when open_pack_element uses a scalar_pack_index) in SILCloner.
- Add a simplification for tuple_pack_element_addr to replace it with tuple_element_addr when it uses a scalar_pack_index. This is near-identical to the existing SILCombine visitor for tuple_pack_element_addr (which worked for dynamic_pack_index).

TODO: Fix or remove old SILCombine visitors for pack instructions that are broken or made obsolete by this change.
2026-05-22 13:15:47 +01:00
Daniil Kovalev d5eba5d245 [AutoDiff] SILCombine: handle convert_function use of differentiable_function (#88919)
The patch enhances sil-combiner handling of `differentiable_function` by
adding support for `convert_function` which is further used in
`differentiable_function_extract`:

```
  %0 = differentiable_function ... %x
  %1 = begin_borrow %0
  %2 = convert_function %1 to ...
  %3 = differentiable_function_extract [xxx] %2
  // use of %3
```

-->

```
  %0 = differentiable_function ... %x
  // use of %x
```
2026-05-21 18:47:22 +00:00
Aidan Hall 51dec85971 Simplify tuple_pack_element_addr with scalar_pack_index
If a tuple_pack_element_addr uses a scalar_pack_index rather than a
dynamic_pack_index, we can replace it with tuple_element_addr, since the
specific tuple element accessed is statically known.
2026-05-21 18:00:40 +01:00
Erik Eckstein 096ede496f LoopInvariantCodeMotion: fix an ownership error caused by hoisting trivial sub-projection loads
If `load [trivial]` only loads a "part" of a stored value, which itself is non-trivial, the pass crashes with an ownership error.
The fix is to wrap the projection instructions (e.g. `struct_extract`) inside a borrow scope. This is correctly done in `createProjectionAndCopy`.

https://github.com/swiftlang/swift/issues/89255
rdar://177430359
2026-05-21 08:18:02 +02:00
Erik Eckstein 83739a0462 LoopInvariantCodeMotion: fix a crash when trying to hoist load [take]
So far we supported hoisting a `load [take]` which "takes" just a part of a stored value (i.e. a projected value).
This works as long as no other struct/tuple field is also loaded in the loop.
If this is the case it causes an ownership error.
The fix is to disallow hoisting projected `load [take]` instructions.
2026-05-21 07:54:09 +02:00
Erik Eckstein f11dac4946 SimplifyPointerToAddress: don't require strict when removing address_to_pointer-pointer_to_address pairs with matching types
rdar://177220346
2026-05-19 19:02:37 +02:00
Aidan Hall 070f7923d9 Bridging: Rename FunctionConvention.results to resultsWithError
This matches the name of the C++ method it bridges, and avoids the ambiguity of
the previous name.
2026-05-18 14:47:05 +01:00
Ben Cohen ad8a8f7cc8 SILOptimizer: add FunctionConvention.formalResults; use it in PackSpecialization
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.
2026-05-18 14:45:26 +01:00
elsa 83d4291709 CSE Optimizer Pass rewrite (#88248)
Resolves rdar://173862129
2026-05-15 19:11:10 +01:00
Daniil Kovalev aa8f1d7efd [AutoDiff] Fix crash due to use after consume in differentiable_function (#88918)
The patch implements proper sil-combiner handling of
`differentiable_function` for cases when extractee has non-trivial
ownership. In such casese, it is consumed by the differentiable_function
instruction. We must copy the extractee before the consumption point so
the copy remains live afterward.

Fixes #88816
2026-05-13 21:33:13 +00:00
Erik Eckstein 8e6560aa78 SIL: fix handling of index_addr in AccessUtils
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
2026-05-12 19:59:37 +02:00
Egor Zhdan 919f56364a Merge pull request #82216 from swiftlang/egorzhdan/rm-xcode-12-workaround
[SwiftCompilerSources][build] Remove a workaround for missing libc++ in the SDK
2026-05-11 16:58:13 +01:00
Andrew Trick 2dca2e48c4 Merge pull request #88980 from atrick/fix-immortal-init
LifetimeDependenceDiagnostics: calls with no deps are immortal
2026-05-09 14:22:17 -07:00
Andrew Trick f41daa2087 Merge pull request #88968 from atrick/fix-makeborrow-escape
LifetimeDependenceDiagnostics: add Builtin.makeBorrow support
2026-05-08 17:20:46 -07:00
Andrew Trick 4845b0bf4d LifetimeDependenceDiagnostics: calls with no deps are immortal
Fix lifetime diagnostics to consider an implicit initializer of a ~Escapable
type to be implicitly immortal. Required to handle Optional<~Escapable> stored
properties, such as:

struct Foo<Element: ~Escapable>: ~Escapable {
  var element: Element?

  @_lifetime(borrow c)
  init<C>(c: borrowing C) {
    // error: Lifetime-dependent variable 'self' escapes its scope
  }
}

The fix is simply to remove a temporary safeguard that I put in place to
compensate for our incomplete closure lifetimes. We now have the complete
representation of lifetimes on closures, so don't need the safeguard.

Representationally, a function that returns a ~Escapable value but has no
dependendencies is immortal. This was always the intended design, but the
temporary safeguard treated these cases as implicitly bound to some local scope.

Removing this safeguard has the effect of:

- Variable intialization is immortal (it cannot depend on anything by
  definition). The safety of the initializer is checked inside the implementation
  of those expressions rather than the caller.

- Empty ~Escapable types have an implicit immortal initializer (why not?)

- Calls to a function with @_unsafeNonescapableResult but no @_lifetime
  annotation produce an immortal value. This is reasonable, and we want to
  deprecate this attribute as soon as possible anyway. It is not for general use.

This is currently blocking usage of BorrowingSequence, such as a hypothetical BorrowingSequenceMapSequenceIterator.

Fixes rdar://176561897 ([nonescapable] initialization of Optional fields reports
a lifetime escape)
2026-05-08 16:47:56 -07:00
Andrew Trick 1ed083be0c LifetimeDependenceDiagnostics: add Builtin.makeBorrow support
Code like this currently looks like a lifetime escape:

  struct Ref<T: ~Copyable & ~Escapable>: ~Escapable {
    private let ref: Builtin.Borrow<T>

    @_lifetime(borrow target)
    init(_ target: borrowing T) {
      self.ref = Builtin.makeBorrow(target)
    }
  }

This is blocking the implementation of `Ref<~Escapable>`.

Fixes rdar://176564359 ([nonescapable] support Builtin.makeBorrow in
lifetime diagnostics)
2026-05-08 12:26:42 -07:00
Meghana Gupta ebd4d11225 Merge pull request #88847 from meg-gupta/fixeaborrow
Update SIL utilities for address results from borrow accessors
2026-05-07 20:57:06 -07:00
Daniil Kovalev a9a74aa8fe [AutoDiff] Find partial_apply of pullback w/o loop in closure spec pass (#88911)
Currently, AutoDiff Closure Specialization pass iterates over all VJP
instructions and checks each of them against a set of conditions which
`partial_apply` of pullback must satisfy.

This logic could be re-implemented w/o loop, checking conditions in
opposite direction, starting from `return` instruction and transitively
going to defining instructions of operands (`tuple` and `partial_apply`
for the desired pullback case).
2026-05-07 22:52:48 +00:00
Erik Eckstein ba0b04559e ComputeEscapeEffects: add a complexity limit for escape analysis of function arguments
Similar to what we do in AliasAnalysis

related to rdar://175999887
2026-05-07 09:52:14 +02:00
Erik Eckstein bdc1c4d34f AliasAnalysis: use a complexity limit in getApplyEffect
Like we do in other parts of AliasAnalysis which call into escape analysis.

Fixes a compile time problem.
rdar://175937160
2026-05-07 09:52:14 +02:00
Gábor Horváth cfeda37650 Merge pull request #88622 from Xazax-hun/tsan-effects-modeled
[SILOptimizer] Correctly compute the effects of TSan instrumentation
2026-05-06 12:20:31 +01:00