Commit Graph

17 Commits

Author SHA1 Message Date
Erik Eckstein 78340fd42d Optimizer: de-virtualize deinits of non-copyable InlineArray elements
This is especially important for Embedded Swift because non de-virtualized deinits result in IRGen crashes.

Fixes a compiler crash in embedded
rdar://175984319
2026-05-05 07:27:13 +02:00
Andrew Trick 401d2ee072 Fix DeinitDevirtualizer to handle non-generic deinitializer function
Avoid passing an invalid substitution map into createApply.

Required conditions (from the bug report):
1. `~Copyable` struct with user-defined `deinit`
2. Nested inside a constrained extension where all generic parameters are concrete
3. A `destroy_value` or `destroy_addr` of the struct's value exists in some function
4. DeinitDevirtualizer runs (release-mode optimization pipeline)

Fixes rdar://173803881 ([GH:#88213] [SILOptimizer] DeinitDevirtualizer assertion
failure with ~Copyable type in all-concrete constrained extension)

Suggested by: coenttb
2026-04-01 20:56:42 -07:00
Erik Eckstein 9f0a9d77c0 DeinitDevirtualizer: don't devirtualize destroy_value [dead_end]
It doesn't make sense to de-virtualize `destroy_value [dead_end]` because such operations are no-ops anyway.
This is especially important for Embedded Swift, because introducing calls to generic deinit functions after the mandatory pipeline can result in IRGen crashes.

rdar://168171608
2026-02-04 09:10:24 +01:00
Erik Eckstein 6dde4c942e MandatoryPerformanceOptimizations: force de-virtualizing value-type deinits
Do this even if the function then contains references to other functions with wrong linkage.
MandatoryPerformanceOptimization fixes the linkage afterwards.
This is similar to what we already do with de-virtualizing class and witness methods: https://github.com/swiftlang/swift/pull/76032

rdar://168171608
2026-02-02 19:36:48 +01:00
Erik Eckstein bdf5a70258 DeinitDevirtualizer: don't create an invalid function_ref in a serialized function.
Serialized functions may not reference non-public functions.

Fixes a compiler crash
rdar://169022052
2026-01-28 13:10:30 +01:00
Anthony Latsis ac619010e3 SwiftCompilerSources/SIL: Fix APInt assertion failure on rebranch
The assertion is hit through `TypeValueInst.simplify` when constructing
an integer literal instruction with a negative 64-bit `Swift.Int` and a
bit width of 32 (the target pointer bit width for arm64_32 watchOS).
This happens because we tell the `llvm::APInt` constructor to treat the
input integer as unsigned by default in `getAPInt`, and a negative
64-bit signed integer does not fit into 32 bits when interpreted as
unsigned.

Fix this by flipping the default signedness assumption for the Swift API
and introducing a convenience method for constructing a 1-bit integer
literal instruction, where the correct signedness assumption depends on
whether you want to use 1 or -1 for 'true'.

In the context of using an integer to construct an `llvm::APInt`, there
are 2 other cases where signedness matters that come to mind:
1. A non-decimal integer literal narrower than 64 bits, such as
   `0xABCD`, is used.
2. The desired bit width is >64, since `llvm::APInt` can either
   zero-extend or sign-extend the 64-bit integer it accepts.

Neither of these appear to be exercised in SwiftCompilerSources, and
if we ever do, the caller should be responsible for either (1)
appropriately extending the literal manually, e.g.
`Int(Int16(bitPattern: 0xABCD))`, or (2) passing along the appropriate
signedness.
2025-09-24 09:37:42 +01:00
Erik Eckstein 49d3960c68 MandatoryPerformanceOptimization: de-virtualize deinits of builtin "destroyArray"
This is required for embedded swift.
rdar://157131184
2025-08-28 08:05:27 +02:00
Erik Eckstein 380ea889bc SIL: fix self-argument APIs in Function
`var selfArgument` should return an optional, i.e. nil if the function doesn't have a self argument.
2025-03-26 07:30:10 +01:00
Erik Eckstein 1f534e1c6f DeinitDevirtualizer: bail out for C++ move-only types.
We cannot de-virtualize C++ destructor calls of C++ move-only types because we cannot get its destructor in SIL.
Fixes a miscompile.
2025-01-27 09:59:48 +01:00
Erik Eckstein 9279a2c0d6 Devirtualization: make sure to de-serialize the body of shared deinit functions.
Sometimes it can happen that a deinit function, which is imported from another module, has shared linkage.
In this case it is important to de-serialize the function body. Otherwise it would be illegal SIL.

Unfortunately I don't have a test case for this.
2024-11-27 18:05:36 +01:00
Erik Eckstein 10782cf42b SwiftCompilerSources: introduce the AST module
As the optimizer uses more and more AST stuff, it's now time to create an "AST" module.
Initially it defines following AST datastructures:
* declarations: `Decl` + derived classes
* `Conformance`
* `SubstitutionMap`
* `Type` and `CanonicalType`

Some of those were already defined in the SIL module and are now moved to the AST module.
This change also cleans up a few things:
* proper definition of `NominalTypeDecl`-related APIs in `SIL.Type`
* rename `ProtocolConformance` to `Conformance`
* use `AST.Type`/`AST.CanonicalType` instead of `BridgedASTType` in SIL and the Optimizer
2024-10-02 07:10:29 +02:00
Erik Eckstein 52d6ae334d DeinitDevirtualizer: don't erase the destroy instruction if the the destroyed value can't be de-virtualized
This can happen if the destroyed type is resilient.
Fixes a verifier crash.
2024-08-12 13:34:50 +02:00
Erik Eckstein 715a765b6e Deinit-Devirtualization: fix a crash when trying to de-virtualize a non-copyable generic
rdar://129980818
2024-06-17 13:47:46 +02:00
Andrew Trick 2128c21106 Migrate SwiftCompilerSources to FunctionConvention.
Layers:
- FunctionConvention: AST FunctionType: results, parameters
- ArgumentConventions: SIL function arguments
- ApplyOperandConventions: applied operands

The meaning of an integer index is determined by the collection
type. All the mapping between the various indices (results,
parameters, SIL argument, applied arguments) is restricted to the
collection type that owns that mapping. Remove the concept of a
"caller argument index".
2024-01-03 12:24:50 -08:00
Erik Eckstein 11c74317a9 deinit-devirtualization: completely de-compose non-copyable destroys
Even if the destroyed value doesn't have a deinit.
This fixes a false alarm when a non-copyable value ends its lifetime in a function with performance annotations.

rdar://117002721
2023-12-13 20:03:02 +01:00
Erik Eckstein 285c60d959 deinit-devirtualization: correctly handle drop_deinit for address types
Make it clear that drop_deinit cannot be used to prevent a deinit called from a destroy_addr.
This is more a refactoring and clarification than a bug fix, because a destroy_addr cannot have a drop_deinit as operand, anyway.
2023-11-30 14:33:02 +01:00
Erik Eckstein 96e57d62f6 Optimizer: de-virtualize deinits of non-copyable types
In regular swift this is a nice optimization. In embedded swift it's a requirement, because the compiler needs to be able to specialize generic deinits of non-copyable types.
The new de-virtualization utilities are called from two places:

* from the new DeinitDevirtualizer pass. It replaces the old MoveOnlyDeinitDevirtualization, which is very basic and does not fulfill the needs for embedded swift.

* from MandatoryPerformanceOptimizations for embedded swift
2023-11-27 09:21:34 +01:00