Commit Graph

8083 Commits

Author SHA1 Message Date
Andrew Trick
16699e8110 Merge pull request #87015 from atrick/fix-ossa-rauw
Another fix for the OSSA RAUW utility for unowned phis
2026-02-06 14:13:26 -08:00
Meghana Gupta
617deca5ea Merge pull request #87011 from meg-gupta/oslogopt
Fix OSLogOptimization for complete lifetimes in SIL
2026-02-06 09:12:58 -08:00
Aidan Hall
e98a7a6bf8 Merge pull request #86842 from aidan-hall/just-func-type-lifetimes-try-print
LifetimeDependence: Support function types
2026-02-06 10:09:25 +00:00
Meghana Gupta
280057b8d8 Fix OSLogOptimization for complete lifetimes in SIL 2026-02-05 17:01:40 -08:00
Andrew Trick
2120c0502a Another fix for the OSSA RAUW utility for unowned phis
Fixes rdar://169556118 (Assertion: (succ->getSinglePredecessorBlock() == predBB)
function visitInsertionPoints at ValueLifetime.cpp:37.)
2026-02-05 15:01:11 -08:00
Aidan Hall
6aa55785f0 LifetimeDependence: Tests for function type attribute
Includes:
- rdar://166912068 test case
- Nested type SIL tests
- rdar://160894371 test
- Many more
2026-02-05 14:50:44 +00:00
eeckstein
dcad02e22b Merge pull request #86979 from eeckstein/di-closures
DefiniteInitialization: handle inout-self uses when analyzing closures
2026-02-05 07:27:04 +01:00
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
eeckstein
fd78c993c6 Merge pull request #86975 from eeckstein/fix-deinit-devirtualization
DeinitDevirtualizer: don't devirtualize `destroy_value [dead_end]`
2026-02-05 07:26:30 +01:00
Erik Eckstein
259f5403b8 DefiniteInitialization: handle inout-self uses when analyzing closures
Fixes a false "used before being initialized" error when using self-mutating functions inside conditional operators (`&&`, `||`) in initializers.
This is a follow-up on https://github.com/swiftlang/swift/pull/35276.

rdar://168784050
2026-02-04 15:04:37 +01:00
Meghana Gupta
c47610bf3b Merge pull request #86947 from meg-gupta/bailoutforeachloopunroll
Bailout of ForEachLoopUnroll pass when sources of element stores cannot be extended
2026-02-04 02:59:05 -08: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
Meghana Gupta
fbaa30b426 Bailout of ForEachLoopUnroll pass when sources of element stores cannot be extended 2026-02-02 16:13:10 -08: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
Adrian Prantl
8b7d18ae00 Merge pull request #86902 from adrian-prantl/168622625
[TempRValueElimination] Make AllocStackInst.hasUses analysis global
2026-02-01 18:55:34 -08:00
Adrian Prantl
d7ca6483a0 [TempRValueElimination] Make AllocStackInst.hasUses analysis global
Wihtout this change an alloc_stack instruction that is defined in a different
basic block than its use could result in instructions that are not dominated by
its operands. In an asserts build this is caught by the SIL verifier, but in a
non-asserts build it can crash the compiler.

Thanks to Erik Eckstein for the actual implementation of the fix!

rdar://168622625
2026-01-30 14:01:19 -08: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
Meghana Gupta
d1df7aa236 Diagnose trivial-type borrow accessor results using the same rules as non-trivial types 2026-01-29 15:45:06 -08:00
Meghana Gupta
16a2d7e18d Merge pull request #86812 from meg-gupta/fixsimplifycfg
Fix SimplifyCFG::simplifyTryApplyBlock for owned arguments in ossa
2026-01-29 00:16:30 -08:00
eeckstein
ad787dc6d4 Merge pull request #86840 from eeckstein/deinit-opts
Optimizer: fix two problems related to value-type deinits
2026-01-29 07:33:36 +01:00
Meghana Gupta
1144aa33d4 Fix SimplifyCFG::simplifyTryApplyBlock for owned arguments in ossa 2026-01-28 19:21:18 -08: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
Erik Eckstein
144b4b910d SROA: don't try to destructure a non-copyable type with a deinit
This check was only done for the top-level alloc_stack, but not for any nested types.

rdar://169022052
2026-01-28 13:10:30 +01:00
Alejandro Alonso
a4fdb7d9ec Simplify the identity for dereference borrows 2026-01-27 11:04:25 -08:00
Alejandro Alonso
9f95dc7695 Simplify init_borrow_addr when the borrow type is statically known
make sure we register as well as add test
2026-01-27 11:03:53 -08:00
Meghana Gupta
a2a2374410 Merge pull request #86744 from meg-gupta/dcefix
Remove unnecessary code from DeadCodeElimination
2026-01-26 06:42:52 -08:00
Andrew Trick
eb012174e8 Merge pull request #86767 from atrick/fix-ossa-rauw
Fix the OSSA RAUW utility for unowned phis
2026-01-24 09:24:03 -08:00
elsa
5e9f215f31 Merge pull request #86010 from elsakeirouz/rework-for-each-desugar
Rework ForEachStmt Desugaring
2026-01-24 13:55:51 +00:00
eeckstein
4ae970e634 Merge pull request #86741 from eeckstein/argument-effects
SIL: assume a read-effect for unused indirect arguments
2026-01-24 07:56:21 +01:00
Andrew Trick
96bc9aa90c Fix the OSSA RAUW utility for unowned phis
The OwnershipRAUW utility is called by CSE, SILCombine, etc. whenever OSSA
values are substituted or combined. It handles ownership corner cases by
creating new copies. Destroys need to be insert for those new copies after all
original uses. It is impossible to do that when phis are involved. The utility
already checks for phis involving owned or guaranteed values, but unowned phis
were not anticipated.

