Commit Graph

403 Commits

Author SHA1 Message Date
Erik Eckstein
46035305aa Optimizer: improve simplification of alloc_stack
* Reimplement most of the logic in Swift as an Instruction simplification and remove the old code from SILCombine
* support more cases of existential archetype replacements:

For example:
```
  %0 = alloc_stack $any P
  %1 = init_existential_addr %0, $T
  use %1
```
is transformed to
```
  %0 = alloc_stack $T
  use %0
```

Also, if the alloc_stack is already an opened existential and the concrete type is known,
replace it as well:
```
  %0 = metatype $@thick T.Type
  %1 = init_existential_metatype %0, $@thick any P.Type
  %2 = open_existential_metatype %1 : $@thick any P.Type to $@thick (@opened("X", P) Self).Type
  ...
  %3 = alloc_stack $@opened("X", any P) Self
  use %3
```
is transformed to
```
  ...
  %3 = alloc_stack $T
  use %3
```
2025-03-07 15:59:34 +01:00
Erik Eckstein
5572c832e1 SILOptimizer: replace existential archetypes with concrete types in witness_method instructions 2025-03-07 15:59:34 +01:00
Erik Eckstein
71de3d90e0 Optimizer: replace existential archetypes with concrete types in apply instructions
If an apply uses an existential archetype (`@opened("...")`) and the concrete type is known, replace the existential archetype with the concrete type
  1. in the apply's substitution map
  2. in the arguments, e.g. by inserting address casts
For example:
```
  %5 = apply %1<@opend("...")>(%2) : <τ_0_0> (τ_0_0) -> ()
```
->
```
  %4 = unchecked_addr_cast %2 to $*ConcreteType
  %5 = apply %1<ConcreteType>(%4) : <τ_0_0> (τ_0_0) -> ()
```
2025-03-07 15:59:34 +01:00
Erik Eckstein
35097b5a71 Optimizer: simplify unconditional_checked_cast to existential metatypes.
Replace `unconditional_checked_cast` to an existential metatype with an `init_existential_metatype`, it the source is a conforming type.
Note that init_existential_metatype is better than unconditional_checked_cast because it does not need to do any runtime casting.
2025-03-07 15:59:33 +01:00
Erik Eckstein
df81283b97 SILCombine: make it possible to add a Swift simplification to an existing SILCombine visit function.
So far a `SILCombineSimplifiable` could only replace a SILCombine visit implementation.
With the `SWIFT_SILCOMBINE_PASS_WITH_LEGACY` (to be used in Passes.def) it's possible to keep an existing C++ implementation and on top of that add a Swift Simplification pass.
2025-03-07 15:59:33 +01:00
Erik Eckstein
de841fdcd5 Fix a comment about SILCombine "passes" in Passes.def 2025-03-07 15:59:33 +01:00
Meghana Gupta
3fe1029ef8 [NFC] Reorganize and rename ArrayBoundsCheckOpts.cpp 2025-02-28 09:50:58 -08:00
Erik Eckstein
5b93eb31bf Optimizer: remove the AllocVectorLowering pass
It's not needed anymore, because the "FixedArray" experimental feature is replaced by inline-arrays.
2025-02-12 10:51:14 +01:00
Erik Eckstein
0a011cddd8 Remove the old (and now obsolete) PredictableMemoryAccessOptimizations pass 2025-02-07 11:30:35 +01:00
Erik Eckstein
ce73deebc4 RedundantLoadElimination: add a "mandatory" redundant load elimination pass
And make `eliminateRedundantLoads` callable from other optimizations
2025-02-07 11:30:35 +01:00
Nate Chandler
1d22288f24 [NFC] SIL: Subpass runs can take values.
Allow continueWithNextSubpassRun to take a SILValue.
2025-01-16 08:18:29 -08:00
Erik Eckstein
9aff288be4 Optimizer: re-implement the pointer_to_address SILCombine peephole optimizations in swift
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.
2024-12-21 08:28:22 +01:00
Erik Eckstein
bf496aa4f6 Optimizer: add simplification for fix_lifetime
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
2024-12-13 12:06:20 +01:00
Erik Eckstein
3e35df0983 Simplification: run begin_borrow simplification in SILCombine 2024-12-11 12:32:34 +01:00
Erik Eckstein
6b38f2aab4 Optimizer: simplify load_borrow
* 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]`
2024-12-11 12:32:33 +01:00
eeckstein
81c65758e3 Merge pull request #78059 from eeckstein/destroy-hoisting
Optimizer: add a new destroy-hoisting optimization
2024-12-11 06:18:05 +01:00
Erik Eckstein
5be781a9a0 Optimizer: add a new destroy-hoisting optimization
It hoists `destroy_value` instructions  without shrinking an object's lifetime.
This is done if it can be proved that another copy of a value (either in an SSA value or in memory) keeps the referenced object(s) alive until the original position of the `destroy_value`.
```
  %1 = copy_value %0
  ...
  last_use_of %0
  // other instructions
  destroy_value %0       // %1 is still alive here
