Commit Graph

1779 Commits

Author SHA1 Message Date
Meghana Gupta
a0c939bd3b Use @inout result convention for mutate accessors 2025-10-20 09:05:32 -07:00
eeckstein
e74a7ecef9 Merge pull request #84979 from eeckstein/global-init-optimizations
Optimizer: some small (mandatory) optimization improvements for static initialization of globals
2025-10-20 07:32:03 +02:00
Michael Gottesman
a9d409d526 Merge pull request #83346 from gottesmm/pr-df6aafa41c61b9a9a6ee4965a1564ec2946a0dc9
[concurrency] Change #isolated to mask out the TBI bits of the witness pointer of the implicit isolated any Actor pointer so we can do optimizations on TBI supporting platforms in the future.
2025-10-17 17:02:43 -07:00
Erik Eckstein
62e2871b2f MandatoryPerformanceOptimizations: run DeadStoreElimination for global init functions.
Cleanup leftovers from simplification.
The InitializeStaticGlobals pass cannot deal with dead stores in global init functions.
2025-10-17 20:25:19 +02:00
Erik Eckstein
794964adba MandatoryRedundantLoadElimination: remove redundant loads from global variables
This is important in the initializer functions of globals. It can enabled static initialization of globals in more cases.
2025-10-17 20:25:19 +02:00
Erik Eckstein
110010856f AliasAnalysis: handle debug_step in computeMemoryEffect
The `debug_step` instruction does not have a memory effect on any specific address
2025-10-17 20:25:18 +02:00
Daniil Kovalev
75f80410e6 Run closure specialization only if ownership info is present in callee (#84956)
Calling `cloneRecursively` from `SpecializationInfo.cloneClosures`
requires the callee having ownership info. Otherwise, the cloner uses
`recordFoldedValue` instead of `recordClonedInstruction`, and
`postProcess` hook is not called, which leads to an assertion failure in
`BridgedClonerImpl::cloneInst`.
2025-10-17 10:51:57 -07:00
Michael Gottesman
fe9c21fd87 [sil] Add a new instruction cast_implicit_actor_to_optional_actor.
This instruction converts Builtin.ImplicitActor to Optional<any Actor>. In the
process of doing so, it masks out the bits we may have stolen from the witness
table pointer of Builtin.ImplicitActor. The bits that we mask out are the bottom
two bits of the top nibble of the TBI space on platforms that support TBI (that
is bit 60,61 on arm64). On platforms that do not support TBI, we just use the
bottom two tagged pointer bits (0,1).

By using an instruction, we avoid having to represent the bitmasking that we are
performing at the SIL level and can instead just make the emission of the
bitmasking an IRGen detail. It also allows us to move detection if we are
compiling for AArch64 to be an IRGen flag instead of a LangOpts flag.

The instruction is a guaranteed forwarding instruction since we want to treat
its result as a borrowed projection from the Builtin.ImplicitActor.
2025-10-16 10:52:04 -07:00
Erik Eckstein
610539a85f SIL: streamline Operand Sequence APIs
* remove `filterUsers(ofType:)`, because it's a duplication of `users(ofType:)`
* rename `filterUses(ofType:)` -> `filter(usersOfType:)`
* rename `ignoreUses(ofType:)` -> `ignore(usersOfType:)`
* rename `getSingleUser` -> `singleUser`
* implement `singleUse` with `Sequence.singleElement`
* implement `ignoreDebugUses` with `ignore(usersOfType:)`

This is a follow-up of eb1d5f484c.
2025-10-16 10:12:33 +02:00
Erik Eckstein
82bffd3b21 Simplification: fold tuple - copy_value - destructure_tuple sequences
We already do this for structs.
Also, refactor the simplification to share the logic between structs and tuples
2025-10-14 10:20:17 +02:00
Erik Eckstein
5104c317ca TempRValueElimination: fix a problem with non-copyable types
In case of a non-copyable type the final destroy (or take) of a stack location can be missing if the value has only trivial fields.
The optimization inserted a `destroy_addr` in this case although it wasn't there before.

Beside fixing this problem I also refactored the code a bit to make it more readable.
2025-10-10 21:37:27 +02:00
Andrew Trick
d653b0ccd0 Merge pull request #84739 from atrick/lifedep-unsafeaddress
LifetimeDependenceDefUseWalker: store to unsafeMutableAddress
2025-10-09 18:40:32 -07:00
Erik Eckstein
181b2f1f6d Optimizer: eliminate struct_extracts of an owned struct where the struct_extracts are inside a borrow scope
This is done by splitting the `begin_borrow` of the whole struct into individual borrows of the fields (for trivial fields no borrow is needed).
And then sinking the `struct` to it's consuming use(s).

```
  %3 = struct $S(%nonTrivialField, %trivialField)  // owned
  ...
  %4 = begin_borrow %3
  %5 = struct_extract %4, #S.nonTrivialField
  %6 = struct_extract %4, #S.trivialField
  use %5, %6
  end_borrow %4
  ...
  end_of_lifetime %3
```
->
```
  ...
  %5 = begin_borrow %nonTrivialField
  use %5, %trivialField
  end_borrow %5
  ...
  %3 = struct $S(%nonTrivialField, %trivialField)
  end_of_lifetime %3
```

This optimization is important for Array code where the Array buffer is constantly wrapped into structs and then extracted again to access the buffer.
2025-10-08 17:48:37 +02:00
Erik Eckstein
87a9d4ca2e Optimizer: notify that operand instructions of a deleted instruction have changed
This makes sure that instruction simplification doesn't terminate too early, missing some optimization opportunities.
2025-10-08 17:48:37 +02:00
Andrew Trick
4378995a78 LifetimeDependenceDefUseWalker: store to unsafeMutableAddress
Handle storing to a mutable property implemented as unsafeMutableAddress. In
SIL, the stored address comes from pointer_to_address. Recognize the addressor
pattern and handle the store as if it writes to a regular property of 'self'.

Required for UnsafePointer<~Escapable>.pointee.
2025-10-07 13:22:27 -07:00
Andrew Trick
4a7895e15b SwiftCompilerSources: bridge Function.isAddressor() 2025-10-07 10:44:42 -07:00
Andrew Trick
0d496b5404 SwiftCompilerSources: bridge Type.unsafePointerElementType 2025-10-07 10:44:42 -07:00
eeckstein
757de6e2a6 Merge pull request #84711 from eeckstein/fix-licm
LoopInvariantCodeMotion: fix check for hoisting `load_borrow` instructions
2025-10-07 11:40:29 +02:00
eeckstein
401a2ac2bc Merge pull request #84704 from eeckstein/closure-specialization
ClosureSpecialization: support for OSSA and a big overhaul
2025-10-07 06:59:08 +02:00
Andrew Trick
c2171ea9b0 Merge pull request #84703 from atrick/lifedep-diag-init
Lifetimes: add a diagnostic note for implicit accessors
2025-10-06 12:29:51 -07:00
Erik Eckstein
55cdc31936 LoopInvariantCodeMotion: a small refactoring
which is now possible as we removed the "fallthrough" from the previous case
2025-10-06 17:57:12 +02:00
Erik Eckstein
e88096e971 LoopInvariantCodeMotion: fix check for hoisting load_borrow instructions
We need to check aliasing for all kind of side-effect instructions, not just stores and destroys
2025-10-06 17:57:12 +02:00
Erik Eckstein
df20d36255 ClosureSpecialization: support for OSSA and a big overhaul
Beside supporting OSSA, this change significantly simplifies the pass.
The main change is that instead of starting at a closure (e.g. `partial_apply`) and finding all call sites, we now start at a call site and look for closures for all arguments. This makes a lot of things much simpler, e.g. not so many intermediate data structures are required to track all the states.

I needed to remove the 3 unit tests because the things those tests were testing are not there anymore. However, the pass is tested with a lot of sil tests (and I added quite a few), which should give good test coverage.

The old ClosureSpecializer pass is still kept in place, because at that point in the pipeline we don't have OSSA, yet. Once we have that, we can replace the old pass withe the new one.
However, the autodiff closure specializer already runs in the OSSA pipeline and there the new changes take effect.
2025-10-06 12:02:48 +02:00
Erik Eckstein
89bba668e2 Mangling: add a closure specialization mangling for arguments which specialize for the same closure as a previous argument
For example:
```
  %1 = partial_apply %closure
  apply %f(%1, %1)    // first argument: `.closure(%1)`
                      // second argument: `.previousArgumentIndex(0)`
```
2025-10-06 09:47:41 +02:00
Erik Eckstein
08696eeb92 Cloner: set the cloner's builder insertion point to the entry block when creating a new entry block in the cloned function
This allows clients to directly clone specific instructions into the new entry block
2025-10-06 09:47:40 +02:00
Erik Eckstein
898b8754bf SIL: add some Instruction/Builder APIs
* `var UncheckedValueCastInst.fromValue`
* `BeginApplyInst.isNonThrowing` and `BeginApplyInst.isNonAsync`
* `Builder.createUncheckedValueCast`
2025-10-06 09:47:40 +02:00
Erik Eckstein
2cd625a367 Optimizer: add the Builder.insertCleanupAtFunctionExits utility 2025-10-06 09:47:40 +02:00
Erik Eckstein
c3612bafb8 SIL: make var OperandArray.values available for all kind of operand sequences 2025-10-06 09:47:40 +02:00
Andrew Trick
771e9b522e Lifetimes: add a diagnostic note for implicit accessors
Lifetime diagnostics may report an error within an implicit initializer or
accessor. The source location is misleading in these cases and causes much
consternation.
2025-10-05 20:16:44 -07:00
Andrew Trick
bed80eed72 [NFC] LifetimeDependence computeAddressRange comments and test case 2025-10-03 20:48:07 -07:00
Andrew Trick
ac31a2f619 LifetimeDependenceDiagnostics: extend temp alloc to unreachable.
When a non-Escapable value depends on the address of a trivial value, we use a
special computeAddressableRange analysis to compute the trivial value's
scope. Extend that analysis to include unreachable paths.

Fixes this pattern:

    inlineStorage.span.withUnsafeBytes

where inlineStorage is a trivial type defined in the user module. This
does not reproduce directly with InlineArray, but it is a problem for
user modules that have their own trivial wrapper around an InlineArray.

Fixes rdar://161630684 (Incorrect diagnostic: lifetime-dependent value escapes its scope)
2025-10-03 20:47:59 -07:00
Andrew Trick
7197f63ce2 Comment LifetimeDependenceScopeFixup. Explain unreachable paths. 2025-10-03 20:44:17 -07:00
Erik Eckstein
171607afa7 DeadStoreElimination: fix a corner case of storing a trivial case of a non-trivial enum
Storing a trivial enum case in a non-trivial enum must be treated like a non-trivial init or assign, e.g.
```
  %1 = enum $Optional<String>, #Optional.none!enumelt
  store %1 to [trivial] %0  // <- cannot delete this store!
  store %2 to [assign] %0
```
2025-10-02 19:20:35 +02:00
nate-chandler
5945606067 Merge pull request #84577 from nate-chandler/rdar161433604
[Optimizer] Use valid inst range to broadcast inlining changes.
2025-10-01 14:08:52 -07:00
Arnold Schwaighofer
7853ba0a7f Merge pull request #84178 from aschwaighofer/inline_always
Add experimental feature `@inline(always)`
2025-10-01 07:23:24 -07:00
Arnold Schwaighofer
25a071efc8 Add experimental feature @inline(always)
The intent for `@inline(always)` is to act as an optimization control.
The user can rely on inlining to happen or the compiler will emit an error
message.

Because function values can be dynamic (closures, protocol/class lookup)
this guarantee can only be upheld for direct function references.

In cases where the optimizer can resolve dynamic function values the
attribute shall be respected.

rdar://148608854
2025-09-30 08:36:26 -07:00
Erik Eckstein
b527020364 LoopInvariantCodeMotion: bail on split load [take]
We currently don't support split `load [take]`, i.e. `load [take]` which does _not_ load all non-trivial fields of the initial value.
2025-09-30 10:39:51 +02:00
Erik Eckstein
fc6302e3e9 LoopInvariantCodeMotion: correctly handle load [copy]
When moving loads and stores out of a loop, a `load [copy]` must be replaced by a `copy_value`.
2025-09-30 10:39:51 +02:00
Erik Eckstein
a6fb1876ef LoopInvariantCodeMotion: correctly create projections for owned values
Owned structs and tuples must be projected by `destructure_struct` and `destructure_tuple`, respectively.

rdar://161467837
2025-09-30 10:39:51 +02:00
Erik Eckstein
7bbe5c6fe2 LoopInvariantCodeMotion: don't hoist loads and stores if the memory location is not initialized at loop exits.
If the memory is not initialized at all exits, it would be wrong to insert stores at exit blocks.
2025-09-30 10:39:51 +02:00
Nate Chandler
07d75186ba [Optimizer] Don't walk to deleted.
During inlining, some instructions in the caller may be deleted.  So
when publishing this best effort list of instructions which were
"changed" during inlining, don't start from a deleted instruction.
Instead just don't publish, as already happens in other cases.

Without actually addressing
```
// TODO: get a list of cloned instructions from the `inlineFunction`
```
this is somewhat better than checking for having reached the end of the
function during the walk because that will result in falsely
broadcasting that some unchanged instructions have changed whereas this
change only results in not broadcasting which is already being done in
some cases (e.g. when a `begin_apply` is immediately followed by an
`end_apply`).
2025-09-29 20:52:18 -07:00
Nate Chandler
b62798381e [Optimizer] Don't walk from deleted.
During inlining, the apply is deleted.  So when publishing this best
effort list of which instructions were "changed" during inlining, start
from the instruction before the deleted apply.
2025-09-29 20:52:18 -07:00
Nate Chandler
36205d90d2 [Gardening] Detypo'd "inlining". 2025-09-29 13:56:29 -07:00
Erik Eckstein
273874cd59 ConstantCapturePropagation: don't propagate keypaths with multiple uses in non-OSSA
We cannot do this because we don't know where to insert the compensating release after the propagated `partial_apply`.
A required `strong_retain` may have been moved over the `partial_apply`.
Then we would release the keypath too early.

Fixes a mis-compile
rdar://161321614
2025-09-29 18:42:39 +02:00
Erik Eckstein
12626475c3 ConstantCapturePropagation: refactor Value.isConstant 2025-09-29 18:42:39 +02:00
Erik Eckstein
e3055673f4 ConstantCapturePropagation: support sub-pass bisecting 2025-09-29 18:42:39 +02:00
Kavon Farvardin
d8e23cb2d4 Merge pull request #84523 from kavon/manual-ownership/usability-fixes-4
Usability improvements for ManualOwnership, part 4
2025-09-26 06:07:31 -07:00
Kavon Farvardin
32263bb9b8 ManualOwnership: add workaround for vars
For a proof-of-concept quality feature,
we can just skip the pass causing problems until
a proper solution is implemented.
2025-09-25 15:53:18 -07:00
Michael Gottesman
c1959f8cfd Merge pull request #84516 from gottesmm/pr-c70794ebe028f9c9476b9f9b19b1c5a74a4e2e61
[cmake] Make SwiftCompilerSources support debug info in RelWithDebInfoMode and use -Os instead of -O with MinSizeRel.
2025-09-25 13:58:47 -05:00
eeckstein
16ce6b85ea Merge pull request #84511 from eeckstein/fix-init-static-globals
InitializeStaticGlobals : reapply support of non-loadable enums with a fix
2025-09-25 18:46:16 +02:00