Commit Graph

103 Commits

Author SHA1 Message Date
Meghana Gupta
c528afccf2 Fix ClosureLifetimeFixup to insert destroys at leaking blocks 2025-03-14 15:48:44 -07:00
Andrew Trick
7760dbc983 Fix ClosureLifetimeFixup handling of incomplete liveness.
Correctly handle pointer escapes and dependent uses to avoid miscompiles.
2025-03-02 23:51:34 -08: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
Nate Chandler
f9b32a5c4d [NFC] CLF: Compute reachable blocks only.
Don't form a set of unreachable blocks, we only need to check whether
any given block is unreachable, which can be done via
`ReachableBlocks::isVisited`.
2024-12-18 11:25:42 -08:00
Nate Chandler
c53b1a5711 [Gardening] Detypo'd comment. 2024-12-18 11:25:41 -08:00
Erik Eckstein
51e3e5ed80 Optimizer: rename BorrowArgumentsUpdater -> GuaranteedPhiUpdater
NFC
2024-11-12 09:26:59 +01:00
Erik Eckstein
6b8c6a3c3b SIL: rename updateBorrowedFrom to updateBorrowArguments
NFC
2024-11-12 09:26:58 +01:00
Nate Chandler
344ef3df37 [ClosureLifetimeFixup] Flag dead-end destroys. 2024-07-29 07:26:08 -07:00
Nate Chandler
a7c6538d4e Revert "Merge pull request #73275 from nate-chandler/lifetime-completion/enable"
This reverts commit 840198ec9b, reversing
changes made to b74303c214.
2024-07-26 07:12:45 -07:00
Nate Chandler
92e5dc84cd [ClosureLifetimeFixup] Flag dead-end destroys. 2024-07-24 17:56:31 -07:00
Nate Chandler
812891cf81 [NFC] PrunedLiveness: Clarified boundary API.
When checking whether an instruction is contained in a liveness
boundary, a pointer to a DeadEndBlocks instance must always be passed.
When the pointer is null, it is only checked that the instruction occurs
within the direct live region.  When the pointer is non-null, it is
checked whether the instruction occurs within the region obtained by
extending the live region up to the availability boundary within
dead-end regions that are adjacent to the non-lifetime-ending portion of
the liveness boundary.
2024-07-23 13:38:35 -07:00
Meghana Gupta
a470b04bbf [NFC] clang-format some parts of ClousreLifetimeFixup 2024-07-02 16:26:51 -07:00
Meghana Gupta
c895a9ba10 Add a flag to disable copy elimination of captures in ClosureLifetimeFixup 2024-07-02 16:25:38 -07:00
Meghana Gupta
98074a86c4 Enable copy elimination of captures for all types in ClosureLifetimeFixup
rdar://130026658
2024-07-02 16:25:34 -07:00
Meghana Gupta
d6729280f3 [NFC] clang-format parts of tryRewriteToPartialApplyStack 2024-07-01 09:53:14 -07:00
Meghana Gupta
56d59c9db3 [NFC] Rename OrigUnusedDuringClosureLifetimeWalker -> OrigUnmodifiedDuringClosureLifetimeWalker 2024-07-01 09:53:14 -07:00
Meghana Gupta
e71cd4b005 Improve copy elimination of noncopyable captures in ClosureLifetimeFixup
For a mark_dependence user of the stack, look through the mark_dependence chain
to match the partial_apply.

Since this is a superset of the `markDepChain` logic, remove that.
So that we don't have 2 ways to check for the same.
2024-06-27 10:34:29 -07:00
Meghana Gupta
960619b0a0 Fix ClosureLifetimeFixup's copy elimination for noncopyable values
On finding unrecognized user, reset `initialization` of the stack so that we
don't inadvertently eliminate copy
2024-06-27 02:55:29 -07:00
Mishal Shah
790d4da2e4 Merge pull request #74593 from Azoy/why-are-we-copying
[SILOptimizer] Handle the mark_dependence chain when eliminating copies in ClosureLifetimeFixup
2024-06-21 15:44:57 -07:00
Alejandro Alonso
8ed84e8aed Handle the mark_dependence chain when eliminating copies in ClosureLifetimeFixup 2024-06-20 14:44:11 -07:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Erik Eckstein
e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
2024-04-10 13:38:10 +02:00
Andrew Trick
2e82db8e1b ClosureLifetimeFixup; emit mark_dependence [nonescaping].
It is safe to do so because the on_stack transformation already checks that the closure has a single known apply use.
2024-03-18 17:45:33 -07:00
Michael Gottesman
11f0ff6e32 [sil] Ensure that all SILValues have a parent function by making it so that SILUndef is uniqued at the function instead of module level.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.

