Commit Graph

104 Commits

Author SHA1 Message Date
Nate Chandler
017f003147 [OSSA] Fix borrowCopyOverGuaranteedUsers dead-ends.
The utility was computing the boundary of the `copy_value` with the
`end_borrow`s as users.  But there may not be any `end_borrow`s thanks
to dead-ends.  Instead, consider both guaranteed users and any
`end_borrow`s.

Fixes a miscompile in CSE.

rdar://158353230
2025-08-14 17:05:26 -07:00
Nate Chandler
1fe65b0e3d [NFC] Deleted two unused functions. 2025-08-14 16:15:43 -07:00
Andrew Trick
05fcf5fbbc Fix OSSA RAUW utility for move_value that changes ownership.
CSE "looks through" ownership operations, which can lead to problematic substitutions. This fix cleans up owned operands even when the newly substituted value has no ownership.

For example:

    %0 = enum $Optional<Interface>, #Optional.none!enumelt
    %1 = move_value [lexical] %0
    %2 = enum $Optional<Interface>, #Optional.none!enumelt
    %3 = struct $EndpointCommon (%2)
    %4 = struct $EndpointCommon (%1)

CSE combines the two .none enums:

    %0 = enum $Optional<Interface>, #Optional.none!enumelt
    %2 = enum $Optional<Interface>, #Optional.none!enumelt

Then combines the two structs:

    %3 = struct $EndpointCommon (%2)
    %4 = struct $EndpointCommon (%1)

Leaving a dead move_value:

    %1 = move_value [lexical] %0

which is invalid OSSA. Now, when replacing the owned struct, we add destroys for its operands.

Fixes rdar://156431548 Error! Found a leaked owned value that was never consumed.
2025-07-29 11:18:10 -07:00
Andrew Trick
b3a445fb55 Fix BorrowingOperand::getBorrowIntroducingUserResult()
To handle borrowing operands that produce a dependence value but do not create a
nested borrow scope. This includes non-reborrow borrowed-from and guaranteed
mark_dependence [nonescaping].
2025-02-25 23:08:54 -08:00
Meghana Gupta
4561658799 Avoid creating unoptimizable copies in CSE
CSE uses OSSA rauw which creates copies and copies that are created to optimize
across borrow scopes are unoptimizable. This PR avoids this situation for now.
2025-02-19 11:20:43 -08:00
Meghana Gupta
53553fa172 Fix swift::areUsesWithinValueLifetime for guaranteed values
To find if all the uses are within a guaranteed value, we should find all borrow introducers.

swift::findOwnershipReferenceAggregate looks only through forwarding operations with single operands.

For simplicity, continue using swift::findOwnershipReferenceAggregate, but return false when it does
not find a borrow introducer.
2025-01-31 15:10:57 -08:00
Meghana Gupta
27fc324c8c Fix AddressOwnership for unidentified access
AccessBase can have Unindentified kind where the base value maybe
invalid.

Bailout early for such accesses in ownership rauw.
2025-01-28 09:08:38 -08:00
Meghana Gupta
2c256180ce Add new utility swift::areUsesWithinValueLifetime 2025-01-10 16:15:50 -08:00
Erik Eckstein
48b913af4b Optimizer: make the hasOwnershipOperandsOrResults utility available in OwnershipOptUtils 2025-01-02 10:42:01 +01:00
Erik Eckstein
6990a195a3 Optimizer: rename GuaranteedPhiUpdater -> PhiUpdater
Because it now has the replacePhisWithIncomingValues utility, which works for all kind of phis.
2024-12-12 09:09:11 +01:00
Erik Eckstein
09a5a4487a Optimizer: add a utility to replaces phis with the unique incoming values if all incoming values are the same
This is needed after running the SSAUpdater for an existing OSSA value, because the updater can
insert unnecessary phis in the middle of the original liverange which breaks up the original
liverange into smaller ones:

```
   %1 = def_of_owned_value
   %2 = begin_borrow %1
   ...
   br bb2(%1)
 bb2(%3 : @owned $T): // inserted by SSAUpdater
   ...
   end_borrow %2      // use after end-of-lifetime!
   destroy_value %3
```

