Commit Graph

95 Commits

Author SHA1 Message Date
Aidan Hall 070f7923d9 Bridging: Rename FunctionConvention.results to resultsWithError
This matches the name of the C++ method it bridges, and avoids the ambiguity of
the previous name.
2026-05-18 14:47:05 +01:00
Erik Eckstein 8e6560aa78 SIL: fix handling of index_addr in AccessUtils
Fixes a miscompile when the index of `index_addr` is a negative integer constant. In this case two access paths were considered overlapping while in reality they reference two different array elements.

The miscompile manifested in the dead-store-elimination pass, but could potentially also show up in other passes, which use this utility.

https://github.com/swiftlang/swift/issues/77558
rdar://176820188
2026-05-12 19:59:37 +02:00
Joe Groff 097b0d3400 SIL: Split unchecked_*_enum_data_addr according to ownership and effects.
We cannot use spare bits or other overlapping storage layout tricks with fundamentally
address-only enums, and we can take advantage of this to do borrowing switches or other
in-place projections without copying the value. However, for resilient enums, the
implementation may use spare bit packing, but the type must be handled address-only
outside of its defining module, and we didn't have a way to express that with
borrowing switch. Optimization passes have also been running into problems with the
complexity that we were using `unchecked_take_enum_data_addr` sometimes as a pure
operation. This patch splits the instruction into three:

- `unchecked_inplace_enum_data_addr` represents a nondestructive in-place enum
  projection. It is only allowed for enums whose projection operation is
  nondestructive.
- `unchecked_take_enum_data_addr` represents a destructive enum projection,
  invalidating the enum and leaving the payload to be further consumed.
  This matches the current instruction's semantics.
- `unchecked_borrow_enum_data_addr` represents a borrowing enum projection.
  The instruction takes a second operand for "scratch" space, which the
  enum representation may be copied into in order to avoid invalidating the
  enum value, so the result is dependent on the lifetime of both the
  original enum and the scratch buffer. This allows for borrowing switches
  over resilient enums.

`unchecked_borrow_enum_data_addr` is implemented by taking advantage of the
"address-only enums can't do spare bit optimization" property at runtime.
We inspect the operand type's bitwise-borrowability from its metadata. If
the type is bitwise-borrowable, then we are allowed to bitwise-copy the
enum to the scratch space and apply the projection to the scratch space,
preserving the original value. If the type is not bitwise-borrowable, then
we cannot use spare bit optimization in its layout, so we apply the
projection in-place.

Fixes rdar://174952822.
2026-04-27 15:40:37 -07:00
Erik Eckstein dd4f3073ca DestroyHoisting: add a complexity limit for very large functions
For very large functions this optimization can run into noticeable quadratic behavior.
Therefore, ignore functions with more than 100000 SIL instructions.
This limit is large enough to not affect most of real-world SIL functions.
2026-03-16 16:12:28 +01:00
Erik Eckstein a03ac54643 Cloner: ignore type-dependent operands when recursively cloning instructions
Fixes a crash
2026-02-20 18:28:12 +01:00
Erik Eckstein 12a798de3a SIL: improve pushPredecessors and pushSuccessors of InstructionWorklist
* add a `isTransparent` closure argument to speed up iteration for transparent blocks.
* add documentation and tests
2026-02-11 06:43:45 +01:00
Joe Groff b11e8c985a SIL: Handle dereference_borrow returns in SILGenCleanup.
Make sure an `end_borrow` is emitted on the `dereference_borrow` so that
SILGenCleanup recognizes this pattern and lowers it to a `return_borrow`
as it does for returned `load_borrow`s. Add support to the Swift implementation
of `BorrowingInstruction` for `DereferenceBorrow`.
2026-01-23 08:02:09 -08:00
Erik Eckstein 54347dbfd7 SIL Verifier: enable a check for end-borrows
This check requires complete OSSA 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 87dc1c5d8b SIL verifier: accept "owned" ownership for borrowed-from's enclosing values
"none" is like "owned" and can happen e.g. if a non-trivial enum is constructed with a trivial case:
```
  %1 = enum $Optional<AnyObject>, #Optional.none!enumelt   // ownership: none
  ...
  %3 = borrowed %phi from (%1)
```

