Commit Graph

372 Commits

Author SHA1 Message Date
Erik Eckstein
ee18f8c168 Simplification: fix a crash in alloc_stack simplification
Handle the case that a type dependent operand is a dynamic-self argument and not an open-existential instruction.

rdar://148258964
2025-04-01 10:58:45 +02:00
Andrew Trick
97b249bd11 Merge pull request #80263 from atrick/markdep-addr
SIL: add mark_dependence_addr
2025-03-26 10:33:42 -07: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
Andrew Trick
69b6b1d309 LifetimeDependenceDefUseWalker: handle addressable dependencies 2025-03-25 23:02:45 -07:00
Andrew Trick
d9dd93560d Support mark_dependence_addr in SIL passes. 2025-03-25 23:02:45 -07:00
Andrew Trick
ea8cb3c1b4 LifetimeDependenceDiagnostics: recognize store_borrow ranges
Avoid an unnecessary diagnostic when the dependent value's uses are covered by a
StoreBorrow.
2025-03-20 12:17:24 -07:00
Slava Pestov
8bcd09aaa4 SIL: Preliminary refactoring of SILWitnessTable::AssociatedConformanceWitness
The Protocol field isn't really necessary, because the conformance
stores the protocol. But we do need the substituted subject type
of the requirement, just temporarily, until an abstract conformance
stores its own subject type too.
2025-03-18 19:38:42 -04:00
Andrew Trick
ce18a4bce8 Merge pull request #79985 from atrick/fix-destroyhoist
Fix DestroyHoisting: InteriorLiveness for noescape closures
2025-03-18 05:07:27 -07:00
Erik Eckstein
37455b6ab6 Optimizer: use formal types instead of SIL types for classifying dynamic casts.
Casts always work with formal rather than lowered types.
This fixes a potential bug when lowered types are different than formal types, like function types.
2025-03-14 09:45:27 +01:00
Erik Eckstein
d52f7d1619 AST/SIL: Refactor and simplify AST.Type, AST.CanonicalType and SIL.Type
* let `SIL.Type` conform to `TypeProperties` to share the implementation of common type properties between the AST types and `SIL.Type`
* call references to an `AST.Type` `rawType` (instead of just `type`)
* remove unneeded stuff
* add comments
2025-03-14 09:40:22 +01:00
Andrew Trick
995c74966d Fix DestroyHoisting: InteriorLiveness for noescape closures
InteriorLiveness has a new "visitInnerUses" mode used by DestroyHoisting. That
mode may visit dependent values, which was not valid for noescape
closures. ClosureLifetimeFixup inserts destroys of noescape closures after the
destroys of the captures. So following such dependent value could result in an
apparent use-after-destroy. This causes DestroyHoisting to insert redundant
destroys.

Fix: InteriorUses will conservatively only follow dependent values if they are
escapable. Non-escapable values, like noescape closures are now considered
escapes of the original value that the non-escapable value depends on. This can
be improved in the future, but we may want to rewrite ClosureLifetimeFixup first.

Fixes the root cause of: rdar://146142041
2025-03-13 09:17:31 -07:00
Erik Eckstein
23b4c6fc34 embedded: fix specialization of associated conformance entries in witness tables
When creating a specialized witness table, we need to get the right specialized conformance.
In IRGen don't emit associated conformance witness table entries if the protocol is not a class protocol.
In this case the associated type can never be used to create an existential. Therefore such a witness table entry is never used at runtime in embedded swift.

Fixes a compiler crash