It's not needed to run this utility if SSAUpdater is used to create a _new_ OSSA liverange.
2024-12-12 08:57:57 +01: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
Tim Kientzle
f09fb7dfa4 Update a couple of files to pull assertion helpers from the new header 2024-05-16 12:50:23 -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
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
Ben Barham
f292ec9784 Use the new template deduction guides rather than makeArrayRef
LLVM has removed `make*ArrayRef`, migrate all references to their
constructor equivalent.
2024-02-23 20:04:51 -08:00
Meghana Gupta
ce242691a6 Bail out of ossa rauw for move only values 2024-01-05 23:10:45 -08: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
Meghana Gupta
3f6bfca2f9 Merge pull request #64554 from meg-gupta/fixsilcombineubci
Fix OSSA RAUW utility's insertion point
2023-03-24 12:26:06 -04:00
Meghana Gupta
a4c693fcf3 Update OSSA RAUW utils to insert borrows before the value being replaced 2023-03-23 11:45:51 -07:00
Andrew Trick
15796e3ff9 PrunedLiveness: add a SILFunction argument
So that liveness can migrate to using a SILBitfield.
2023-03-22 01:36:48 -07:00
Andrew Trick
f9861ec9c0 Add APIs for terminator results that forward ownership.
Add TermInst::forwardedOperand.

Add SILArgument::forwardedTerminatorResultOperand. This API will be
moved into a proper TerminatorResult abstraction.

Remove getSingleTerminatorOperand, which could be misused because it's
not necessarilly forwarding ownership.

Remove the isTransformationTerminator API, which is not useful or well
defined.

Rewrite several instances of complex logic to handle block arguments
with the simple terminator result API. This defines away potential
bugs where we don't detect casts that perform implicit conversion.

Replace uses of the SILPhiArgument type and code that explicitly
handle block arguments. Control flow is irrelevant in these
situations. SILPhiArgument needs to be deleted ASAP. Instead, use
simple APIs like SILArgument::isTerminatorResult(). Eventually this
will be replaced by a TerminatorResult type.
2022-12-12 12:37:35 -08:00
Allan Shortlidge
4f8d33ffb5 SILOptimizer: Break circular dependency with SIL library by moving extendStoreBorrow(). 2022-10-27 15:29:37 -07:00
Andrew Trick
d386d1ba05 Fix OSSA RAUW perform() to handle replaceAllUsesWith for terminators 2022-10-22 21:57:47 -07:00
Andrew Trick
40e03ef782 Update passes to use SSAPrunedLiveness or MultiDefPrunedLiveness 2022-10-04 13:27:47 -07:00
Andrew Trick
ca503b54b7 Redesign PrunedLiveness APIs, introducing live ranges
First restore the basic PrunedLiveness abstraction to its original
intention. Move code outside of the basic abstraction that polutes the
abstraction and is fundamentally wrong from the perspective of the
liveness abstraction.

Most clients need to reason about live ranges, including the def
points, not just liveness based on use points. Add a PrunedLiveRange
layer of types that understand where the live range is
defined. Knowing where the live range is defined (the kill set) helps
reliably check that arbitrary points are within the boundary. This
way, the client doesn't need to be manage this on its own. We can also
support holes in the live range for non-SSA liveness. This makes it
safe and correct for the way liveness is now being used. This layer
safety handles:

- multiple defs
- instructions that are both uses and defs
- dead values
- unreachable code
- self-loops

So it's no longer the client's responsibility to check these things!

Add SSAPrunedLiveness and MultiDefPrunedLiveness to safely handle each
situation.

