Commit Graph

92 Commits

Author SHA1 Message Date
Nate Chandler
40bcc74b47 [OSSACanOwned] Don't dead-end extend if consumed.
When the utility is used by the ConsumeOperatorCopyableValuesChecker,
the checker guarantees that the lifetime can end at the consumes, that
there are no uses after those consumes.  In that circumstance, the
utility maintains liveness to those consumes and as far as possible
without introducing a copy everywhere else.

The lack of complete lifetimes has forced the utility to extend liveness
of values to dead-ends.  That extension, however, is in tension with the
use that the checker is putting the utility to.  If there is a dead-end
after a consume, liveness must not be maintained to that dead-end.

rdar://147586673
2025-04-21 18:09:30 -07:00
Nate Chandler
6ff0c07fe6 [NFC] OSSACanOwned: Extracted predicate. 2025-04-21 18:09:30 -07:00
Nate Chandler
02618f562d [NFC] OSSACanOwned: Renamed field. 2025-04-21 18:09:30 -07:00
Nate Chandler
8e7dae560d [OSSACanOwned] Bail on escaping inner pointers.
If there is a pointer escape, we cannot safely rewrite its lifetime.
2025-02-27 07:20:27 -08:00
Nate Chandler
f1bc3b5205 [OSSACanOwned] Dead-end extend base lifetime.
Regardless of consumes of copies, if the original lexical value is not
consumed on a dead-end path, it must remain live to that dead-end.

rdar://145226757
2025-02-27 07:20:27 -08:00
Nate Chandler
5ffe092fa5 [OSSACanOwned] Extend all lifetimes to dead-ends.
Uses of borrows may occur between the borrow and a dead-end regardless
of lexicality, so always extend lifetimes to dead-ends.
2025-02-27 07:20:25 -08:00
nate-chandler
23a049c38d Merge pull request #79205 from nate-chandler/nfc/20250206/1
[NFC] OSSACanonicalizeOwned: Simplify Def definition.
2025-02-07 08:14:53 -08:00
Nate Chandler
c6e0480e1c [NFC] OSSACanOwned: Simplify Def definition.
It's sufficient just to have a struct with a kind and a value.  There
aren't any cases where the payload's original type benefits from being
statically preserved--they're only ever obtained as `SILValue`s.  Keep
the type safety by way of constructors.
2025-02-06 17:58:20 -08: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
Nate Chandler
ebf602803e [OSSACanOwned] Fix liveness passed to completion.
To determine where a lifetime ends within dead-end blocks,
OSSACanonicalizeOwned uses OSSACompleteLifetime's
visitAvailabilityBoundary.  This API takes a liveness which it uses to
walk forward to the availability boundary.  Specifically, the liveness
passed from OSSACanonicalizeOwned to OSSACompleteLifetime is a variation
of OSSACanonicalizeOwned's own liveness (it has destroys added).

There is a mismatch in the characteristics of livenesses created by
OSSACanonicalizeOwned and OSSACompleteLifetime:  The former deals with
not only direct uses of a value but also uses of its copies; that
introduces the possibility for consuming uses in the middle of liveness.
The latter on the other hand deals only with uses of a single value
(nestedly, but at each level of nesting only a single value).  Passing a
liveness from the former to the latter without handling this mismatch
is incorrect: OSSACompleteLifetime understands consuming uses to always
end a lifetime, even when they are in the middle of a copy-extended
liveness.  The result is that OSSACompleteLifetime produces non-sensical
results when provided with such a liveness.

