Commit Graph

522 Commits

Author SHA1 Message Date
eeckstein
2bf3979f95 Merge pull request #86974 from eeckstein/simplification-pass
Optimizer: don't remove unused `destructure_struct` of a non-copyable value
2026-02-05 07:26:49 +01:00
Erik Eckstein
9f0a9d77c0 DeinitDevirtualizer: don't devirtualize destroy_value [dead_end]
It doesn't make sense to de-virtualize `destroy_value [dead_end]` because such operations are no-ops anyway.
This is especially important for Embedded Swift, because introducing calls to generic deinit functions after the mandatory pipeline can result in IRGen crashes.

rdar://168171608
2026-02-04 09:10:24 +01:00
Erik Eckstein
7ea1756fa4 Optimizer: don't remove unused destructure_struct of a non-copyable value
Because `destructure_struct` acts as lifetime-ending use. Removing this instruction results in an ownership error.
This can happen if a non-copyable struct only has trivial fields.

Fixes a verifier crash
https://github.com/swiftlang/swift/issues/86901
rdar://169285436
2026-02-04 08:47:42 +01:00
Erik Eckstein
6dde4c942e MandatoryPerformanceOptimizations: force de-virtualizing value-type deinits
Do this even if the function then contains references to other functions with wrong linkage.
MandatoryPerformanceOptimization fixes the linkage afterwards.
This is similar to what we already do with de-virtualizing class and witness methods: https://github.com/swiftlang/swift/pull/76032

rdar://168171608
2026-02-02 19:36:48 +01:00
Erik Eckstein
5cd70731da LifetimeCompletion/DiagnoseUnreachable: fix a wrong "will never be executed" warning
Make sure that debug locations are correct so that instruction which are inserted by DI after a no-return call doesn't cause DiagnoseUnreachable to print a wrong warning.
Also, add `extend_lifetime` to the list of excluded instructions in DiagnoseUnreachable.
2026-01-30 11:52:49 +01:00
Erik Eckstein
bdf5a70258 DeinitDevirtualizer: don't create an invalid function_ref in a serialized function.
Serialized functions may not reference non-public functions.

Fixes a compiler crash
rdar://169022052
2026-01-28 13:10:30 +01:00
Joe Groff
9a417d4c28 Handle Borrow instructions in LifetimeCompletion 2026-01-23 10:03:23 -08:00
Joe Groff
5f49668577 Builtin.dereferenceBorrow should maintain the memory location of addressable values. 2026-01-23 08:02:09 -08:00
Joe Groff
b11e8c985a SIL: Handle dereference_borrow returns in SILGenCleanup.
Make sure an `end_borrow` is emitted on the `dereference_borrow` so that
SILGenCleanup recognizes this pattern and lowers it to a `return_borrow`
as it does for returned `load_borrow`s. Add support to the Swift implementation
of `BorrowingInstruction` for `DereferenceBorrow`.
2026-01-23 08:02:09 -08:00
Joe Groff
bc53d4ecb4 SIL: Handle Borrow instructions in more utility visitors. 2026-01-23 08:02:09 -08:00
Erik Eckstein
18063707b5 Optimizer: enable complete OSSA lifetimes throughout the pass pipeline
This new OSSA invariant simplifies many optimizations because they don't have to take care of the corner case of incomplete lifetimes in dead-end blocks.

The implementation basically consists of these changes:
* add the lifetime completion utility
* add a flag in SILFunction which tells optimization that they need to run the lifetime completion utility
* let all optimizations complete lifetimes if necessary
* enable the ownership verifier to check complete lifetimes
2026-01-22 17:41:48 +01:00
Erik Eckstein
0f0aa0c17b Optimizer: require that there are no unreachable blocks and infinite loops in OSSA
These two new invariants eliminate corner cases which caused bugs if optimization didn't handle them.
Also, it will significantly simplify lifetime completion.

The implementation basically consists of these changes:
* add a flag in SILFunction which tells optimization if they need to take care of infinite loops
* add a utility to break infinite loops
* let all optimizations remove unreachable blocks and break infinite loops if necessary
* add verification to check the new SIL invariants