Split code that I can't figure out into
DiagnosticPrunedLiveness. Hopefully it will be deleted soon.
2022-10-04 13:27:44 -07:00
Josh Soref
730b16c569 Spelling siloptimizer
* access
* accessed
* accesses
* accessor
* acquiring
* across
* activated
* additive
* address
* addresses'
* aggregated
* analysis
* and
* appropriately
* archetype
* argument
* associated
* availability
* barriers
* because
* been
* beginning
* belongs
* beneficial
* blocks
* borrow
* builtin
* cannot
* canonical
* canonicalize
* clazz
* cleanup
* coalesceable
* coalesced
* comparisons
* completely
* component
* computed
* concrete
* conjunction
* conservatively
* constituent
* construct
* consuming
* containing
* covered
* creates
* critical
* dataflow
* declaration
* defined
* defining
* definition
* deinitialization
* deliberately
* dependencies
* dependent
* deserialized
* destroy
* deterministic
* deterministically
* devirtualizes
* diagnostic
* diagnostics
* differentiation
* disable
* discipline
* dominate
* dominates
* don't
* element
* eliminate
* eliminating
* elimination
* embedded
* encounter
* epilogue
* epsilon
* escape
* escaping
* essential
* evaluating
* evaluation
* evaluator
* executing
* existential
* existentials
* explicit
* expression
* extended
* extension
* extract
* for
* from
* function
* generic
* guarantee
* guaranteed
* happened
* heuristic
* however
* identifiable
* immediately
* implementation
* improper
* include
* infinite
* initialize
* initialized
* initializer
* inside
* instruction
* interference
* interferes
* interleaved
* internal
* intersection
* intractable
* intrinsic
* invalidates
* irreducible
* irrelevant
* language
* lifetime
* literal
* looks
* materialize
* meaning
* mergeable
* might
* mimics
* modification
* modifies
* multiple
* mutating
* necessarily
* necessary
* needsmultiplecopies
* nonetheless
* nothing
* occurred
* occurs
* optimization
* optimizing
* original
* outside
* overflow
* overlapping
* overridden
* owned
* ownership
* parallel
* parameter
* paths
* patterns
* pipeline
* plottable
* possible
* potentially
* practically
* preamble
* precede
* preceding
* predecessor
* preferable
* preparation
* probably
* projection
* properties
* property
* protocol
* reabstraction
* reachable
* recognized
* recursive
* recursively
* redundant
* reentrancy
* referenced
* registry
* reinitialization
* reload
* represent
* requires
* response
* responsible
* retrieving
* returned
* returning
* returns
* rewriting
* rewritten
* sample
* scenarios
* scope
* should
* sideeffects
* similar
* simplify
* simplifycfg
* somewhat
* spaghetti
* specialization
* specializations
* specialized
* specially
* statistically
* substitute
* substitution
* succeeds
* successful
* successfully
* successor
* superfluous
* surprisingly
* suspension
* swift
* targeted
* that
* that our
* the
* therefore
* this
* those
* threshold
* through
* transform
* transformation
* truncated
* ultimate
* unchecked
* uninitialized
* unlikely
* unmanaged
* unoptimized key
* updataflow
* usefulness
* utilities
* villain
* whenever
* writes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-10-03 18:31:33 -04: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
Andrew Trick
9dba1c1fb5 Temporary fix for OSSA RAUW utilities.
This fix unblocks unrelated optimizer commits. A unit test will be
introduced with those commits.

The RAUW utility does not correctly handle reborrows. It is in the
middle of being rewritten. For now, simply bail out since this isn't
an important case to optimize.
2022-02-17 23:55:32 -08:00
Andrew Trick
1c8f142a73 OwnershipOptUtils - computeGuaranteedBoundary 2022-02-16 12:23:01 -08:00
Nate Chandler
f8bcfe2328 [RAUW] Allow RAUWing some lexical values.
RAUWing a lexical value with a non-lexical value is illegal because it
would result in the value's lifetime being shortened without regard to
deinit barriers.  RAUWing _with_ a lexical value is LEGAL so long as
doing so doesn't extend its lifetime.
2022-02-10 16:28:41 -08:00
Nate Chandler
689c6ac37c [OwnershipOptUtils] Don't RAUW lexical values.
Replacing all uses of a lexical value with another value, even another
lexical value, may change the lifetime of the value in ways that aren't
permitted for a lexical lifetime.
2022-01-27 15:20:02 -08:00
Andrew Trick
febde3da2f SemanticARCOpts fix - remove deadEndBlocks checks
SemanticARCOptVisitor::performGuaranteedCopyValueOptimization was
converting this SIL

    %borrow = begin_borrow %copiedValue
    %copy = copy_value %borrow
    %borrowCopy = begin_borrow %copy
    end_borrow %borrow
    end_borrow %borrowCopy
    destroy_value %copy
    // something something
    unreachable

into

    %borrow = begin_borrow %copiedValue
    %innerBorrow = begin_borrow %borrow
    end_borrow %borrow
    end_borrow %innerBorrow
    // something something
    unreachable

Dead-end blocks are simply irrelevant for this
optimization. Unfortunately, there were multiple layers of attempted
workarounds that were hiding the real problem, except in rare cases.

Thanks Nate Chandler for reducing the test.
2021-12-09 20:23:17 -08:00
Saleem Abdulrasool
910fbee14e gardening: make c++98-compat-extra-semi an error
This cleans up 90 instances of this warning and reduces the build spew
when building on Linux.  This helps identify actual issues when
building which can get lost in the stream of warning messages.  It also
helps restore the ability to build the compiler with gcc.
2021-11-27 11:40:17 -08:00
Andrew Trick
f9d31ca116 InstructionDeleter ctor moves callbacks to fix iterator invalidation
The InstructionDeleter needs to move the callbacks during construction
to prevent the client code from using the old callbacks.