Fix a false verification error
https://github.com/swiftlang/swift/issues/86407
rdar://167833469
2026-01-12 08:56:31 +01:00
Erik Eckstein 6ce2df2ed1 SIL Verifier: workaround a MoveOnlyChecker pass bug
The MoveOnlyChecker is inserting a `destroy_addr` in a read-only access scope, which is illegal.
Relax the verification of read-only access scope by only looking at dynamic scopes.

Fixes a verifier crash.
rdar://166896665
2025-12-22 10:57:41 +01:00
eeckstein fd8c3ea046 Merge pull request #86042 from eeckstein/sil-unit-tests
SwiftCompilerSources: convert all unit-test passes to real tests
2025-12-15 14:38:50 +00:00
Erik Eckstein c822615dc2 Optimizer: convert the UpdateBorrowedFromPass pass to a test
And remove the now empty TestPasses directory.
2025-12-15 10:01:51 +01:00
Erik Eckstein bff873dea0 Optimizer: convert the SILPrinter and TestInstructionIteration passes to tests 2025-12-15 10:01:41 +01:00
Erik Eckstein c639c716b9 Optimizer: convert the RangeDumper pass to a test 2025-12-15 10:01:41 +01:00
Mahdi Bahrami d1bea5b184 Minor fix in HasShortDescription doc-comments 2025-12-15 11:54:41 +03:30
Erik Eckstein edacd4c4e3 Optimizer: convert the AccessDumper from a pass to a test 2025-12-15 09:09:41 +01:00
Joe Groff da4e72cf2d SIL verifier: The atInstruction/atArgument parameter to require should not be optional.
The underlying C++ code expects a non-null `Instruction*` or `SILArgument*` pointer, and
most of the contextual information in a verifier error is derived from these arguments,
so it doesn't really make sense for the Swift level interface to present these arguments
as optional.
2025-12-10 10:27:56 -08:00
Erik Eckstein 9ceb8b83c1 SIL-Verifier: Don't verify that there are no stores in read-only access scopes if there is a conflicting scope
This is a programming error, but the compiler should not crash. The violation is caught at runtime.
2025-12-04 21:12:32 +01:00
Michael Gottesman c876c1ee88 [sil-verifier] Split SILVerifier verificationFailure into separate functions for Instructions, Arguments, and add a variant for Values.
This also required me to change how we handled which instruction/argument we
emit an error about in the verifier. Previously we were using two global
variables that we made nullptr to control which thing we emitted an error about.
This was unnecessary. Instead I added a little helper struct that internally
controls what we will emit an error about and an external "guard" RAII struct
that makes sure we push/pop the instruction/argument we are erroring upon
correctly.
2025-11-21 11:21:15 -08:00
Meghana Gupta 32cd86f719 Update access base for borrow/mutate accessors in SwiftCompilerSources 2025-11-06 10:55:39 -08:00
Andrew Trick f8a847132c Fix ApplySite.isAddressable to handle inout arguments. 2025-10-26 22:09:19 -07:00
Erik Eckstein f32d4be69f SIL Verifier: don't run read-only access scope verification in lowered SIL
LoadableByAddress in lowered SIL can insert `copy_addr`s inside read-only access scope.

rdar://163248403
2025-10-23 14:59:02 +02:00
Erik Eckstein 4f1cbbd07d SIL Verifier: verify that inside a read-only access scope there are no stores to the memory location
This will e.g. catch violations like
```
  %1 = begin_access [read] %0
  store %2 to %0
  end_access %1
```

Also, fix all the sil tests which violate that.
2025-10-22 20:55:21 +02: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 https://github.com/swiftlang/swift/pull/83728/commits/eb1d5f484c9f4dae73a3779191bfdf917fd07a49.
2025-10-16 10:12:33 +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
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 c3612bafb8 SIL: make var OperandArray.values available for all kind of operand sequences 2025-10-06 09:47:40 +02:00
Erik Eckstein 39b9969049 SIL: use Test for the SmallProjectionPath's unit tests
Now that we have `Test` available in the SIL module, we can use it for the SmallProjectionPath's unit tests and get rid of the RunUnitTests pass.
2025-09-24 11:46:34 +02:00
eeckstein 6557efc81d Merge pull request #84437 from eeckstein/fix-smallprojectionpath
fix handling of large indices in SmallProjectionPath
2025-09-23 07:13:31 +02:00
Erik Eckstein da17c26bae fix handling of large indices in SmallProjectionPath
* Fix the right shift operator which didn't work if the number of bits is exactly 64
* Detect overflow when combining indices

