Commit Graph

43 Commits

Author SHA1 Message Date
Gábor Horváth cfeda37650 Merge pull request #88622 from Xazax-hun/tsan-effects-modeled
[SILOptimizer] Correctly compute the effects of TSan instrumentation
2026-05-06 12:20:31 +01:00
Erik Eckstein d28549af34 Optimizer: workaround for fast type casting to the FullApplySite and ReturnInstruction protocols
Rather than doing a standard swift runtime cast to an existential, explicitly check for the conforming instruction classes, which is much faster.
The new `isFullApplySite` and `isReturnInstruction` casting utilities are used in the (very few) time critical places in the optimizer.

After toolchain builders are upgraded to a compiler version which includes the fix for this problem (https://github.com/swiftlang/swift/pull/88270), we don't need this workaround anymore and the regular `as`/`is` casts can be used again.

Now the runtime casts doesn't show up prominently in compile-time profiling data anymore - even with a host compiler which doesn't implement fast type checks, yet.

rdar://173916206
2026-04-30 17:53:39 +02:00
Gabor Horvath 12b6809813 [SILOptimizer] Correctly compute the effects of TSan instrumentation
Passing a C++ object to the TSanInOutAccess builtin resulted in an extra
temporary copy. This copy was not optimized out because the semantics of this
builtin was not understood by the optimizer. Teaching the utils that this
intrinsic does not actually modify the object, does not escape it,
and does not read it lets the optimizer eliminate this copy.

Strictly speaking, the test code that uses interop is not safe/correct,
this is why it had a lifetime issue.

rdar://173921363
2026-04-30 11:21:17 +01:00
Erik Eckstein b18ba61e89 Optimizer: natively implement Instruction.isDeinitBarrier in swift
No need to bridge to the C++ implementation, because the swift implementation is very simple
2026-04-08 21:34:43 +02:00
Meghana Gupta a0eb58fa07 Handle return_borrow in a few more places in SwiftCompilerSources 2025-11-06 10:55:31 -08:00
Meghana Gupta 0bd6825aa2 Update SIL utilities for borrow and mutate accessors under opaque values mode 2025-10-20 09:05:38 -07:00
Meghana Gupta 51c64d5fda Update SideEffects for borrow accessors returning addresses
Add a read effect on the self parameter. Without this, the self parameter can get dead code eliminated by the GenericSpecializer.
2025-09-14 23:38:03 -07:00
Aidan Hall 6a263f8ddb ComputeSideEffects: Compute for functions with effect attributes
After computing side effects, we also remove any global or argument effects that
are computed to happen, but are defined not to, based on the effect attribute.

This allows us to compute the deinit_barrier effect for such functions, fixing
the test case here: rdar://155870190

This supercedes #38324.
2025-08-22 11:42:09 +01:00
Erik Eckstein 41a6b8e257 SwiftCompilerSources: move SIL-related Context APIs from Optimizer to the SIL module 2025-07-28 14:19:11 +02:00
Erik Eckstein 8f39c3cad8 Swift SIL: rename isTakeOfSrc -> isTakeOfSource and isInitializationOfDest -> isInitializationOfDestination
Trying to avoid abbreviations in ABI names
2025-05-06 12:35:21 +02:00
Erik Eckstein 65178170b1 ComputeSideEffects: handle program termination functions which are defined in the same module
This case was neglected. The fix can result in better side effect analysis, e.g. in the stdlib core module.
2025-04-29 20:30:21 +02:00
Erik Eckstein 3ec5d7de24 SIL: replace the is_escaping_closure instruction with destroy_not_escaped_closure
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand
2025-01-24 19:23:27 +01:00
Erik Eckstein e683d7b679 ComputeSideEffects: fix a corner case with consuming indirect arguments in dead-end functions
Usually there _must_ be a read from a consuming in-argument, because the function has to consume the argument.
But in the special case if all control paths end up in an `unreachable`, the consuming read might have been dead-code eliminated.
Therefore make sure to add the read-effect in any case. Otherwise it can result in memory lifetime failures at a call site.

fixes a memory lifetime failure

rdar://134881045
2024-08-29 18:51:46 +02:00
Erik Eckstein c96b196ffa SwiftCompilerSources: bridge SILLinkage
Make SILLInkage available in SIL as `SIL.Linkage`.
Also, rename the misleading Function and GlobalVariable ABI `isAvailableExternally` to `isDefinedExternally`
2024-08-22 08:56:27 +02:00
Alexander Cyon c18a24e499 [SwiftCompilerSources] Fix typos 2024-08-08 22:22:39 -07:00
Erik Eckstein 9eddb24c41 EscapeUtils: replace ...byWalkingDown APIs with an initialWalkingDirection parameter
It simplifies the EscapeUtils API
NFC
2024-07-29 17:33:43 +02:00
Akira Hatanaka 42bc49d3fe Add a new parameter convention @in_cxx for non-trivial C++ classes that are passed indirectly and destructed by the caller (#73019)
This corresponds to the parameter-passing convention of the Itanium C++
ABI, in which the argument is passed indirectly and possibly modified,
but not destroyed, by the callee.

@in_cxx is handled the same way as @in in callers and @in_guaranteed in
callees. OwnershipModelEliminator emits the call to destroy_addr that is
needed to destroy the argument in the caller.

rdar://122707697
2024-06-27 09:44:04 -07:00
Erik Eckstein 4b2973a43c ComputeSideEffects: correctly handle escaping arguments
If an argument escapes in a called function, we don't know anything about the argument's side effects.
For example, it could escape to the return value and effects might occur in the caller.

Fixes a miscompile
https://github.com/apple/swift/issues/73477
rdar://127691335
2024-05-13 18:27:49 +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
Ikko Eltociear Ashimine 680c6f3ae2 Fix typo in ComputeSideEffects.swift
mutliple -> multiple
2023-10-03 17:39:39 +09:00
Manu 02b5fa2c8e Fix some typos in the codebase 2023-08-31 18:50:10 -03:00
Andrew Trick 8a71844456 Cleanup SIL ComputeSideEffects for partial_apply arguments 2023-08-29 16:58:56 -07:00
Andrew Trick 4ce6fcf18f Fix SIL function side effects to handle unapplied escaping
Fixes rdar://113339972 DeadStoreElimination causes uninitialized closure context

Before this fix, the recently enabled function side effect implementation
would return no side effects for a partial apply that is not applied
in the same function. This resulted in DeadStoreElimination
incorrectly eliminating the initialization of the closure context.

The fix is to model the effects of capturing the arguments for the
closure context. The effects of running the closure body will be
considered later, at the point that the closure is
applied. Running the closure does, however, depend on the captured
values to be valid. If the value being captured is addressible,
then we need to model the effect of reading from that memory. In
this case, the capture reads from a local stack slot:

    %stack = alloc_stack $Klass
    store %ref to %stack : $*Klass
    %closure = partial_apply [callee_guaranteed] %f(%stack)
      : $@convention(thin) (@in_guaranteed Klass) -> ()

Later, when the closure is applied, we won't have any reference back
to the original stack slot. The application may not even happen in a caller.

Note that, even if the closure will be applied in the current
function, the side effects of the application are insufficient to
cover the side effects of the capture. For example, the closure
body itself may not read from an argument, but the context must
still be valid in case it is copied or if the capture itself was
not a bitwise-move.

As an optimization, we ignore the effect of captures for on-stack
partial applies. Such captures are always either a bitwise-move
or, more commonly, capture the source value by address. In these
cases, the side effects of applying the closure are sufficient to
cover the effects of the captures. And, if an on-stack closure is
not invoked in the current function (or passed to a callee) then
it will never be invoked, so the captures never have effects.
2023-08-16 11:58:11 -07:00
Erik Eckstein 799bd0a5f5 Swift Optimizer: some reformatting in the optimization passes
Use tail closures for all optimization passes.
NFC.
2023-08-04 10:33:52 +02:00
Erik Eckstein efcd90af7d Swift SIL: rename ownership enums and properties in LoadInst and StoreInst
`ownership` is a bad name in `LoadInst`, because it hides `Value.ownership`.
Therefore rename it to `loadOwnership`.
Do the same for ownership in StoreInst to be consistent.
2023-07-11 22:33:02 +02:00
Erik Eckstein f1095556c9 Swift SIL: let var UnaryInstruction.operand return an Operand and not a Value
To avoid confusion. Instead add specific getters for unary instructions with dedicated names.

NFC
2023-02-21 17:57:29 +01:00
Erik Eckstein dfde580872 Effects: bail if effects are requested for not supported projection paths
Effects are only defined for operations which don't involve a load.
 In case the argument's path involves a load we need to return the global effects.
2023-02-11 08:55:20 +01:00
Erik Eckstein cc60815bfe ComputeSideEffects: fix wrong side effect computation of releases/destroys
Only global side effects of the destructor were considered, but side effects weren't attributed to the released value.

rdar://105237110
2023-02-11 08:55:20 +01:00
Erik Eckstein cc68bd98c9 Swift Optimizer: rework pass context types and instruction passes
* split the `PassContext` into multiple protocols and structs: `Context`, `MutatingContext`, `FunctionPassContext` and `SimplifyContext`
* change how instruction passes work: implement the `simplify` function in conformance to `SILCombineSimplifyable`
* add a mechanism to add a callback for inserted instructions
2023-01-16 15:11:34 +01:00
Erik Eckstein c32d6cd0fb EscapeUitls: some refactoring 2023-01-16 15:11:34 +01:00
Erik Eckstein 6c35258f83 Swift SIL: rename parent accessors to parentX, e.g. Instruction.parentBlock
It makes it easier to read
2023-01-16 15:11:34 +01:00
Erik Eckstein 1f0f9d65b9 ComputeSideEffects: ignore side effects of debug_value with address operands
We already ignored side effects of debug_value with non-address operands. Now also do this for address operands.
2023-01-05 09:56:11 +01:00
Erik Eckstein e26affacbd ComputeSideEffects: correct side effects for destroy_addr
A destroy_addr also involves a read from the address. It's equivalent to a `%x = load [take]` and `destroy_value %x`.
It's also a write, because the stored value is not available anymore after the destroy.

Fixes a compiler crash in SILMem2Reg.

rdar://103879105
2023-01-05 09:56:11 +01:00
Anton Korobeynikov dd6f468d09 Ensure that partial_apply of partial_apply does not produce conservative global side effects. (#62351)
Fixes #62249
2022-12-02 06:14:46 -08:00
Erik Eckstein 82107c5bf2 ComputeSideEffects: consider effects in dead-end blocks
It was a wrong assumption that we can ignore effects in dead-end blocks.
2022-11-09 08:06:19 +01:00
Erik Eckstein ab2fe452f9 ComputeSideEffects: checking for unknown argument uses need to consider type which contain raw pointers 2022-11-09 08:06:19 +01:00
Erik Eckstein dbb4d4db32 ComputeSideEffects: fix a typo in a comment 2022-11-09 08:06:19 +01:00
Erik Eckstein b275d987b5 ComputeSideEffects: handle reference count reading instructions.
Conservatively model those effects as "destroy" effects.
2022-10-20 09:20:28 +02:00
Erik Eckstein 8961e2982e swift side effects: some additions and refactoring
add `Function.getSideEffects(forArgument:,atIndex:,withConvention:)`
2022-10-20 09:20:28 +02:00
Erik Eckstein 60609eb809 Swift SIL: invert Type.isNonTrivialOrContainsRawPointer to Type.isTrivialNonPointer
This is consistent with `Type.isTrivial`.
Also, introduce corresponding properties in `Value`: `hasTrivialType` and `hasTrivialNonPointerType`, because
1. It's less to type than `Type.isTrivial(in: function)` because `Value` knows in which function it is.
2. It fixes the corner case where value is an `Undef`, which has not parent function.
2022-10-20 09:20:28 +02:00
Erik Eckstein 0a2d233d1e compute effects: Don't modify the effects if they didn't change
This avoids sending a change notification which can trigger unnecessary other invalidations.
2022-10-20 09:20:28 +02:00
Nate Chandler 4476088ab5 [ComputeSideEffects] Track deinit-barrier-ness.
Functions "are deinit barriers" (more pedantically, applies of functions
are deinit barriers) if any of their instructions are deinit barriers.
During side-effect analysis, when walking a function's instructions for
other global effects, also check for the deinit-barrier effect.  If an
instruction is found to be a deinit barrier, mark the function's global
effects accordingly.

Add SILFunction::isDeinitBarrier to conveniently access the effects
computed during ComputeSideEffects.

Update the isBarrierApply predicate to iterate over the list of callees,
if complete, to check whether any is a deinit barrier.  If none is, then
the apply is not a deinit barrier.
2022-10-18 21:23:22 -07:00
Erik Eckstein 741c6c38df Swift Optimizer: add the ComputeSideEffects pass.
Computes the side effects for a function, which consists of argument- and global effects.
This is similar to the ComputeEscapeEffects pass, just for side-effects.
2022-10-05 07:38:11 +02:00