Commit Graph

11224 Commits

Author SHA1 Message Date
eeckstein
ea6ed2fdec Merge pull request #82537 from eeckstein/fix-closure-specializer
ClosureSpecializer: don't specialize captures of stack-allocated Objective-C blocks
2025-06-27 06:46:48 +02:00
Erik Eckstein
1a009f5b0d ClosureSpecializer: don't specialize captures of stack-allocated Objective-C blocks
Bail if the closure captures an ObjectiveC block which might _not_ be copied onto the heap, i.e optimized by SimplifyCopyBlock.
We can't do this because the optimization inserts retains+releases for captured arguments.
That's not possible for stack-allocated blocks.

Fixes a mis-compile
rdar://154241245
2025-06-26 19:17:37 +02:00
Erik Eckstein
45dc83bcd8 SemanticARCOpts: don't ignore dead-end blocks in the liverange analysis
This can result in wrong ARC optimizations in dead-end blocks.
Fixes a SIL verification error.

rdar://154356277
2025-06-26 16:06:32 +02:00
stzn
660263cf2c [region-isolation] Fix crash due to missing visitVectorBaseAddrInst case
Credit to https://github.com/stzn for initial work on the patch.

rdar://151401230
2025-06-23 11:11:59 -07:00
Andrew Trick
7a29d9d8b6 Fix MoveOnlyObjectCheckerPImpl::check() for mark_dependence.
Handle the presence of mark_dependence instructions after a begin_apply.

Fixes a compiler crash:
"copy of noncopyable typed value. This is a compiler bug. ..."
2025-06-22 17:39:13 -07:00
Andrew Trick
c41715ce8c Fix MoveOnlyObjectCheckerPImpl::check() changed flag
Extract the special pattern matching logic that is otherwise unrelated to the
check() function. This makes it obvious that the implementation was failing to
set the 'changed' flag whenever needed.
2025-06-22 16:38:06 -07:00
nate-chandler
17c1fbd5f4 Merge pull request #82313 from jamieQ/copy-prop-ossa-dead-ends-build-time-fix
[SILOptimizer]: slow OSSA lifetime canonicalization mitigation
2025-06-21 08:50:58 -07:00
Erik Eckstein
6714a72256 Optimizer: re-implement and improve the AllocBoxToStack pass
This pass replaces `alloc_box` with `alloc_stack` if the box is not escaping.
The original implementation had some limitations. It could not handle cases of local functions which are called multiple times or even recursively, e.g.

```
public func foo() -> Int {
  var i = 1

  func localFunction() { i += 1 }

  localFunction()
  localFunction()
  return i
}

```

The new implementation (done in Swift) fixes this problem with a new algorithm.
It's not only more powerful, but also simpler: the new pass has less than half lines of code than the old pass.

The pass is invoked in the mandatory pipeline and later in the optimizer pipeline.
The new implementation provides a module-pass for the mandatory pipeline (whereas the "regular" pass is a function pass).
This is required because the mandatory pass needs to remove originals of specialized closures, which cannot be done from a function-pass.
In the old implementation this was done with a hack by adding a semantic attribute and deleting the function later in the pipeline.

I still kept the sources of the old pass for being able to bootstrap the compiler without a host compiler.

rdar://142756547
2025-06-20 08:15:04 +02:00
Erik Eckstein
28dd6f7064 Optimizer: improve the SpecializationCloner
* add `cloneFunctionBody` without an `entryBlockArguments` argument
* remove the `swift::ClosureSpecializationCloner` from the bridging code and replace it with a more general `SpecializationCloner`
2025-06-20 08:15:02 +02:00
Erik Eckstein
d8e4e501f6 Optimizer: add some SIL modification APIs to Context
* `insertFunctionArgument`
* `BeginAccessInst.set(accessKind:)`
* `erase(function:)`
2025-06-20 08:15:01 +02:00
Erik Eckstein
de28cf04cc Optimizer: add Context. mangle(withBoxToStackPromotedArguments) 2025-06-20 08:15:01 +02:00
Erik Eckstein
bc7024edfe Optimizer: fix ModulePassContext.mangle(withDeadArguments:)
If mangled the wrong argument indices.
2025-06-20 08:15:00 +02:00
Erik Eckstein
4212c611e5 Optimizer: add Context.createSpecializedFunctionDeclaration
Originally this was a "private" utility for the ClosureSpecialization pass.
Now, make it a general utility which can be used for all kind of function specializations.
2025-06-20 08:15:00 +02:00
Jamie
1f3f830fc7 [SILOptimizer]: slow OSSA lifetime canonicalization mitigation
OSSA lifetime canonicalization can take a very long time in certain
cases in which there are large basic blocks. to mitigate this, add logic
to skip walking the liveness boundary for extending liveness to dead
ends when there aren't any dead ends in the function.