The new `breakIfniniteLoops` utility breaks infinite loops in the control flow by inserting an "artificial" loop exit to a new dead-end block with an `unreachable`.
It inserts a `cond_br` with a `builtin "infinite_loop_true_condition"`:
```
bb0:
  br bb1
bb1:
  br bb1              // back-end branch
```
->
```
bb0:
  br bb1
bb1:
  %1 = builtin "infinite_loop_true_condition"() // always true, but the compiler doesn't know
  cond_br %1, bb2, bb3
bb2:                  // new back-end block
  br bb1
bb3:                  // new dead-end block
  unreachable
```
2026-01-22 17:41:23 +01:00
Erik Eckstein
2860c2df77 Optimizer: add DominatorTree.getImmediateDominator and DominatorTree.getDominanceOrder 2026-01-22 17:41:22 +01:00
Daniil Kovalev
1f77138afe [AutoDiff] Closure specialization: specialize branch tracing enums (#85757)
This patch contains part of the changes intended to resolve #68944.

1. Closure info gathering logic.
2. Branch tracing enum specialization logic.
3. Specialization of branch tracing enum basic block arguments in VJP.
4. Specialization of branch tracing enum payload basic block arguments
in pullback.

Note that mangling-related logic is implemented in C++ since at this
moment we have no Swift bridged for that.

Here is a simplified example of how branch tracing enum (BTE)
specialization looks like.

Before specialization:

```
enum $_AD__xxx {
  case bb0(((Float) -> Float))
}

func vjp(...) {
  // ...
  %foo      = function_ref $foo         : (Float, Float) -> Float
  %pa1      = partial_apply %foo(%arg1) : (Float) -> Float
  %payload1 = tuple (%pa1)              : ((Float) -> Float)
  %bte      = enum $_AD__xxx.bb0!enumelt, %payload1
  // ...
}

func pullback(%bte, ...) {
  // ...
  %payload2 = unchecked_enum_data %bte, $_AD__xxx.bb0!enumelt : ((Float) -> Float)
  %pa2      = tuple_extract %payload2, 0                      : (Float) -> Float
  %res      = apply %pa2(%arg2)                               : Float
  // ...
}
```

After specialization:

```
enum $_AD__xxx_spec_bb0_0 {
  case bb0(((Float)))
}

func vjp(...) {
  // ...
  %captured1 = tuple (%arg1)      : (Float)
  %payload1  = tuple (%captured1) : ((Float))
  %bte_spec  = enum $_AD__xxx_spec_bb0_0.bb0!enumelt, %payload1
  // ...
}

func pullback_spec(%bte_spec, ...) {
  // ...
  %payload2  = unchecked_enum_data %bte, $_AD__xxx_spec_bb0_0.bb0!enumelt : ((Float))
  %captured2 = tuple_extract %payload2, 0                                 : (Float)
  %arg1      = tuple_extract %captured2, 0                                : Float
  %foo       = function_ref $foo                                          : (Float, Float) -> Float
  %res       = apply %foo(%arg2, %arg1)                                   : Float
  // ...
}
```
2025-12-21 00:33:50 +00:00
Meghana Gupta
5c4ce2f942 Merge pull request #86023 from meg-gupta/miscborrowfixes
Minor fixes to borrow accessors
2025-12-16 20:03:19 -08:00
Meghana Gupta
0c5fe56b7f Bailout on address apply result while computng argument escaping effects 2025-12-15 13:02:13 -08:00
Erik Eckstein
d8a85693c8 Optimizer: convert the FunctionUsesDumper pass to a test 2025-12-15 10:01:41 +01:00
Erik Eckstein
6ef1064a92 Optimizer: add ModuleTest 2025-12-15 10:01:41 +01:00
Erik Eckstein
751e52cdc3 Optimizer: convert the DeadEndBlockDumper pass to a test 2025-12-15 10:01:40 +01:00
Erik Eckstein
dc38a2226e Optimizer: convert the AliasInfoDumper and MemBehaviorDumper passes to tests 2025-12-15 09:09:41 +01:00
Erik Eckstein
abc40b3b55 Optimizer: convert the EscapeInfoDumper from a pass to a test 2025-12-15 09:09:40 +01:00
Andrew Trick
d609889e87 Merge pull request #85934 from atrick/fix-closure-liveness
Fix InteriorUseWalker: consider partial_apply [on_stack] an escape
2025-12-11 15:05:21 -08:00
Joe Groff
4479b49fd8 SIL: Handle address ReturnInsts from borrow accessors as yielding uses.
This avoids a spurious lifetime error when an address-only borrow accessor returns a
non-`Escapable` value from a non-`Escapable` aggregate.
2025-12-10 11:44:41 -08:00
Andrew Trick
f7c3c6f437 Fix InteriorUseWalker: consider partial_apply [on_stack] an escape
Fixes a bug in MandatoryDestroyHoisting where a captured value is destroyed
before a copy of the closure.

On-stack closures can be copied, and all copied uses must be within the borrow
scope of the captured operand. This is just like any other non-Escapable value,
so treat it as such by checking `Value.mayEscape` rather than `Type.Escapable`.

Originally, I wanted to make it illegal to copy of partial_apply [on_stack], but
it looks like we still allow it.

I would rather not complicate any logic yet with special handling for this
case. To fix any performance concerns, we might be able to simplify the
representation instead by banning copy_value on on-stack closures.

Fixes rdar://165850554 swift-frontend crash: While running "CopyPropagation" -
Invalid SIL provided to OSSACompleteLifetime?!)
2025-12-09 14:38:04 -08:00
eeckstein
d0f8ccef28 Merge pull request #85857 from eeckstein/fix-vtable-specialization
Embedded: allow generic class constructors
2025-12-05 20:17:52 +01:00
Erik Eckstein
8b496f668f Embedded: allow generic class constructors
For example:

```
  public class C: MyClass {
    public init(p: some P) {
      // ...
    }
  }
```

Constructors are not called via the vtable (except "required" constructors).
Therefore we can allow generic constructors.

https://github.com/swiftlang/swift/issues/78150
rdar://138576752
2025-12-05 11:35:00 +01:00
Aidan Hall
b1eb70bf45 Revert "[DebugInfo] Salvage more in -O builds"
This reverts commit a95d2979f9.

rdar://165667449
2025-12-04 15:39:39 +00:00
Arnold Schwaighofer
36a3c6e611 Merge pull request #85644 from aschwaighofer/wip_embedded_exits_with_eriks_changes_v1
[embedded] Fix associated type conformances for specialized witness tables
2025-12-01 16:40:31 -08:00
Aidan Hall
96dca43eb9 Merge pull request #85244 from aidan-hall/fixing-debug-info-rebase
Retain more debug info in optimized builds
2025-12-01 20:49:40 +00:00
Arnold Schwaighofer
0c882d42ce Merge pull request #85625 from aschwaighofer/wip_embedded_cast_tuples
[embedded] Allow casting to tuples and tighten the check which existentials we support in embedded with existentials
2025-12-01 08:27:43 -08:00
eeckstein
9304ce951c Merge pull request #85707 from eeckstein/embedded-witness-method-specialization
embedded: change the function representation of directly called witness methods
2025-12-01 09:36:45 +01:00
Aidan Hall
a95d2979f9 [DebugInfo] Salvage more in -O builds
Specifically, improved debug info retention in:
* tryReplaceRedundantInstructionPair,
* splitAggregateLoad,
* TempLValueElimination,
* Mem2Reg,
* ConstantFolding.

The changes to Mem2Reg allow debug info to be retained in the case tested by
self-nostorage.swift in -O builds, so we have just enabled -O in that file
instead of writing a new test for it.

We attempted to add a case to salvageDebugInfo for unchecked_enum_data, but it
caused crashes in Linux CI that we were not able to reproduce.
2025-11-28 17:42:18 +00:00
Erik Eckstein
78cb4ca197 Optimizer: extract replacing an apply into a utility function ApplySite.replace(withCallTo:) 2025-11-26 16:23:47 +01:00
Arnold Schwaighofer
b9f6454386 [embedded] Add support for storing/casting function types 2025-11-21 14:55:32 -08:00
Erik Eckstein
fa3bfa3b10 embedded: don't try to specialize vtables of C++ imported reference-counted classes
Fixes a false compiler error