rdar://146448091
2025-03-11 11:33:10 +01:00
Erik Eckstein
5016e35880 Optimizer: add two small utilities for instructions
* `func Instruction.dominatesInSameBlock(_ otherInst: Instruction) -> Bool`
* `var Instruction.concreteTypeOfDependentExistentialArchetype`
2025-03-07 15:59:34 +01:00
Erik Eckstein
810064b7dc Cleanup and additions to AST and SIL Type/CanonicalType
* factor out common methods of AST Type/CanonicalType into a `TypeProperties` protocol.
* add more APIs to AST Type/CanoncialType.
* move `MetatypeRepresentation` from SIL.Type to AST.Type and implement it with a swift enum.
* let `Builder.createMetatype` get a CanonicalType as instance type, because the instance type must not be a lowered type.
2025-03-07 15:59:33 +01:00
Andrew Trick
b3f401d346 LifetimeDependenceScopeFixup: handle indirect yields & fix bugs
Handle coroutines that yield an address. Fix bugs involving extension of
multiple nested scopes that depend on multiple coroutine operands.
2025-03-05 02:12:21 -08:00
Andrew Trick
3019c843be LifetimeDependence: allow dependence on the store_borrow address
Previously, the dependence was on the stored value, but that is incorrect for
'@'_addressable parameters.
2025-03-03 11:56:37 -08:00
Andrew Trick
bc6200e592 SwiftCompilerSources: bridge '@'_addressable dependencies 2025-03-03 11:56:37 -08:00
Andrew Trick
6e75813a9b OwnershipLiveness fix: support visitInnerUses
DestroyHoisting is using this utility. This requires complete liveness. But we
can't rely on complete liveness because complete lifetimes is not
enabled. Instead, we use a visitInnerUses flag to try to ignore borrow
scopes. That flag was never properly implemented. Make an attempt here.
2025-02-26 02:54:37 -08:00
Andrew Trick
2542515b69 OwnershipLiveness.swift fix: don't ignore trivial types
interiorPointerUse is dealing with addresses, so the memory still needs to be
alive regardless of the type.
2025-02-26 02:33:13 -08:00
Andrew Trick
747b1ac28a Fix OwnershipLivenes.swift visitInnerBorrowUses
Always visit the use even if it is the beginning of an inner borrow. This
provides a "better" liveness result in the case of dead borrows and gives the
client a chance to see/intercept all uses.
2025-02-26 01:42:19 -08:00
Andrew Trick
0f728f0514 Fix BorrowingInstruction.visitEndBorrows to handle borrowed-from
For borrowed-from of a reborrow, the value is the block argument. So we need to
look through the borrowed-from user.
2025-02-26 01:40:42 -08:00
Andrew Trick
38137c5383 OwnershipLiveness.swift: add comments
and rename visitOwnedDependentUses
2025-02-26 00:39:25 -08:00
Andrew Trick
406afc7202 SwiftCompilerSources: Fix InteriorUseWalker with visitInnerUses.
Add support to all kinds of borrowing instructions so we visit all their inner uses.
2025-02-26 00:38:18 -08:00
Andrew Trick
8decfa4910 Add BorrowingInstruction.innerValue 2025-02-26 00:37:20 -08:00
Andrew Trick
083ab98818 Simplify OwnershipLiveness.swift, remove reborrowingUse.
Remove complexity around reborrows. They no longer need special treatment.
2025-02-25 23:36:14 -08:00
Andrew Trick
b854ab18c1 OwnershipUseVisitor.visitInnerBorrowUses: support dependent values
Add liveness support for dependent values: borrowed-from & mark_dependence so
they aren't reported as unknown uses.
2025-02-25 23:08:55 -08:00
Andrew Trick
907097421b Add BorrowingInstruction.dependentValue and .scopedValue
This consolidates the rules for borrow scopes so we can simplify interior liveness.
2025-02-25 23:08:55 -08:00
Andrew Trick
5864004c4e SwiftCompilerSources: remove adjacent phis from InteriorUseWalker.
The extra complexity for traversing phis is not needed now that it handles
borrowed-from instructions. Remove the redundant logic because it complicates
the liveness algorithm and generates confusing results.
2025-02-25 23:08:54 -08:00
Andrew Trick
5a1a487d14 Fix InteriorUseWalker to handle dependent lifetimes as inner scopes
Inner scopes must all be reported because the walker assumes they are
complete. It is up to the client to either complete them or recursively follow
them.
2025-02-25 23:08:54 -08:00
Andrew Trick
7f6962adff Fix OwnershipUseVisitor.dependentUse()
Check if the forwarded value is trivial, not the base value. Presumably, we
won't call this visitor at all if the base is trivial.

Record a dependent non-Escapable values as a pointer-escape. InteriorUseWalker
does not handle lifetime dependencies. That requires
LifetimeDependenceDefUseWalker.
2025-02-25 23:08:54 -08:00
Andrew Trick
f1792d80b3 Fix BorrowingOperand.visitScopeEndingUses
Only return false if the visitor returns false. Clients were ignoring the
result.

If the BorrowingOperand does not create a borrow scope, call visitUnknownUse
instead.