Updates `DeadEndBlocks` with a new `isEmpty` method and cache to
determine if there are any dead-end blocks in a given function.
2025-06-18 17:52:14 -05:00
Meghana Gupta
e42b564800 Merge pull request #82033 from meg-gupta/fixinlinercrash
Fix an inliner crash when inlining begin_apply with scoped lifetime dependence
2025-06-12 10:53:19 -07:00
Stephen Canon
9259c3eec4 Add new interleave and deinterleave builtins (#81689)
Ideally we'd be able to use the llvm interleave2 and deinterleave2
intrinsics instead of adding these, but deinterleave currently isn't
available from Swift, and even if you hack that in, the codegen from
LLVM is worse than what shufflevector produces for both x86 and arm. So
in the medium-term we'll use these builtins, and hope to remove them in
favor of [de]interleave2 at some future point.
2025-06-12 12:01:53 -04:00
Meghana Gupta
8396a6d8c0 Fix an inliner crash when inlining begin_apply with scoped lifetime dependence
LifetimeDependenceInsertion inserts mark_dependence on token result of a begin_apply
when it yields a lifetime dependent value. When such a begin_apply gets inlined,
the inliner can crash because of the remaining uses of the token result.

Fix this by inserting mark_dependence on parameter operands that are lifetime dependence sources
and deleting the mark_dependence on token results in the inliner.

Fixes rdar://151568816
2025-06-12 01:35:36 -07:00
eeckstein
116a453556 Merge pull request #82177 from eeckstein/fix-lha
LowerHopToActor: insert a borrow scope for an `Optional<Actor>.none` value
2025-06-12 06:16:45 +02:00
Michael Gottesman
e95b8570d6 Merge pull request #82149 from gottesmm/pr-4cb0aff1ceb16d75edcadd4de2ed612b97924226
Change send-never-sendable of isolated partial applies to use SIL level info instead of AST info.
2025-06-11 13:52:43 -07:00
Erik Eckstein
5489627310 LowerHopToActor: insert a borrow scope for an Optional<Actor>.none value
An optional-none value has "none" ownership, but still a borrow scope is needed.
Fixes a SIL verifier crash.
rdar://153066034
2025-06-11 13:35:21 +02:00
Michael Gottesman
f31236931b Change send-never-sendable of isolated partial applies to use SIL level info instead of AST info.
The reason I am doing this is that we have gotten reports about certain test
cases where we are emitting errors about self being captured in isolated
closures where the sourceloc is invalid. The reason why this happened is that
the decl returned by getIsolationCrossing did not have a SourceLoc since self
was being used implicitly.

In this commit I fix that issue by using SIL level information instead of AST
level information. This guarantees that we get an appropriate SourceLoc. As an
additional benefit, this fixed some extant errors where due to some sort of bug
in the AST, we were saying that a value was nonisolated when it was actor
isolated in some of the error msgs.

rdar://151955519
2025-06-10 08:09:32 -07:00
Andrew Trick
16fffd1704 Fix MoveOnlyWrappedTypeEliminator handling of store_borrow.
Defer visiting an instruction until its operands have been visited. Otherwise,
this pass will crash during ownership verification with invalid operand
ownership.

Fixes rdar://152879038 ([moveonly] MoveOnlyWrappedTypeEliminator ownership
verifier crashes on @_addressableSelf)
2025-06-09 19:45:09 -07:00
Arnold Schwaighofer
11942d70bd Merge pull request #81995 from aschwaighofer/fix_looprotate_densemap_subscript_bug
LoopRotate: Fix a by reference map bug under reallocation
2025-06-06 12:56:10 -07:00
eeckstein
a33ff9879a Merge pull request #81969 from eeckstein/temp-lvalue-elimination
Optimizer: improve TempLValueOpt
2025-06-06 15:30:29 +02:00
Doug Gregor
67b55566fe Merge pull request #82005 from DougGregor/generalize-checked-cast-options
[SIL] Generalize CastingIsolatedConformances to CheckedCastInstOptions
2025-06-05 08:43:09 -07:00
Erik Eckstein
2b9b2d243c Optimizer: improve TempLValueOpt
* re-implement the pass in swift
* support alloc_stack liveranges which span over multiple basic blocks
* support `load`-`store` pairs, copying from the alloc_stack (in addition to `copy_addr`)