Such large indices usually don't appear in real code, except in internal String operations where (potentially large) integer values are treated as pointers.

Fixes a compiler crash
https://github.com/swiftlang/swift/issues/84372
rdar://160863199
2025-09-22 18:49:24 +02:00
Jakub Florek 38f28c1049 Reapply "Merge pull request #84045 from MAJKFL/new-sil-licm-pass-copy-ownership"
This reverts commit d2cd281d4c.
2025-09-19 16:06:35 +01:00
Jakub Florek d2cd281d4c Revert "Merge pull request #84045 from MAJKFL/new-sil-licm-pass-copy-ownership"
This reverts commit a5c6156525, reversing
changes made to 2b6ea81b9e.
2025-09-17 15:52:48 +01:00
Jakub Florek a5c6156525 Merge pull request #84045 from MAJKFL/new-sil-licm-pass-copy-ownership
Ownership support for LICM
2025-09-16 11:02:28 +01:00
Jakub Florek df24019195 Rename Cloner.cloneRecursivelyToGlobal. 2025-09-10 16:18:50 +01:00
Meghana Gupta ce128e71e2 Update SIL verification for borrow accessors 2025-09-09 15:25:08 -07:00
Meghana Gupta 0bec28f510 Update borrowed from for guaranteed results of borrow accessors 2025-09-09 15:20:05 -07:00
Erik Eckstein b8a49692eb Optimizer: add TypeSubstitutionCloner and func cloneAndSpecializeFunction
Also move `func cloneFunction` from ContextCommon.swift to OptUtils.swift
2025-09-04 08:15:45 +02:00
Erik Eckstein 231042b9a8 SIL: some Cloner cleanups and improvements
* move some Cloner utilities from ContextCommon.swift directly into Cloner.swift
* add an `cloneRecursively` overload which doesn't require the `customGetCloned` closure argument
* some small cleanups
2025-09-04 08:15:45 +02: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
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
Erik Eckstein e5081a511f AliasAnalysis: fix aliasing of ref_tail_addr access bases
In contrast to `ref_element_addr`, tail addresses can also be obtained via a superclass (in case the derived class doesn't add any stored properties).
Therefore if the instance types differ by sub-superclass relationship, they may alias.

Fixes a miscompile
2025-08-28 08:09:39 +02:00
Andrew Trick eb1d5f484c [NFC] SwiftCompilerSources: add a correctly named filterUsers API
Rename existing filterUsers to filterUses.
2025-08-14 09:08:11 -07:00
Erik Eckstein b38490b2e2 SwiftCompilerSources: move PhiUpdater.swift from the Optimizer to the SIL module 2025-07-28 14:19:11 +02:00
Erik Eckstein 319f49ad9f SwiftCompilerSources: move the Verifier to the SIL module 2025-07-28 14:19:11 +02:00
Erik Eckstein 1eb49ec186 SwiftCompilerSources: move ForwardingUtils and BorrowUtils to the SIL module 2025-07-28 14:19:11 +02:00
Erik Eckstein a767261fec SwiftCompilerSources: move the getAccessBaseTest to the SIL module 2025-07-28 14:19:10 +02:00
Erik Eckstein e95283ba38 SwiftCompilerSources: make the testing infrastructure available in the SIL module
add `Test`, which is the SIL-equivalent of `FunctionTest`.
It's invocation closure gets a `TestContext` instead of a `FunctionContext`.

^ The commit message #2 will be skipped:

^ - test
2025-07-28 14:19:10 +02:00
Erik Eckstein e2129b50ce SwiftCompilerSources: move the SSAUpdater utility from the Optimizer to the SIL module 2025-07-28 14:19:07 +02:00