Until we have complete lifetimes, to avoid breaking code that cannot handle dead
defs, consider a dead borrow scope to be an unknown use.
2025-02-25 23:08:54 -08:00
Andrew Trick
a4a675ee00 Remove adjacent phi handling from InteriorUseWalker.
At least the Swift utilities should rely on borrowed-from.
2025-02-25 23:08:54 -08:00
Andrew Trick
6188d29026 Handle borrowed-from in OwnershipUseVisitor.
If it is not a reborrow, then it produces a dependent value, just like
mark_dependence.
2025-02-25 23:08:54 -08:00
Andrew Trick
e22541544c Remove unused computeInterorLiveness API.
This encourages the client to check whether InteriorLivenessResult is valid or
escaping before using the instruction range.
2025-02-25 23:08:54 -08:00
Andrew Trick
fda53929c2 Add support for borrowed-from to BorrowingInstruction.
All instructions with a "Borrow" operand ownership must be valid
BorrowingInstructions.
2025-02-25 23:08:54 -08:00
Andrew Trick
6c99017588 Minor comment cleanup and code formatting.
Extracted from the functional changes for clarity.
2025-02-25 23:08:53 -08:00
Andrew Trick
75e84f1e97 Rename InteriorLiveness methods for clarity.
It was too easy to confuse the "inner" vs. "outer" value.

Use less ambigous names: visitAllUses vs visitInnerScopeUses
2025-02-25 23:08:53 -08:00
Erik Eckstein
57a236e671 InitializeStaticGlobals: support statically initializing globals which are or contain inline arrays
For example:

```
struct S {
  static let slab: Slab = [1, 2, 3, 4]
}
```

rdar://143005996
2025-02-12 22:37:49 +01:00
Erik Eckstein
e0b4f71af6 SIL: remove the alloc_vector instruction
It's not needed anymore, because the "FixedArray" experimental feature is replaced by inline-arrays.
2025-02-12 10:51:14 +01:00
Andrew Trick
fa3ebb5c1e LifetimeDependence.Scope add global variable support.
This fixes functions that return @lifetime(immortal).
2025-02-10 09:11:22 -08:00
Andrew Trick
39bae0bb58 LifetimeDependenceDiagnostics: immortal dependence on global 'let' 2025-02-10 09:11:22 -08:00
Andrew Trick
c3de120ca5 LifetimeDependence: simplify and fix multiple bugs.
Functional changes:

Improved modeling of dependence on local variable scopes.

For nested modify->read accesses, only extend the read accesses.

Avoid making a read access dependent on an inout argument.
The following needs to be an error to prevent span storage from being modified:

  @lifetime(owner)
  foo(owner: inout Owner) -> Span {
    owner.span
  }

Improve usability of borrowing trivial values (UnsafePointer). Allow:

  let span = Span(buffer.baseAddress)

Ignore access scopes for trivial values.

Structural changes:

Delete the LifetimeDependenceUseDefWalker.

Encapsulate all logic for variable introducers within the LifetimeDependenceInsertion pass. Once mark_dependence instructions are inserted, no subsequent pass needs to think about the "root" of a dependence.

Fixes: rdar://142451725 (Escape analysis fails with mutations)
2025-02-10 09:11:22 -08:00
Andrew Trick
eae2f06dc7 Extend and improve AccessBase.findSingleInitializer
Return an Initializer rather than a tuple. This makes it easier and more robust
for clients to track dependencies on initialized memory.
2025-02-10 09:11:22 -08:00
Andrew Trick
8b39b6d16a LocalVariableUtils: record mark_dependence bad address operands
Avoid bailing out when something depends on the local variable.
2025-02-10 09:11:22 -08:00
Erik Eckstein
ce73deebc4 RedundantLoadElimination: add a "mandatory" redundant load elimination pass
And make `eliminateRedundantLoads` callable from other optimizations
2025-02-07 11:30:35 +01:00
Erik Eckstein
ad2462f7f2 RedundantLoadElimination: optimize a load from a memory location which was written by copy_addr
For example:
```
  %1 = alloc_stack $B
  copy_addr %0 to [init] %1
  %3 = load [take] %1
  dealloc_stack %1
```
->
```
  %3 = load [copy] %0
```
2025-02-07 11:30:34 +01:00
Andrew Trick
e705a6d7c3 Temporarily introduce AnyInteriorPointer operand ownership.
This is necessary to fix a recent OSSA bug that breaks common occurrences on
mark_dependence [nonescaping]. Rather than reverting that change above, we make
forward progress toward implicit borrows scopes, as was the original intention.

In the near future, all InteriorPointer instructions will create an implicit
borrow scope. This means we have the option of not emitting extraneous
begin/end_borrow instructions around intructions like ref_element_addr,
open_existential, and project_box. After that, we can also migrate
GuaranteedForwarding instructions like tuple_extract and struct_extract.
2025-02-05 16:23:02 -08: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
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
eeckstein
2af03dd177 Merge pull request #78768 from eeckstein/fix-borrowed-from-updater
SIL: when updating borrowed-from instructions, remove the old enclosing values first
2025-01-22 18:40:26 +01:00