Those improvements help to reduce temporary stack allocations, especially for InlineArrays.

rdar://151606382
2025-06-05 06:45:18 +02:00
Doug Gregor
bc4cf1236b [SIL] Generalize CastingIsolatedConformances to CheckedCastInstOptions
We are going to need to add more flags to the various checked cast
instructions. Generalize the CastingIsolatedConformances bit in all of
these SIL instructions to an "options" struct that's easier to extend.

Precursor to rdar://152335805.
2025-06-04 17:12:28 -07:00
Arnold Schwaighofer
1860967a29 Add a comment 2025-06-04 13:27:44 -07:00
Arnold Schwaighofer
59b8813807 LoopRotate: Fix a by reference map bug under reallocation
When using a densemap subscript expression on both sides of an
assignment in the same statement of the same map we run into the issue
that the map can reallocate because of the assignment but we are
referencing the value of the RHS map subscript by reference --
i.e we can reference deallocated memory.

Not good.

My attempts at making a reproducer crash failed.

rdar://151031297
2025-06-04 12:57:00 -07:00
Erik Eckstein
cbbf33dc55 LICM: fix a wrong tuple type when splitting loads
When creating a tuple, the type needs to be specified because otherwise, if the original tuple has labels, it will cause a type mismatch verification error.

rdar://152588539
2025-06-04 19:59:54 +02:00
Nate Chandler
c41fd47f1f [DestroyAddrHoisting] Skip init_enum_data_addrs.
A destroy of an `init_enum_data_addr` is not equivalent to a destroy of
the whole enum's address.  Treat such destroys just like destroys of
`struct_element_addr`s are treated: by bailing out.

rdar://152431332
2025-06-03 15:32:42 -07:00
Michael Gottesman
7d82d72b22 Merge pull request #81909 from gottesmm/pr-775f782ff711827a2a0dce73a522b6eb9bc2d484
[rbi] Lookthrough an invocation of DistributedActor.asLocalActor when determining actor instances.
2025-06-02 17:04:18 -07:00
Michael Gottesman
331626e6fa [rbi] Lookthrough an invocation of DistributedActor.asLocalActor when determining actor instances.
In this case, what is happening is that in SILGen, we insert implicit
DistributedActor.asLocalActor calls to convert a distributed actor to its local
any Actor typed form. The intention is that the actor parameter and result are
considered the same... but there is nothing at the SIL level to enforce that. In
this commit, I change ActorInstance (the utility that defines actor identity at
a value level) to look through such a call.

I implemented this by just recognizing the decl directly. We already do this in
parts of SILGen, so I don't really see a problem with doing this. It also
provides a nice benefit that we do not have to modify SILFunctionType to
represent this or put a @_semantic attribute on the getter.

NOTE: Generally, Sema prevents us from mixing together different actors. In this
case, Sema does not help us since this call is inserted implicitly by the
distributed actor implementation in SILGen. So this is not a problem in general.