```
->
```
  %1 = copy_value %0
  ...
  last_use_of %0
  destroy_value %0
  // other instructions
```

The benefit of this optimization is that it can enable copy-propagation by moving destroys above deinit barries and access scopes.
2024-12-10 16:28:11 +01:00
Erik Eckstein
dd78dc722b Optimizer: add an optimization to remove copy_value of a borrowed value.
It removes a `copy_value` where the source is a guaranteed value, if possible:

```
  %1 = copy_value %0   // %0 = a guaranteed value
  // uses of %1
  destroy_value %1     // borrow scope of %0 is still valid here
```
->
```
  // uses of %0
```

This optimization is very similar to the LoadCopyToBorrow optimization.
Therefore I merged both optimizations into a single file and renamed it to "CopyToBorrowOptimization".
2024-12-09 20:01:07 +01:00
Erik Eckstein
63f6a2f30d Optimizer: remove the ArrayElementPropagation optimization
Propagating array element values is done by load-simplification and redundant-load-elimination.
So ArrayElementPropagation is not needed anymore.

ArrayElementPropagation also replaced `Array.append(contentsOf:)` with individual `Array.append` calls.
This optimization is removed, because the benefit is questionably, anyway.
In most cases it resulted in a code size increase.
2024-11-28 10:35:40 +01:00
Erik Eckstein
99ef6f727d Optimizer: replace unchecked_enum_data simplification in SILCombine with the corresponding instruction simplification from SwiftCompilerSources
The optimization in SILCombine had a bug (which is already fixed in the instruction simplification).
2024-11-14 09:18:29 +01:00
Michael Gottesman
32b4de60a9 Rename transfer -> send.
Accomplished using clangd's rename functionality.
2024-11-04 15:17:51 -08:00
Erik Eckstein
b8026d74e6 Revert "Revert "Optimizer: improve the load-copy-to-borrow optimization and implement it in swift""
This reverts commit 0666c446ec.
2024-10-22 08:40:18 +02:00
Erik Eckstein
0666c446ec Revert "Optimizer: improve the load-copy-to-borrow optimization and implement it in swift"
This reverts commit eed8645610.
2024-10-18 10:36:06 +02:00
Erik Eckstein
e0533e6125 SIL: add an API to replace all entries of a VTable
* add `ModulePassContext.replaceVTableEntries()`
* add `ModulePassContext.notifyFunctionTablesChanged()`
2024-10-14 14:43:11 +02:00
Erik Eckstein
eed8645610 Optimizer: improve the load-copy-to-borrow optimization and implement it in swift
The optimization replaces a `load [copy]` with a `load_borrow` if possible.

```
  %1 = load [copy] %0
  // no writes to %0
  destroy_value %1
```
->
```
  %1 = load_borrow %0
  // no writes to %0
  end_borrow %1
