Commit Graph

11369 Commits

Author SHA1 Message Date
Anton Korobeynikov
3011cc6077 Correctly handle multiple semantic results for autodiff subset
differential thunks.

Fixes https://github.com/swiftlang/swift/issues/84365
2025-09-17 15:46:33 -10:00
Anton Korobeynikov
7668666ad2 Support differentiation of wrapped value modify accessors (#78794)
Some fixes for coroutines with normal results and `partial_apply` of coroutines were required.

Fixes #55084
2025-09-10 02:30:26 -07:00
John McCall
64d020ec45 [NFC] Introduce a convenience specialization of CanTypeVisitor that
forwards the paired nominal type methods to common implementations.
2025-09-05 14:02:36 -04:00
Erik Eckstein
844217d58c Optimizer: replace explicit_copy_value and explicit_copy_addr with their non-explicit counterparts
The `explicit_copy_value` and `explicit_copy_addr` instructions are only used for non-copyable diagnostics in the mandatory pipeline.
After that we can replace them by their non-explicit counterparts so that optimizations (which only know of `copy_value` and `copy_addr`) can do their work.

rdar://159039552
2025-09-04 19:40:53 +02:00
Erik Eckstein
bb3b0b2859 Optimizer: remove the old CapturePropagation pass 2025-09-04 08:15:47 +02:00
Erik Eckstein
ddea9f6aa0 Optimizer: switch to the new ConstantCapturePropagation pass in the pass pipeline 2025-09-04 08:15:46 +02:00
Erik Eckstein
8e86b5ce3b Optimizer: add a preserveGenericSignature flag to FunctionPassContext.createSpecializedFunctionDeclaration 2025-09-04 08:15:46 +02:00
Erik Eckstein
45b1a21e74 Optimizer: make ModulePassContext.specialize() also available in FunctionPassContext and add two argument flags
add `convertIndirectToDirect` and `isMandatory`
2025-09-04 08:15:45 +02:00
Erik Eckstein
1a4bd76f95 Mangling: add specialization mangling for more complex constant propagated function arguments
So far, constant propagated arguments could only be builtin literals.
Now we support arbitrary structs (with constant arguments), e.g. `Int`.
This requires a small addition in the mangling scheme for function specializations.
Also, the de-mangling tree now looks a bit different to support a "tree" of structs and literals.
2025-09-04 08:15:44 +02:00
Erik Eckstein
bc244d1122 SIL: move the FunctionBuilderTy template argument from TypeSubstCloner to remapParentFunction 2025-09-04 08:15:44 +02:00
Janat Baig
f21eb5375e Merge branch 'main' into temp-branch 2025-09-02 20:23:25 -04:00
nate-chandler
b3af244c46 Merge pull request #84022 from nate-chandler/rdar158139991
[Mem2Reg] Add end_lifetime for more trivial case non-trivial enums.
2025-09-01 06:56:26 -07:00
Jakub Florek
eae7864370 Merge pull request #83988 from MAJKFL/new-sil-licm-pass-copy
New SIL LICM pass
2025-09-01 10:28:17 +01:00
Erik Eckstein
86076e2ada RawSILInstLowering: Don't insert an access scope for assign_or_init if there is already one.
This avoids inserting a dynamic access check when the parent is static (and therefore can be statically enforced).
2025-08-30 07:29:14 +02:00
Erik Eckstein
667de83339 Optimizer: move DiagnoseStaticExclusivity after MandatoryAllocBoxToStack
This is needed because MandatoryAllocBoxToStack can convert dynamic accesses to static accesses.
Also, it improves diagnostics for closure captures.
2025-08-30 07:28:33 +02:00
Nate Chandler
1c52364d28 [Mem2Reg] Complete single-block trivial enum cases
Add `end_lifetime` for values of non-trivial enum type which aren't
destroyed in non-dead-end blocks.
2025-08-29 15:47:10 -07:00
Nate Chandler
4b3588c9b9 [NFC] Mem2Reg: Delete this dead code.
Since the time that lifetimes in `alloc_stack [lexical]` began to be
represented after promotion by `move_value [lexical]`s, the
`endOwnedLexicalLifetimeBeforeInst` is just an assertion.  In the
future, lifetimes of values never destroyed that leak into dead end
blocks should be completed by OSSACompleteLifetime.  For now, just
delete this code.
2025-08-29 15:45:23 -07:00
Nate Chandler
69abf25f3a [NFC] Mem2Reg: Restructured conditional.
In preparation for adding other cases.  Also improved comments.
2025-08-29 15:45:19 -07:00
Nate Chandler
1f7432dedb [Mem2Reg] Don't skip write-only enum locations.
The lifetimes of the values stored into these locations may need to be
completed: if a trivial case of a non-trivial enum is written to the
location, its lifetime must be completed.

rdar://158139991
2025-08-29 15:45:14 -07:00
Nate Chandler
63a3c65147 [Mem2Reg] Fix isStorageValid.
In a few places, it wasn't getting set to false: `end_borrow`s of
`store_borrow`s and `load [take]`s.
2025-08-29 15:45:12 -07:00
Michael Gottesman
391ad21583 [rbi] Make all PartitionOpErrors noncopyable types.
I am going to be adding support to passes for emitting IsolationHistory behind a
flag. As part of this, we need to store the state of the partition that created
the error when the error is emitted. A partition stores heap memory so it makes
sense to make these types noncopyable types so we just move the heap memory
rather than copying it all over the place.
2025-08-29 15:18:55 -07:00
Michael Gottesman
6d20c74c3e Merge pull request #83903 from gottesmm/rdar152454571
[rbi] Teach RegionIsolation how to properly error when 'inout sending' params are returned.
2025-08-29 14:56:58 -07:00
eeckstein
05ddeae3c7 Merge pull request #83977 from eeckstein/fix-array-property-opt
Optimizer: fix an ownership violation when duplicating loops
2025-08-29 13:43:18 +02:00
Nate Chandler
09b1c3109d [NFC] Mem2Reg: Remove unused parameter. 2025-08-28 15:32:50 -07:00
Jakub Florek
85aeb41bd0 Remove old LICM pass. 2025-08-28 22:57:46 +01:00
nate-chandler
9fe43836f6 Merge pull request #83907 from nate-chandler/rdar158149082
[AllocBoxToStack] Don't destroy in dead-ends.
2025-08-28 13:36:28 -07:00
Jakub Florek
07ac8b3478 Add new loop invariant code motion. 2025-08-28 21:00:33 +01:00
Jakub Florek
e3140e0ae0 Add new generalized cloner. 2025-08-28 20:57:57 +01:00
Jakub Florek
bc86fe5a38 Hoist ArrayCallKind to a separate file 2025-08-28 20:50:33 +01:00
Erik Eckstein
87e7250750 Optimizer: fix an ownership violation when duplicating loops
If a guaranteed value is used in a dead-end exit block and the enclosing value is _not_ destroyed in this block, we end up missing the enclosing value as phi-argument after duplicating the loop.
TODO: once we have complete lifetimes we can remove this check again.

rdar://159125605
2025-08-28 18:40:54 +02:00
Anthony Latsis
f0bfdf63af Merge pull request #83945 from swiftlang/jepa-main2
SIL: Audit some `llvm::APInt` constructions to not hit an assertion with `implicitTrunc` set to false on rebranch
2025-08-28 12:35:25 +01:00
Nate Chandler
1eafced6a2 [AllocBoxToStack] Don't destroy in dead-ends.
It is valid to leak a value on paths into dead-end regions.
Specifically, it is valid to leak an `alloc_box`.  Thus, "final
releases" in dead-end regions may not destroy the box and consequently
may not release its contents.  Therefore it's invalid to lower such final
releases to `dealloc_stack`s, let alone `destroy_addr`s.  The in-general
invalidity of that transformation results in miscompiling whenever a box
is leaked and its projected address is used after such final releases.

Fix this by not treating final releases as boundary markers of the
`alloc_box` and not lowering them to `destroy_addr`s and
`dealloc_stack`s.

rdar://158149082
2025-08-27 17:03:48 -07:00
Arnold Schwaighofer
07248c70b8 Merge pull request #83904 from aschwaighofer/mark_dep_closure_inline_heuristic
ConstantTracker: Look through mark_dependence instructions
2025-08-27 14:50:28 -07:00
Anthony Latsis
2bfe2bd587 SIL: Treat -1 as signed when using it to construct an "all bits set" llvm::APInt
This should enable us to revert
73c70ee338.
2025-08-27 15:22:30 +01:00
Anthony Latsis
26540ca439 SIL: Do not use -1 to construct a 1-bit llvm::APInt
A -1 truncated to 1 bit is just 1, so stop overcomplicating things here.
2025-08-27 12:41:10 +01:00
JanBaig
be6e6e50a7 Use callback to avoid repeated allocation when collecting initialized properties 2025-08-26 14:37:57 -04:00
JanBaig
f4d9c7bb04 Add getDeclContextOrNull to AssignOrInitInst 2025-08-26 14:37:57 -04:00
JanBaig
66b38a63b7 Refactor lowerAssignOrInitInstruction 2025-08-26 14:37:57 -04:00
Erik Eckstein
87bf92494a SILCombine: fix convert_function -> apply peephole for generic function types
Currently we cannot deal with generic arguments/returns. Bail in this case.

Fixes a compiler crash
rdar://158809851
2025-08-26 10:16:49 +02:00
Meghana Gupta
745bef670f Merge pull request #83901 from meg-gupta/printsilmodule
Add options to print the SIL module after SILGen and SIL passes
2025-08-25 18:47:52 -07:00
Michael Gottesman
d22255e7bf Merge pull request #83855 from gottesmm/pr-723e8720ba1310d5199281d6ef14fd5ab808667c
[concurrency] NFC refactor out some code from LowerHopToActor before changing the pass.
2025-08-25 15:23:56 -07:00
Michael Gottesman
8745ab00de [rbi] Teach RegionIsolation how to properly error when 'inout sending' params are returned.
We want 'inout sending' parameters to have the semantics that not only are they
disconnected on return from the function but additionally they are guaranteed to
be in their own disconnected region on return. This implies that we must emit
errors when an 'inout sending' parameter or any element that is in the same
region as the current value within an 'inout sending' parameter is
returned. This commit contains a new diagnostic for RegionIsolation that adds
specific logic for detecting and emitting errors in these situations.

To implement this, we introduce 3 new diagnostics with each individual
diagnostic being slightly different to reflect the various ways that this error
can come up in source:

* Returning 'inout sending' directly:

```swift
func returnInOutSendingDirectly(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
  return x // expected-warning {{cannot return 'inout sending' parameter 'x' from global function 'returnInOutSendingDirectly'}}
  // expected-note @-1 {{returning 'x' risks concurrent access since caller assumes that 'x' and the result of global function 'returnInOutSendingDirectly' can be safely sent to different isolation domains}}
}
```

* Returning a value in the same region as an 'inout sending' parameter. E.x.:

```swift
func returnInOutSendingRegionVar(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
  var y = x
  y = x
  return y // expected-warning {{cannot return 'y' from global function 'returnInOutSendingRegionVar'}}
  // expected-note @-1 {{returning 'y' risks concurrent access to 'inout sending' parameter 'x' since the caller assumes that 'x' and the result of global function 'returnInOutSendingRegionVar' can be safely sent to different isolation domains}}
}
```

* Returning the result of a function or computed property that is in the same
region as the 'inout parameter'.

```swift
func returnInOutSendingViaHelper(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
  let y = x
  return useNonSendableKlassAndReturn(y) // expected-warning {{cannot return result of global function 'useNonSendableKlassAndReturn' from global function 'returnInOutSendingViaHelper'}}
  // expected-note @-1 {{returning result of global function 'useNonSendableKlassAndReturn' risks concurrent access to 'inout sending' parameter 'x' since the caller assumes that 'x' and the result of global function 'returnInOutSendingViaHelper' can be safely sent to different isolation domains}}
}
```

Additionally, I had to introduce a specific variant for each of these
diagnostics for cases where due to us being in a method, we are actually in our
caller causing the 'inout sending' parameter to be in the same region as an
actor isolated value:

* Returning 'inout sending' directly:

```swift
extension MyActor {
  func returnInOutSendingDirectly(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
    return x // expected-warning {{cannot return 'inout sending' parameter 'x' from instance method 'returnInOutSendingDirectly'}}
    // expected-note @-1 {{returning 'x' risks concurrent access since caller assumes that 'x' is not actor-isolated and the result of instance method 'returnInOutSendingDirectly' is 'self'-isolated}}
  }
}
```

* Returning a value in the same region as an 'inout sending' parameter. E.x.:

```swift
extension MyActor {
  func returnInOutSendingRegionLet(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
    let y = x
    return y // expected-warning {{cannot return 'y' from instance method 'returnInOutSendingRegionLet'}}
    // expected-note @-1 {{returning 'y' risks concurrent access to 'inout sending' parameter 'x' since the caller assumes that 'x' is not actor-isolated and the result of instance method 'returnInOutSendingRegionLet' is 'self'-isolated}}
  }
}
```

* Returning the result of a function or computed property that is in the same region as the 'inout parameter'.

```swift
extension MyActor {
  func returnInOutSendingViaHelper(_ x: inout sending NonSendableKlass) -> NonSendableKlass {
    let y = x
    return useNonSendableKlassAndReturn(y) // expected-warning {{cannot return result of global function 'useNonSendableKlassAndReturn' from instance method 'returnInOutSendingViaHelper'; this is an error in the Swift 6 language mode}}
    // expected-note @-1 {{returning result of global function 'useNonSendableKlassAndReturn' risks concurrent access to 'inout sending' parameter 'x' since the caller assumes that 'x' is not actor-isolated and the result of instance method 'returnInOutSendingViaHelper' is 'self'-isolated}}
  }
}
```

To implement this, I used two different approaches depending on whether or not
the returned value was generic or not.

* Concrete

In the case where we had a concrete value, I was able to in simple cases emit
diagnostics based off of the values returned by the return inst. In cases where
we phied together results due to multiple results in the same function, we
determine which of the incoming phied values caused the error by grabbing the
exit partition information of each of the incoming value predecessors and seeing
if an InOutSendingAtFunctionExit would emit an error.

* Generic

In the case of generic code, it is a little more interesting since the result is
a value stored in an our parameter instead of being a value directly returned by
a return inst. To work around this, I use PrunedLiveness to determine the last
values stored into the out parameter in the function to avoid having to do a
full dataflow. Then I take the exit blocks where we assign each of those values
and run the same check as we do in the direct phi case to emit the appropriate
error.

rdar://152454571
2025-08-25 14:57:44 -07:00
Arnold Schwaighofer
2fd904808c ConstantTracker: Look through mark_dependence instructions
An interposed mark_dependence should not block the heuristic that adds a
benefit when inlining a function that takes a closure argument.
2025-08-25 13:57:23 -07:00
Meghana Gupta
3ef10405f8 Add options to print the SIL module after SILGen and SIL passes 2025-08-25 13:05:41 -07:00
Erik Eckstein
bdea6063d7 Mem2Reg: Fix lifetime completion for enum case values.
Enum types may have incomplete lifetimes in address form for trivial case values. When promoted to value form, they will end up with incomplete ossa lifetimes.
Because we know that the incomplete enum values are trivial enum cases we complete their lifetimes with `end_lifetime` instead of `destroy_value`.
This is especially important for Embedded Swift where we are not allowed to insert destroys which were not there before.

Fixes a compiler crash in Embedded Swift caused by de-virtualizing such an inserted destroy and ending up with a non-specialized generic function.

rdar://158807801
2025-08-25 09:35:46 +02:00
Janat Baig
798c0f51a4 Merge branch 'main' into temp-branch 2025-08-23 11:11:04 -04:00
JanBaig
52895fefc3 [SIL] Remove AssignByWrapper references from SIL passes 2025-08-22 23:20:53 -04:00
JanBaig
6f1ee54885 [SIL] Remove AssignByWrapper suport from SIL parsing and serialization 2025-08-22 23:17:54 -04:00
JanBaig
4c61096be7 [SIL] Remove AssignByWrapper handling from analysis and utils 2025-08-22 23:15:16 -04:00
Michael Gottesman
21915ae428 [concurrency] NFC refactor out some code from LowerHopToActor before changing the pass.
Specifically, I am refactoring out the code that converts actor/Optional<any
Actor> to an executor in preparation for adding code to LowerHopToExecutor that
handles Builtin.ImplicitIsolationActor.

The only actual functional change is that I made getExecutorForOptionalActor
support being invoked when generating code (i.e. when its SILBuilder has an
insertion point at the end of the block). It previously assumed that it would
always have a real SILInstruction as an insertion point. The changes can be seen
in the places where we now check if the insertion point equals the end of a
block. Its very minor and due to conditional control flow doesn't have any
actual impact given the manner that the code today is generated. This came up in
a subsequent commit when I reuse this code to generate a helper function for
converting Builtin.ImplicitIsolationActor to Builtin.Executor.
2025-08-22 12:40:51 -07:00