rdar://152436817
2025-06-02 12:21:55 -07:00
nate-chandler
dd75d2ed82 Merge pull request #81854 from nate-chandler/rdar152195094
[DestroyAddrHoisting] Don't destructure NE aggs.
2025-05-30 11:32:12 -07:00
Nate Chandler
f7ca26ce93 [NFC] SIL: This utility takes a func not a module.
In preparation to use the function in the implementation.
2025-05-29 15:36:15 -07:00
Arnold Schwaighofer
7ac551636b Merge pull request #81714 from aschwaighofer/se0460
SE-0460: Introduce @specialized attribute
2025-05-28 12:03:48 -07:00
eeckstein
89bdb311ab Merge pull request #81780 from eeckstein/optimize-enum-comparison
Optimize enum comparisons
2025-05-28 07:01:29 +02:00
Michael Gottesman
746414bcd8 Merge pull request #81716 from gottesmm/pr-b82786e1ebbf00a9de46d342f0694a28999bc178
[send-non-sendable] Recurse to the full underlying value computation instead of just the object one when computing the underlying object of an address.
2025-05-27 11:39:48 -07:00
Erik Eckstein
ed8922bc8e PerformanceInliner: always inline synthesized enum comparisons if one of the operands is a constant enum
If there is a "constant" enum argument to a synthesized enum comparison, we can always inline it, because most of it will be constant folded anyway.
This ensures the compiler is not creating terrible code for very simple enum comparisons, like
```
   if someEnum == .someCase {
      ...
   }
```