```

The new implementation uses alias-analysis (instead of a simple def-use walk), which is much more powerful.

rdar://115315849
2024-10-11 09:41:37 +02:00
Erik Eckstein
c97502374b Optimizer: add constant folding of classify_bridge_object
Constant fold `classify_bridge_object` to `(false, false)` if the operand is known to be a swift class.
2024-10-08 16:24:46 +02:00
Michael Gottesman
f985b0ee03 [thunk-lowering] Add a pass that performs lowering of ThunkInsts.
Right now it just handles the "identity" case so we can validate the
functionality.
2024-10-02 14:15:49 -07:00
Erik Eckstein
7ffd270008 embedded: move the VTableSpecializer pass into MandatoryPerformanceOptimizations
MandatoryPerformanceOptimizations already did most of the vtable specialization work.
So it makes sense to remove the VTableSpecializerPass completely and do everything in MandatoryPerformanceOptimizations.
2024-09-25 19:32:14 +02:00
Alejandro Alonso
b35ac50d3c Optimize TypeValueInst in Swift 2024-09-04 15:13:48 -07:00
Ryan Mansfield
908d97dde5 SIL: Fix cl::desc typos. [NFC] 2024-08-29 16:26:56 -04:00
Erik Eckstein
f9b524b1cb AliasAnalysis: a complete overhaul of alias- and memory-behavior analysis
The main changes are:

*) Rewrite everything in swift. So far, parts of memory-behavior analysis were already implemented in swift. Now everything is done in swift and lives in `AliasAnalysis.swift`. This is a big code simplification.

*) Support many more instructions in the memory-behavior analysis - especially OSSA instructions, like `begin_borrow`, `end_borrow`, `store_borrow`, `load_borrow`. The computation of end_borrow effects is now much more precise. Also, partial_apply is now handled more precisely.

*) Simplify and reduce type-based alias analysis (TBAA). The complexity of the old TBAA comes from old days where the language and SIL didn't have strict aliasing and exclusivity rules (e.g. for inout arguments). Now TBAA is only needed for code using unsafe pointers. The new TBAA handles this - and not more. Note that TBAA for classes is already done in `AccessBase.isDistinct`.

*) Handle aliasing in `begin_access [modify]` scopes. We already supported truly immutable scopes like `begin_access [read]` or `ref_element_addr [immutable]`. For `begin_access [modify]` we know that there are no other reads or writes to the access-address within the scope.

*) Don't cache memory-behavior results. It turned out that the hit-miss rate was pretty bad (~ 1:7). The overhead of the cache lookup took as long as recomputing the memory behavior.
2024-07-29 17:33:46 +02:00
Ben Barham
d72f5b12c4 Update StringRef::equals references to operator==
`equals` has been deprecated upstream, use `operator==` instead.
2024-06-27 19:14:06 -07:00
Kshitij
74166a4ab6 [Autodiff] Moves bridging code accesses in closure-spec opt behind APIs
Addresses some other surfacial feedback as well.
2024-05-13 15:37:30 -07:00
Kshitij
ab751d57ab [Autodiff] Adds logic to generate specialized functions in the closure-spec pass 2024-05-13 11:16:42 -07:00
Kshitij
fd609846ae Makes the swift-based closure-spec pass an experimental frontend feature 2024-05-02 09:14:05 -07:00
Kshitij
c8375c06ae [Autodiff] Adds part of the closure-specialization optimization pass
Changes in this CR add part of the, Swift based, Autodiff specific
closure specialization optimization pass. The pass does not modify any
code nor does it even exist in any of the optimization pipelines. The
rationale for pushing this partially complete optimization pass upstream
is to keep up with the breaking changes in the underlying Swift based
compiler infrastructure.
2024-05-02 09:14:05 -07:00
Michael Gottesman
c4f7076baf [region-isolation] When RegionIsolation is enabled, delay the preconcurrency import not used diagnostic to the SIL pipeline.
The reason why I am doing this is that I am going to be adding support for
preconcurrency imports to TransferNonSendable. That implies that we can have
preconcurrency import suppression in the SIL pipeline and thus that emitting the
diagnostic in Sema is too early.

To do this, I introduced a new module pass called
DiagnoseUnnecessaryPreconcurrencyImports that runs after the SILFunction pass
TransferNonSendable. The reason why I use a module pass is to ensure that
TransferNonSendable has run on all functions before we attempt to emit these
diagnostics. Then in that pass, we iterate over all of the modules functions and
construct a uniqued array of SourceFiles for these functions. Then we iterate
over the uniqued SourceFiles and use the already constructed Sema machinery to
emit the diagnostic using the source files.

rdar://126928265
2024-04-23 12:42:43 -05:00
Erik Eckstein
e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
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.
2024-04-10 13:38:10 +02:00
Artem Chikin
69fdc1356c Revert "Revert "Add mandatory SIL pass implementing '@_alwaysEmitConformanceMetadata' protocol attribute"" 2024-04-03 09:29:51 -07:00
Erik Eckstein
367dc1a299 SwiftCompilerSources: add OperandSet and OperandWorklist
Implemented by bridging the C++ OperandSet, similar to BasicBlockSet and NodeSet
2024-03-21 15:52:39 +01:00
Erik Eckstein
7afa419dd4 SIL: improve inline bitfields in SILNode, SILBasicBlock and Operand
* Let the customBits and lastInitializedBitfieldID share a single uint64_t. This increases the number of available bits in SILNode and Operand from 8 to 20. Also, it simplifies the Operand class because no PointerIntPairs are used anymore to store the operand pointer fields.
* Instead make the "deleted" flag a separate bool field in SILNode (instead of encoding it with the sign of lastInitializedBitfieldID). Another simplification
* Enable important invariant checks also in release builds by using `require` instead of `assert`. Not catching such errors in release builds would be a disaster.
* Let the Swift optimization passes use all the available bits and not only a fixed amount of 8 (SILNode) and 16 (SILBasicBlock).
2024-03-21 15:52:39 +01:00
Meghana Gupta
dacf5b47e3 Add an option -sil-break-before-pass-count to break before running a pass when in the debugger
We often look at the SIL output of -sil-print-function and may want to debug a specific pass
after looking at the output.

-sil-break-before-pass-count=<pass_number> will allow to automatically break in the debugger
after <pass_count> of passes are run.

Example:
From -sil-print-function dump:
"SIL function after  #6680, stage MidLevel,Function, pass 38: RedundantLoadElimination"

-Xllvm -sil-break-before-pass-count=6680 will break before running this pass in the debugger
2024-03-12 15:16:01 -07:00
Andrew Trick
a451af14c9 Increase BlockCapacity from 8 to 16 for intrusive BasicBlockSet.
InstructionRange uses 3 sets. Some algorithms need two active ranges at the top-level. Additionally, utilities often have few levels of nesting that each require a block set.
2024-03-05 17:08:13 -08:00
Michael Gottesman
3236bc26fa [region-isolation] Refactor out the stubify dead function if no longer used functionality from move only checker into its own pass and put it before region based isolation.
I am doing this since region based isolation hit the same issue that the move
checker did. So it makes sense to refactor the functionality into its own pass
and move it into a helper pass that runs before both.

It is very conservative and only stubifies functions that the specialization
passes explicitly mark as this being ok to be done to.
2024-03-01 13:11:07 -08:00
Michael Gottesman
11f0ff6e32 [sil] Ensure that all SILValues have a parent function by making it so that SILUndef is uniqued at the function instead of module level.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.

rdar://123484595
2024-02-27 13:14:47 -08:00
Meghana Gupta
7508a90af0 Enable destructure_struct/destructure_tuple simplifications in silcombine 2024-02-26 10:58:08 -08:00
Erik Eckstein
71fcae7fe8 SwiftCompilerSources: add the ability to implement SIL verification in swift 2024-02-22 07:12:10 +01:00
Nate Chandler
5a6873b98f [SILOptimizer] Remove DestroyHoisting pass.
It's no longer used.
2024-02-19 11:41:38 -08:00
Meghana Gupta
75bd5b08dd Add LifetimeDependenceScopeFixup pass 2024-02-13 16:52:01 -08:00
Andrew Trick
8c092911ef Add the LifetimeDependenceInsertion pass.
Insert mark_dependence [nonescaping] markers at every lifetime
introducer that produces a lifetime-dependent value.
2024-02-12 09:57:14 -08:00