Fixes iterator invalidation bugs.
2021-11-18 11:38:08 -08:00
Andrew Trick
c86d112891 Update #include for InstructionDeleter.h 2021-11-18 11:38:08 -08:00
swift-ci
d034448e2d Merge pull request #40004 from meg-gupta/fixossautiledgecase 2021-11-17 19:41:28 -08:00
Meghana Gupta
4924b65bee In GuaranteedOwnershipExtension::Status::ExtendLifetime mode, also extend the borrow scope if needed 2021-11-01 15:04:02 -07:00
Meghana Gupta
e9df26803b Add new api makeGuaranteedValueAvailable 2021-11-01 14:03:22 -07:00
Meghana Gupta
04293732cf Add new apis to OwnershipLifetimeExtender 2021-11-01 14:03:16 -07:00
Kuba Mracek
8158cdf5e5 Revert "Merge pull request #39805 from atrick/oou-opt-rauw"
This reverts commit df26a6d740, reversing
changes made to f9643fd3a2.
2021-10-22 12:29:10 -07:00
Andrew Trick
463922c386 Allow RAUW to optimize struct_extract from function args 2021-10-18 14:16:40 -07:00
Andrew Trick
698ed8e043 Make Ownership RAUW checks more precise - allows more optimization.
Call findOwnershipReferenceRoot when checking for guaranteed values
from SILFunctionArgument.

TODO: We need to add a component path to a reference root abstraction
to handle references that come from a struct_extract or tuple_extract.
2021-10-18 14:16:39 -07:00
Andrew Trick
36fb073c21 OSSA RAUW prepareUnowned - short-circuit empty uses
Avoid generating useless empty copies and borrow scopes.

Bypass all the use-checking logic when there are no uses to avoid
special cases and bugs.
2021-10-18 09:01:15 -07:00
Andrew Trick
652ff78412 OSSA RAUW helper redesign - split prepareReplacement() vs. perform()
Required to fix SILCombine.

Divide the logic into smaller pieces. This allows passes to check for
replaceability before generating the replacement value.

Preparation for simplifying OSSA utilities into smaller logical
components making them flexibile and allowing improvements to be
staged in.
2021-10-18 09:01:15 -07:00
Andrew Trick
4a85e187ca Eliminate unused and incomplete OSSA logic. 2021-10-18 09:01:15 -07:00
Andrew Trick
8062e408ea Migrate to OwnershipLifetimeExtender API: borrowCopyOverScope etc.
Preparation for rewriting non-trivial terminators and generalizing
support for guaranteed phis.

Add guaranteedUsePoints to the RAUW context. This will replace ALL
existing context book-keeping once the old code is deleted.

Introduce a borrowCopyOverScope entry point to handle extending
lifetime over a BorrowedValue. This simply uses the
BorrowedLifetimeExtender.

Introduce higher-level APIs:
- borrowOverValue to extened over a guaranteedValue
- borrowOverSingleUse to extened over a single guaranteed use

These replace both createPlusZeroBorrow and createPlusOneBorrow.

Update RAUW-ctor, RAUW::handleUnowned, and replaceAddressUses to use
the new API.

Restructure RAUW::canFixUpOwnershipForRAUW. Simply use
findInnerTransitiveGuaranteedUses.

Replace RAUW::handleGuaranteed and rewriteReborrows with
OLE::borrowOverValue.

Use the BorrowedLifetimeExtender utility to handle all situations
correctly.

TODO: createPlusOneBorrow can be completely removed, and a massive
amount of confusing/incomplete code can be deleted in a follow-up
commit.
2021-10-18 09:01:15 -07:00
Andrew Trick
850426514a Merge pull request #39761 from atrick/fix-accessopt
Fix AccessEnforcementOpts for OSSA
2021-10-15 00:14:23 -07:00
Andrew Trick
4b592c09d8 Add OSSA utilities for extending lifetimes and borrow scopes
Without introducing any new borrow scopes or owned lifetimes.

Top-level APIs:
- extendOwnedLifetime()
- extendLocalBorrow()

New utilitiy: GuaranteedOwnershipExtension.

This is a simple utility to determine whether new uses can be added to
an existing guaranteed value. It reports the kind of transformation
needed and performs the transformation if requested. If transformation
is needed, it simply calls one of the two top-level APIs.
2021-10-14 13:53:37 -07:00