rdar://123484595
2024-02-27 13:14:47 -08:00
John McCall
d5142668f4 SIL and IRGen support for @isolated(any). SILGen to come. 2024-02-13 03:04:13 -05:00
Andrew Trick
da3f583492 Add mark_dependence [unresolved]
In preparation for inserting mark_dependence instructions for lifetime
dependencies early, immediately after SILGen. That will simplify the
implementation of borrowed arguments.

Marking them unresolved is needed to make OSSA verification
conservative until lifetime dependence diagnostics runs.
2024-02-08 22:53:16 -08:00
Andrew Trick
264cbaea42 Add mark_dependence [nonescaping] flag.
The dependent 'value' may be marked 'nonescaping', which guarantees that the
lifetime dependence is statically enforceable. In this case, the compiler
must be able to follow all values forwarded from the dependent 'value', and
recognize all final (non-forwarded, non-escaping) use points. This implies
that `findPointerEscape` is false. A diagnostic pass checks that the
incoming SIL to verify that these use points are all initially within the
'base' lifetime. Regular 'mark_dependence' semantics ensure that
optimizations cannot violate the lifetime dependence after diagnostics.
2024-01-04 14:47:35 -08:00
Andrew Trick
9ee5d6b342 Merge pull request #70176 from atrick/fix-rewrite-pa-undef
Fix tryRewriteToPartialApplyStack to handle undef
2023-12-08 12:02:41 -08:00
Andrew Trick
224c37959e Fix tryRewriteToPartialApplyStack to handle undef
Fixes rdar://117366370 callback_fn<tryRewriteToPartialApplyStack
2023-12-01 17:16:19 -08:00
Erik Eckstein
0897d8a720 MemoryLifetimeVerifier: use CalleeCache instead of AliasAnalysis
To verify if a function may read from an indirect argument, don't use AliasAnalysis.
Instead use the CalleeCache to get the list of callees of an apply instruction.
Then use a simple call-back into the swift Function to check if a callee has any relevant memory effect set.

This avoids a dependency from SIL to the Optimizer.
It fixes a linker error when building some unit tests in debug.
2023-12-01 19:20:18 +01:00
Evan Wilde
37ede16142 Merge remote-tracking branch 'main' into rebranch
Conflicts:
  lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
2023-10-16 09:31:37 -07:00
Joe Groff
cb6f2b02f5 ClosureLifetimeFixup: Fix parameter indexing issue.
When deciding whether to clean up copies of noncopyable captures, I got
the parameter indexing wrong when the closure has non-capture arguments.
Fixing this allows noncopyable captures to work in more general
circumstances.
2023-10-14 10:00:21 -07:00
swift-ci
4fe55c5732 Merge remote-tracking branch 'origin/main' into rebranch 2023-08-11 00:35:20 -07:00
swift-ci
2667df0799 Merge pull request #67760 from atrick/fix-closure-moveonly-arg
Fix compiler crashes with consuming and borrowing keywords.
2023-08-11 00:32:41 -07:00
swift-ci
525350af1b Merge remote-tracking branch 'origin/main' into rebranch 2023-08-10 22:14:25 -07:00
Andrew Trick
f46d79149d ClosureLifetimeFixup review feedback 2023-08-10 18:51:48 -07:00
Michael Gottesman
29350907fc Convert TransitiveAddressWalker to use CRTP instead of virtual functions. 2023-08-10 12:58:50 -07:00
Andrew Trick
9c24933bd4 Fix compiler crashes with consuming and borrowing keywords.
Without this fix, the new 'consuming' and 'borrowing' keywords cannot
be used with trivial types. Which means, for example, they can't be
used in macro expansions that work on various types.

Fixes patterns like:

public func test1(i: consuming Int) -> Int {
  takeClosure { [i = copy i] in i }
}

public func test2(i: borrowing Int) -> Int {
  takeClosure { [i = copy i] in i }
}

public func test3(i: consuming Int) -> Int {
  takeClosure { i }
}

// Sadly, test4 is still incorrectly diagnosed.
public func test4(i: borrowing Int) -> Int {
  takeClosure { i }
}