Fixes rdar://168620481 swift-frontend crash: While running pass
SILFunctionTransform "GenericSpecializer"
2026-01-23 21:56:30 -08:00
eeckstein
19b52bd3b7 Merge pull request #86748 from eeckstein/check_incremental
check_incremental: better diagnostics for non-determinism checks
2026-01-24 03:30:48 +01:00
Meghana Gupta
bfdfe8f948 Remove DCE support for end_lifetime 2026-01-23 14:04:12 -08:00
Erik Eckstein
58c46dc025 PassManager: add an option -sil-print-pass-md5 to print MD5 hashes of SIL after each pass
With this option an MD5 hash of the SIL is printed after each function or module pass - if the pass has changed the SIL.
This is useful for finding non-determinisms in the optimizer.
2026-01-23 19:20:20 +01:00
Elsa Keirouz
d54a572f7f [Sema] desugar ForEachStmt at AST level 2026-01-23 15:17:29 +00:00
Erik Eckstein
535a58e3fb SIL: assume a read-effect for unused indirect arguments
Even if an indirect argument is unused, pretend that the function reads from it.
If the unused argument is passed to another generic function and that function is specialized,
the argument may be re-abstracted and the specializer inserts a load from the indirect argument.
Therefore we must be prepared that unused indirect argument might get loaded from at some time.

Fixes a compiler crash
rdar://168623362
2026-01-23 15:58:23 +01:00
Erik Eckstein
172bf39901 Optimizer: let OSSA canonicalization always respect deinit barriers
When computing the region to search for deinit barriers, include _all_ destroys of a canonical liverange - including destroys of all copies.
Before this fix, only destroys of the original def were considered which resulted in moving destroys across deinit barriers.

Fixes a miscompile
rdar://168337959
2026-01-23 10:08:41 +01:00
Erik Eckstein
051a4f86cf Optimizer: remove the "eliminateSimpleCopies" peephole optimization from instruction canonicalization
It does not respect deinit barriers when hoisting destroys.
This kind of optimization is done by CopyPropagation, anyway.
2026-01-23 08:50:52 +01:00
Erik Eckstein
27ab7f99c0 MandatoryInlining: fix handling of inlined lexical closures
If the result of the `partial_apply` is lexical we must make sure to make its captured arguments lexical.
Otherwise the argument lifetimes may be shortened after inlining because the (lexical) `partial_apply` is not there anymore to keep the arguments alive.

Fixes a mis-compile
rdar://168337959
2026-01-23 08:42:52 +01:00
eeckstein
ee398d1b18 Merge pull request #86644 from eeckstein/lifetime-completion
Optimizer: enable complete OSSA lifetimes throughout the pass pipeline
2026-01-23 06:14:10 +01:00
eeckstein
fa4339d077 Merge pull request #86708 from eeckstein/temp-rvalue-elimination
TempRValueElimination: fix a problem with `load`-`store` copy elimination
2026-01-23 06:12:39 +01:00
Erik Eckstein
7af1e1ffd1 TempRValueElimination: fix a problem with load-store copy elimination
If a value is "copied" to the stack location via a `load` and `store` instruction pair and the source location is written or de-allocated between both instructions,
the optimization generated wrong SIL.
The fix is to make sure that writes to the source locations are always checked between the `load` and `store`.

rdar://168595700
2026-01-22 18:03:02 +01:00
Erik Eckstein
8158b95a5a Remove the now unused -enable-ossa-complete-lifetimes and -disable-ossa-complete-lifetimes frontend options 2026-01-22 17:41:48 +01: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
16cb80b60d Optimizer: implement all of cond_fail simplification as instruction simplification
Inserts an unreachable after an unconditional fail:
```
  %0 = integer_literal 1
  cond_fail %0, "message"
  // following instructions
```
->
```
  %0 = integer_literal 1
  cond_fail %0, "message"
  unreachable
deadblock:
  // following instructions
```

Remove the old SILCombine implementation because it's not working well with OSSA lifetime completion.
This also required to move the `shouldRemoveCondFail` utility function from SILCombine to InstOptUtils.
2026-01-22 17:41:22 +01:00
Erik Eckstein
2860c2df77 Optimizer: add DominatorTree.getImmediateDominator and DominatorTree.getDominanceOrder 2026-01-22 17:41:22 +01:00
Erik Eckstein
1a4eb8ca7e MandatoryDestroyHoisting: correct handling of destroy_value [dead_end]
Make sure to create `destroy_value` with correct dead_end flags.
Especially, in a dead-end region where the original value's lifetime was ended with a `destroy_value [dead_end]`, the optimization must not re-create a destroy without the dead_end flag.

^ Conflicts:
^	test/SILOptimizer/mandatory-destroy-hoisting.sil
2026-01-22 17:41:21 +01:00
Erik Eckstein
e2ddbf79f0 SIL: fix the corner case of an empty BasicBlockRange
If no block was ever inserted in a BasicBlockRange, the "inclusive" range should be empty and not contain the "begin" block.
2026-01-22 17:41:21 +01:00
Erik Eckstein
4755aa828e DestroyHoisting: correct handling of destroy_value [dead_end]
Make sure to create `destroy_value` with correct dead_end flags.
Especially, in a dead-end region where the original value's lifetime was ended with a `destroy_value [dead_end]`, the optimization must not re-create a destroy without the dead_end flag.

^ Conflicts:
^	test/SILOptimizer/destroy-hoisting.sil
2026-01-22 17:41:21 +01:00