To address this, fixup the liveness passed from OSSACanonicalizeOwned to
OSSACompleteLifetime by demoting consuming uses that appear within
(that's to say _not_ on the boundary) of liveness to non-consuming uses.

rdar://142846936
2025-01-15 11:57:13 -08:00
Nate Chandler
33135a192f [OSSACanOwned] Don't walk into reborrow copies.
Because discovery of defs walks into reborrows and borrowed-from
instructions, copies may be seen whose underlying value is a guaranteed
value (namely, a reborrow or a borrowed-from instruction). Such copies
may be used beyond the lifetime end of such guaranteed values, so it's
not allowed to sink copies to their consuming uses. Such
canonicalization is the responsibility of the OSSACanonicalizeGuaranteed
utility.

rdar://139842132
2024-12-05 11:25:06 -08:00
Nate Chandler
ebd47790fc [OSSACanonicalizeOwned] Only discover defs once.
The utility performs two def-use traversals.  The first determines
liveness from uses.  The second rewrites copies.

Previously, the defs whose uses were analyzed were discovered twice,
once during each traversal.  The non-triviality of the discovery logic
(i.e. the logic determining when to walk into the values produced by the
instructions which were the users of visited uses) opened the
possibility for a divergence between the two discoveries.  This
possibility had indeed been realized--the two traversals didn't visit
exactly the same uses, and issues ensue.

Here, the defs whose uses are analyzed are discovered only once (and not
discarded as their uses are analyzed) during the first traversal.  The
second traversal reuses the defs discovered in the first traversal,
eliminating the possibility of a def discovery difference.

The second traversal is now done in a different order.  This results in
perturbing the SIL in certain cases.
2024-12-05 11:25:06 -08:00
Nate Chandler
eebe9ac20a [NFC] OSSACanonicalizeOwned: Renamed found defs.
The field is no longer a worklist, just a list of discovered defs.
2024-12-05 08:29:52 -08:00
Nate Chandler
498294efa2 [NFC] OSSACanOwned: Record defs in SmallVector.
In preparation for only recording the defs once, replace the
GraphNodeWorklist of defs with a SetVector.  Preserve the current
visitation order by creating a worklist of indices to be visited.
2024-12-05 08:24:46 -08:00
Nate Chandler
d2f251cd9a [NFC] OSSACanonicalizeOwned: Shadow member.
Add a local variable that shadows the `defUseWorklist` instance member,
enabling further constraints (e.g. `const`ness) to eventually be imposed.
2024-12-05 07:31:20 -08:00
Nate Chandler
aed217437e [NFC] OSSACanOwned: Vary rewrite with def kind.
When rewriting uses, determine how that rewriting should proceed based
on the kind of def whose use is being visited.  Direct uses of reborrows
and borrowed-froms never need to be rewritten because every such use is
a use of a guaranteed value and can never require a copy.
2024-12-05 07:31:19 -08:00
Nate Chandler
77bc114e54 [NFC] OSSACanonicalizeOwned: Record def kinds.
Add a type which distinguishes among the types of defs that are pushed
onto the "def-use worklist".  Note that it's not possible to rely on the
kind of value because the root may itself be a copy_value.  For now, the
distinction is discarded as soon as the def is visited.
2024-12-05 07:31:19 -08:00
Nate Chandler
45f3cf9150 [OwnedLifetimeCan] Persist [dead_end].
When creating `destroy_value`s, create them with the `dead_end` flag if
all subsequent destroys (those from which it is notionally being
hoisted) have the flag.
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
acab991197 [Test] Underscored canonicalize_ossa_lifetime.
Use underscores rather than hyphens so that text editors understand the
name as a single word.
2024-07-25 13:52:21 -07:00
nate-chandler
840198ec9b Merge pull request #73275 from nate-chandler/lifetime-completion/enable
[LifetimeCompletion] Enable.
2024-07-25 12:29:44 -07:00
Nate Chandler
c726366f88 [OwnedLifetimeCan] Persist [dead_end].
When creating `destroy_value`s, create them with the `dead_end` flag if
all subsequent destroys (those from which it is notionally being
hoisted) have the flag.
2024-07-24 17:56:31 -07:00
Nate Chandler
95b8eef292 [NFC] OwnedLifetimeCan: Use isWithinBoundary.
Now that `isWithinBoundary` and `areUsesWithinBoundary` are "the same"
(up to the fact that one takes an instruction and the other an array of
operands), there's no reason to use the latter when looking at a single
instruction.
2024-07-24 11:28:00 -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
Nate Chandler
aa8ccafd20 [OwnedLifetimeCan] Prune fewer debug_values.
Use the more precise areUsesWithinBoundary API (which takes dead-end
blocks into account).  This requires first updating liveness with the
newly created destroys.
2024-07-22 21:51:33 -07:00
Nate Chandler
001c41741a [NFC] OwnedLifetimeCan: Record new destroys.
Add them to a small vector.  For now, do nothing with them.
2024-07-22 21:51:33 -07:00
Nate Chandler
4a397cc018 [NFC] OwnedLifetimeCan: Take DeadEndBlocksAnalysis
All clients of OwnedLifetimeCanonicalization pass an instance of the
analysis in.  For now, it's unused.
2024-07-22 21:51:28 -07:00
Nate Chandler
afca04dd08 [OwnedLifetimeCan] Fix clearing.
Just clear all structures in a single method which is called wherever
clearing is done.  Fixes a failure to clear discoveredBlocks under
certain circumstances.
2024-07-22 20:35:29 -07:00
Nate Chandler
f31254150a [NFC] OwnedLifetimeCan: Extracted dead-end visit.
This is separate from deinit barrier visiting, and will be deleted once
complete lifetimes are finished.
2024-07-22 20:35:29 -07:00
Nate Chandler
800cd3f942 [NFC] OwnedLifetimeCan: Remove spurious array.
Inlined a single-caller method and removed the array that was created
only to be iterated over once.
2024-07-22 20:35:29 -07:00
Nate Chandler
6fd25f695e [OwnedLifetimeCan] Barriers affect direct destroys
Copies of a lexical lifetime are not lexical.  Their destroys can be
hoisted over deinit barriers.  So when extending lifetimes to deinit
barriers, only deal with the direct lifetime, not the copy-extended
lifetime.
2024-07-22 20:35:29 -07:00
Nate Chandler
a60f05ebc1 [NFC] OwnedLifetimeCan: Used for-in loop. 2024-07-22 20:35:29 -07:00
Tim Kientzle
1098054291 Merge branch 'main' into tbkka-assertions2 2024-06-18 17:52:00 -07:00
Nate Chandler
5dc3cf1296 [LifetimeCompletion] Removed "with leaks" mode.
Now that the two known issues which resulted in invalid SIL being
provided to lifetime completion have been addressed, tighten up the
completion done on the availability boundary not to allow leaks.
2024-06-06 16:48:46 -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
Nate Chandler
84da0ed4c5 [LifetimeCompletion] Add extend_lifetimes.
The new instructions are inserted after every "user" (according to
InteriorLiveness' SSAPrunedLiveness instance) outside the linear
liveness boundary.
2024-06-05 16:28:28 -07:00
Nate Chandler
a52cc7ae19 [NFC] LifetimeCompletion: Note boundary kind.
When visiting an availability boundary, note what kind of end is
involved.  For now, there's only one.
2024-06-05 16:28:28 -07:00
Nate Chandler
77d26e1eff [NFC] LifetimeCompletion: Rename helper fn.
It visits the availability boundary, so call it
`visitAvailabilityBoundary`.  It's not clear what "unreachable lifetime
ends" are.
2024-06-05 16:27:45 -07:00
Nate Chandler
9d7db52bed [NFC] PrunedLiveness: Tweaked enum wrapper.
Clarify methods.  Unfortunately, without other changes I haven't
identified, the `enum class` can't be made an `enum` for ideal usage.
2024-06-05 16:27:45 -07:00
Nate Chandler
8a933bfa97 [Gardening] Detypo'd. 2024-06-05 16:27:45 -07:00
Nate Chandler
04ffbe8a6e [NFC] OwnedValueCan: Add support for end markers.
Enhance the utility with the ability to end lifetimes of lexical values
at indicated instructions, overriding the usual behavior of maintaining
such lifetimes' previous endpoints (modulo non-deinit-barrier
instructions).
2024-06-03 15:45:29 -07:00
Nate Chandler
dc9baba586 [NFC] OwnedValueCan: Extracted extension visitor.
Parameterized `extendUnconsumedLiveness` on the ends of interest and the
action to take when visiting the extended boundary and named the
resulting function `visitExtendedUnconsumedBoundary`.
2024-06-03 15:45:26 -07:00
Nate Chandler
aa3cbe0c67 [NFC] OwnedValueCan: Typed maximizeLifetime. 2024-06-03 15:45:23 -07:00
Nate Chandler
df008924da [NFC] OwnedValueCan: Typed pruneDebugMode. 2024-06-03 15:45:20 -07:00
Nate Chandler
632406762c [LifetimeCompletion] Add availability_with_leaks.
The new boundary allows for invalid OSSA where values are not consumed
on paths leading to blocks that exit the function normally.  In such
cases, the value is allowed to continue leaking as before.
2024-05-08 17:15:15 -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
Rick van Voorden
f8ae46b3f3 [inclusive-language] changed sanity to soundness 2024-01-25 18:18:02 -08:00
Nate Chandler
72ff0ae589 [Gardening] Improved owned canonicalization logs. 2023-12-14 13:35:26 -08:00
Joe Groff
25061fb281 Merge pull request #69169 from jckarter/store-borrow-lifetime-nesting
SIL: Treat store_borrow as borrowing its source, and have the move-only checker account for borrow scopes.
2023-10-16 13:51:40 -07:00
Joe Groff
1dcf271fe0 SIL: Treat store_borrow as borrowing its source, and have the move-only checker account for borrow scopes.
When rewriting uses of a noncopyable value, the move-only checker failed to take into account
the scope of borrowing uses when establishing the final lifetimes of values. One way this
manifested was when borrowed values get reabstracted from value to in-memory representations,
using a store_borrow instruction, the lifetime of the original borrow would be ended immediately
after the store_borrow begins rather than after the matching end_borrow. Fix this by, first,
changing `store_borrow` to be treated as a borrowing use of its source rather than an
interior-pointer use; this should be more accurate overall since `store_borrow` borrows the
entire source value for a well-scoped duration balanced by `end_borrow` instructions. That done,
change MoveOnlyBorrowToDestructureUtils so that when it sees a borrow use, it ends the borrow
at the end(s) of the use's borrow scope, instead of immediately after the beginning of the use.
2023-10-16 09:12:25 -07:00