Fixes rdar://112795074 (Crash compiling function that has a macro annotation and uses `consuming`)
2023-08-10 11:17:45 -07:00
Evan Wilde
309aed4925 Add SmallSetVector replacement
llvm::SmallSetVector changed semantics
(https://reviews.llvm.org/D152497) resulting in build failures in Swift.
The old semantics allowed usage of types that did not have an
`operator==` because `SmallDenseSet` uses `DenseSetInfo<T>::isEqual` to
determine equality. The new implementation switched to using
`std::find`, which internally uses `operator==`. This type is used
pretty frequently with `swift::Type`, which intentionally deletes
`operator==` as it is not the canonical type and therefore cannot be
compared in normal circumstances.

This patch adds a new type-alias to the Swift namespace that provides
the old semantic behavior for `SmallSetVector`. I've also gone through
and replaced usages of `llvm::SmallSetVector` with the
`Swift::SmallSetVector` in places where we're storing a type that
doesn't implement or explicitly deletes `operator==`. The changes to
`llvm::SmallSetVector` should improve compile-time performance, so I
left the `llvm::SmallSetVector` where possible.
2023-07-25 12:28:27 -07:00
Erik Eckstein
6b1697eb06 use new llvm::Optional APIs to fix deprecation warnings 2023-06-28 14:28:38 +02:00
Joe Groff
ed2cbca04f ClosureLifetimeFixup: Remove copy of borrowed move-only nonescaping captures when possible.
SILGen introduces a copy of the capture, because the semantics of escaping partial_apply's
requires the closure to take ownership of the parameters. We don't know when a closure is
strictly nonescaping or its final lifetime until ClosureLifetimeFixup runs, but that replaces
the consume of the copy with a borrow of the copy normally, hoping later passes fix it up.
We can't wait that long for move-only types, which can't be copied, so try to remove the
copy up front when the copy lives long enough and has no interfering uses other than the
partial_apply. rdar://110137169
2023-06-20 12:10:31 -07:00
Michael Gottesman
59c8cff917 [borrowing] Add support for borrowing/consuming copyable types to be a noimplicitcopy type.
rdar://108383660
2023-06-06 18:12:29 -04:00
Erik Eckstein
4b33b99ee2 MemoryLifetimeVerifier: be more precise with indirect function arguments.
Optimizations can rely on alias analysis to know that an in-argument (or parts of it) is not actually read.
We have to do the same in the verifier: if alias analysis says that an in-argument is not read, there is no need that the memory location is initialized.

Fixes a false verifier error.
rdar://106806899
2023-05-03 14:33:45 +02:00
Joe Groff
69e4b95fb8 SIL: Model noescape partial_applys with ownership in OSSA.
Although nonescaping closures are representationally trivial pointers to their
on-stack context, it is useful to model them as borrowing their captures, which
allows for checking correct use of move-only values across the closure, and
lets us model the lifetime dependence between a closure and its captures without
an ad-hoc web of `mark_dependence` instructions.

During ownership elimination, We eliminate copy/destroy_value instructions and
end the partial_apply's lifetime with an explicit dealloc_stack as before,
for compatibility with existing IRGen and non-OSSA aware passes.
2023-02-16 21:43:53 -08:00
Arnold Schwaighofer
508708919a ClosureLifetimeFixup: Fix corner case of unconnected basic blocks
Dominator based algorithms don't like to run over dead basic blocks.

rdar://103531926
2022-12-21 05:54:36 -08:00
Nate Chandler
9ad44a5056 [ClosureLifetimeFixup] Dealloc args on frontier.
Previously, the dealloc_stacks created for the alloc_stacks used to pass
@in_guaranteed arguments to on_stack closures were created after the
users of the closure.  When SILGen created these alloc_stacks in the
same block as the users, this happened to work.  Now that
AddressLowering creates such alloc_stacks elsewhere, this approach
results in invalid SIL.

Here, the dealloc_stacks are instead at the end of each block in the
dominance frontier of the alloc_stack.
2022-12-13 11:46:47 -08:00
Erik Eckstein
c180d1363e SIL: simplify deleting instruction while iterating over instructions.
Add `deletableInstructions()` and `reverseDeletableInstructions()` in SILBasicBlock.
It allows deleting instructions while iterating over all instructions of the block.
This is a replacement for `InstructionDeleter::updatingRange()`.
It's a simpler implementation than the existing `UpdatingListIterator` and `UpdatingInstructionIteratorRegistry`, because it just needs to keep the prev/next pointers for "deleted" instructions instead of the iterator-registration machinery.
It's also safer, because it doesn't require to delete instructions via a specific instance of an InstructionDeleter (which can be missed easily).
2022-12-12 19:08:54 +01:00
Nate Chandler
bfd865b6b6 [ApplySite] Renamed insertAfterApplication.
Now that it can be called on partial_apply instructions,
insertAfterFullEvaluation does not name what the function does.  One
could imagine a function which inserted after the applies of
(non-escaping) partial_applies.
2022-11-03 13:52:42 -07:00
Meghana Gupta
dccb5ac56d ClosureLifetimeFixup : Ensure borrow scope is inserted on both none/some
path for an optional type.
2022-10-19 19:54:27 -07:00
Michael Gottesman
1e6187c4f4 [sil] Update all usages of old API SILValue::getOwnershipKind() in favor of new ValueBase::getOwnershipKind().
Andy some time ago already created the new API but didn't go through and update
the old occurences. I did that in this PR and then deprecated the old API. The
tree is clean, so I could just remove it, but I decided to be nicer to
downstream people by deprecating it first.
2022-07-26 11:46:23 -07:00