rdar://165209061
2025-11-21 16:33:49 +01:00
Erik Eckstein
60a28cd570 embedded: don't re-abstract witness method calls for existentials
Don't convert indirect to direct arguments. This is needed to support general existentials in embedded swift.
2025-11-20 10:54:37 -08:00
Arnold Schwaighofer
8beaad60bd [embedded] Allow casting to tuples 2025-11-20 10:03:39 -08:00
Arnold Schwaighofer
3cff05d540 [embedded] Implement swift_dynamicCast suport for casts from existential to concrete type 2025-11-19 14:41:37 -08:00
Yuta Saito
8748213d52 Merge pull request #85524 from kateinoigakukun/yt/fix-non-reg2mem-rle-crash 2025-11-16 23:10:20 +09:00
Yuta Saito
e259a257e6 RedundantLoadElim: Fix invalid destructure_struct emission without aggressive reg2mem
The `shouldExpand` in `OptUtils.swift` was incorrectly returning `true`
unconditionally when `useAggressiveReg2MemForCodeSize` was disabled. The
expansion might be invalid for types with addr-only types and structs
with deinit, but we didn't check them before. This could lead to invalid
`destructure_struct` instructions without `drop_deinit` being emitted.
2025-11-15 19:22:33 +00:00
Meghana Gupta
e2123e1b3b Merge pull request #85362 from meg-gupta/moreborrow
Add SIL verification for borrow and mutate accessors and some other minor fixes
2025-11-10 09:04:28 -08:00
Erik Eckstein
eef769c83a Optimizer: when checking for lexical lifetimes look through all ownership-transitioning instructions
except `copy_value`
2025-11-06 20:26:20 +01:00
Meghana Gupta
a0eb58fa07 Handle return_borrow in a few more places in SwiftCompilerSources 2025-11-06 10:55:31 -08:00
Andrew Trick
5943d40edf LifetimeDependenceDiagnostics: handle dynamic casting of Span<T>
Add a special case for checked_cast_addr_br instruction. If it conformed to
SourceDestAddrInstruction, then the diagnostics would already have handled it
naturally, but the instruction's conditional semantics are strange enough that
such a conformance might confuse other passes.

rdar://159793739 (Using `as?` with non-escapable types emits faulty lifetime
diagnostics)
2025-10-30 23:28:25 -07:00
Andrew Trick
e11f7f1f11 LifetimeDependenceDiagnostics: diagnostic error on unknown uses
The common def-use walkers should not return .abortWalk without making a
diagnostic callback.
2025-10-30 23:28:25 -07:00
Andrew Trick
305d75187a LocalVariableUtils: precisely handle function live-out
Only record an outgoingArgument access when the current allocation is an
outgoing argument and the function exiting instruction is ReturnInst.

This avoids invalid SIL where we attempt to extend end_access up to an `unwind` but
fail to actually materialize that end_access.
2025-10-23 23:34:26 -07:00
Andrew Trick
62b04caaa7 LocalVariableUtils add non-escaping closure capture support
Don't always consider an inout_aliasable argument to have
escaped. AccessEnforcementSelection has already done that analysis and left
begin_access [dynamic] artifacts if the argument has escaped in any meaningful
way. Use that information to

Essential for supporting autoclosures that call mutating methods on span-like
things. Such as UTF8Span.UnicodeScalarIterator.skipForward():

e.g. while numSkipped < n && skipForward() != 0 { ... }
2025-10-23 23:34:25 -07:00
Andrew Trick
8200a871c9 Fix LifetimeDependenceDefUseWalker to follow inout dependence
Fixes rdar://157796728 ([nonescapable] [miscompile] No diagnostic error when an
inout MutableSpan is reassigned to a different lifetime source)
2025-10-23 23:34:25 -07:00
Andrew Trick
77ee27a0e7 [NFC] LocalVariableAccessInfo.description 2025-10-23 23:34:25 -07:00
Andrew Trick
de34abe3e5 Fix LocalVariableReachableAccess to handle potential reassignment.
Define LocalAccessInfo._isFullyAssigned to mean that the access does not read
the incoming value. Then treat any assignment that isn't full as a potential read.
2025-10-23 23:34:25 -07:00