rdar://85677499
2025-05-27 12:11:03 +02:00
eeckstein
ddca2bae98 Merge pull request #81706 from eeckstein/mandatory-temprvalue-elimination
Optimizer: Improve performance of large InlineArrays at Onone
2025-05-26 07:56:42 +02:00
Daniil Kovalev
1e403ecf5c [AutoDiff] Support custom derivatives for @_alwaysEmitIntoClient functions (#78908)
Consider an `@_alwaysEmitIntoClient` function and a custom derivative
defined
for it. Previously, such a combination resulted different errors under
different
circumstances.

Sometimes, there were linker errors due to missing derivative function
symbol -
these occurred when we tried to find the derivative in a module, while
it
should have been emitted into client's code (and it did not happen).

Sometimes, there were SIL verification failures like this:

```
SIL verification failed: internal/private function cannot be serialized or serializable: !F->isAnySerialized() || embedded
```

Linkage and serialization options for the derivative were not handled
properly,
and, instead of PublicNonABI linkage, we had Private one which is
unsupported
for serialization - but we need to serialize `@_alwaysEmitIntoClient`
functions
so the client's code is able to see them.

This patch resolves the issue and adds proper handling of custom
derivatives
of `@_alwaysEmitIntoClient` functions. Note that either both the
function and
its custom derivative or none of them should have
`@_alwaysEmitIntoClient`
attribute, mismatch in this attribute is not supported.

The following cases are handled (assume that in each case client's code
uses
the derivative).

1. Both the function and its derivative are defined in a single file in
   one module.

2. Both the function and its derivative are defined in different files
which
   are compiled to a single module.

3. The function is defined in one module, its derivative is defined in
another
   module.

4. The function and the derivative are defined as members of a protocol
extension in two separate modules - one for the function and one for the
   derivative. A struct conforming the protocol is defined in the third
   module.

5. The function and the derivative are defined as members of a struct
extension in two separate modules - one for the function and one for the
   derivative.

The changes allow to define derivatives for methods of `SIMD`.

Fixes #54445
<!--
If this pull request is targeting a release branch, please fill out the
following form:

https://github.com/swiftlang/.github/blob/main/PULL_REQUEST_TEMPLATE/release.md?plain=1

Otherwise, replace this comment with a description of your changes and
rationale. Provide links to external references/discussions if
appropriate.
If this pull request resolves any GitHub issues, link them like so:

  Resolves <link to issue>, resolves <link to another issue>.

For more information about linking a pull request to an issue, see:

https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
-->

<!--
Before merging this pull request, you must run the Swift continuous
integration tests.
For information about triggering CI builds via @swift-ci, see:

https://github.com/apple/swift/blob/main/docs/ContinuousIntegration.md#swift-ci

Thank you for your contribution to Swift!
-->
2025-05-25 09:47:15 -04:00
Arnold Schwaighofer
13ff5abdb8 Introduce @specialized attribute
Implements SE-0460 -- the non-underscored version of @specialized.

It allows to specify "internal" (not abi affecting) specializations.

rdar://150033316
2025-05-23 13:12:47 -07:00
Erik Eckstein
198d4ab0bb Optimizer: run TempRValueElimination also at Onone
Introduce a new pass MandatoryTempRValueElimination, which works as the original TempRValueElimination, except that it does not remove any alloc_stack instruction which are associated with source variables.

Running this pass at Onone helps to reduce copies of large structs, e.g. InlineArrays or structs containing InlineArrays.
Copying large structs can be a performance problem, even at Onone.

rdar://151629149
2025-05-23 18:56:56 +02:00
Erik Eckstein
85228f2c75 Optimizer: do mark_dependence simplification at Onone
* re-implement the SILCombine peephole as a Swift instruction simplification
* run this simplification also in the OnoneSimplification pass
2025-05-23 18:53:57 +02:00
Michael Gottesman
904ebc6784 [send-non-sendable] Recurse to the full underlying value computation instead of just the object one when computing the underlying object of an address.
Otherwise, depending on the exact value that we perform the underlying look up
at... we will get different underlying values. To see this consider the
following SIL:

```sil
  %1 = alloc_stack $MyEnum<T>
  copy_addr %0 to [init] %1
  %2 = unchecked_take_enum_data_addr %1, #MyEnum.some!enumelt
  %3 = load [take] %2
  %4 = project_box %3, 0
  %5 = load_borrow %4
  %6 = copy_value %5
```

If one were to perform an underlying object query on %4 or %3, one would get
back an underlying object of %1. In contrast, if one performed the same
operation on %5, then one would get back %3. The reason why this happens is that
we first see we have an object but that it is from a load_borrow so we need to
look through the load_borrow and perform the address underlying value
computation. When we do that, we find project_box to be the value. project_box
is special since it is the only address base we ever look through since from an
underlying object perspective, we want to consider the box to be the underlying
object rather than the projection. So thus we see that the result of the
underlying address computation is that the underlying address is from a load
[take]. Since we then pass in load [take] recursively into the underlying value
object computation, we just return load [take]. In contrast, the correct
behavior is to do the more general recurse that recognizes that we have a load
[take] and that we need to look through it and perform the address computation.

rdar://151598281
2025-05-22 10:11:40 -07:00
Anton Korobeynikov
799e0f81b0 [AutoDiff] Correct propagate adjoints for array literal values (#81676)
Fixes #81607
2025-05-22 03:03:28 -07:00
Erik Eckstein
e0f5888a8d SIL: define mark_dependence_addr to read and write to its address operand
This prevents simplification and SILCombine passes to remove (alive) `mark_dependence_addr`.
The instruction is conceptually equivalent to
```
  %v = load %addr
  %d = mark_dependence %v on %base
  store %d to %addr
```

Therefore the address operand has to be defined as writing to the address.
2025-05-21 20:03:53 +02:00
Anton Korobeynikov
bc94ac3342 [AutoDiff] Better diagnose non-differentiability for throwing functions (#81669)
Fixes #81608
2025-05-21 09:13:18 -07:00
eeckstein
0ceb5171ff Merge pull request #81649 from eeckstein/global-inlinearray-initialization
Allow more complex InlineArray initializations to end up in a statically initialized global
2025-05-21 06:24:28 +02:00
Michael Gottesman
a6901d8006 Merge pull request #81571 from gottesmm/pr-d7a7ebea7af14e2f9f1ce266febd0c983e3fc888
[rbi] Treat a partial_apply as nonisolated(unsafe) if all of its captures are nonisolated(unsafe).
2025-05-20 11:56:06 -07:00