Commit Graph

48 Commits

Author SHA1 Message Date
Andrew Trick
9d40198c0f SIL: fix miscompiles of non-Copyable struct/enum with deinits
The SIL optimizer has fundamental bugs that result in dropping non-Copyable
struct & enum the deinitializers.

Fix this by

1. correctly representing the ownership of struct & enum values that are
   initialized from trivial values.

2. checking move-only types before deleting forwarding instructions.

These bugs block other bug fixes. They are exposed by other unrelated SIL
optimizations to SIL. I'm sure its possible to expose the bugs with source-level
tests, but the current order of inlining and deinit devirtualization has been
hiding the bugs and complicates reproduction.
2025-08-15 15:03:50 -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
b3dd3f9ea3 [SILCombine] Keep ued(deiniting).
It's not allowed to replace ued(enum(x)) with x if the enum in question
has a deinit.
2024-04-19 14:27:12 -07:00
Nate Chandler
49eb3caad9 [SILCombine] Keep dead drop_deinits. 2024-04-19 12:37:34 -07:00
Andrew Trick
581010d00c SIL: Make drop_deinit a ForwardingInstruction.
drop_deinit forwards ownership while effectively stripping the deinitializer. It is similar to a type cast.

Fixes rdar://125590074 ([NonescapableTypes] Nonescapable types
cannot have deinits)
2024-04-03 18:53:18 -07:00
Nate Chandler
2cbc13aca6 [CanonInst] Process "at" load after rewriting.
When a load/load_borrow is canonicalized, canonicalization should
continue from where the load was before rather than the first
instruction that was after it.  Enables narrowing the load through
a sequence of projections.
2024-03-13 17:42:33 -07:00
Nate Chandler
9c3d941a4a [Gardening] Deleted stale comment. 2024-03-13 17:42:33 -07:00
Joe Groff
161183cbc4 Merge pull request #71803 from jckarter/begin-borrow-fixed-switch-subject
SIL: Enclose switch subjects in a new begin_borrow [fixed] variant.
2024-02-22 14:45:17 -08:00
Joe Groff
d75a62ce64 SIL: Enclose switch subjects in a new begin_borrow [fixed] variant.
We want to preserve the borrow scope during switch dispatch so that move-only
checking doesn't try to analyze destructures or consumes out of it. SILGen
should mark anywhere that's a potential possibility with its own marker so that
it gets borrow checked independently.
2024-02-21 20:41:20 -08:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Nate Chandler
9861422eeb [SIL] Key consume checking off var_decl attr.
Previously, the lexical attribute on begin_borrow instructions was used.
This doesn't work for values without lexical lifetimes which are
consumed, e.g. stdlib CoW types.  Here, the new var_decl attribute on
begin_borrow is keyed off of instead.  This flag encodes exactly that a
value corresponds to a source-level VarDecl, which is the condition
under which checking needs to run.

rdar://118059326
2023-11-28 07:26:09 -08:00
Meghana Gupta
8a7d45f729 Bail out of canonicalization of single struct field stores for non copyable types 2023-07-05 13:39:22 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
Meghana Gupta
7cb3733e29 Rename OwnershipForwardingMixin -> ForwardingInstruction 2023-06-14 10:40:32 -07:00
Andrew Trick
664ec221ae Remove disabled code in splitAggregateLoad.
It is no longer necessary to use debug fragments for load splitting.
2023-05-16 10:18:48 -07:00
Andrew Trick
5d3793d843 Call salvageLoadDebugInfo from splitAggregateLoad
Fixes a know issue in which load splitting drops debug info.

After splitting the load, create a new debug_value instruction for the
loaded memory location, inserting a dereference expression if needed.

This fixes debug information for -Onone debugging. Later, after fixing
optimizations, it will also be called at -O, but not on 5.9.

Fixes rdar://104700920 (At -Onone preserve debug info after splitting loads)
Issue: LLDB missing variables in certain case #62241
2023-05-16 10:18:48 -07:00
Andrew Trick
11053dc4f1 Add salvageLoadDebugInfo to handle LoadInst
Before deleting a load, simply rewrite its debug info to refer to the
loaded address:

%l = load %a
debug_value %l, loc0, scope0, var0

--->

debug_value %a, loc0, scope0, var0, expr op_deref
%l = load %a

Note that alloc_stack addresses do not require the addition of
op_deref because they are already special-cased in IRGen.

This will be called from salvageDebugInfo when it is supported by
optmizations. Until then, it is only called selectively at -Onone.
2023-05-16 09:54:25 -07:00
Andrew Trick
094b204270 Update a comment in splitAggregateLoad 2023-05-15 15:20:57 -07:00
Andrew Trick
21f69d4741 Revert "At -Onone preserve debug info after splitting loads"
This reverts commit 02f7450759.

Fixes rdar://104667596 (incorrectly reports an error when resolving
initialization out of a switch)
2023-01-26 10:04:05 -08:00
Andrew Trick
02f7450759 At -Onone preserve debug info after splitting loads
Load splitting converts an aggregate load into a set of subobject
loads. This is required at -Onone for exclusivity diagnostics.

We cannot preserve the original debug information by redirecting debug
info to the memory address, because that might result in incorrect
debug values if the memory is reused.

Before this fix, we "conservatively" drop debug info in those
cases. This fix preserves full debug info by keeping the original
aggregate load intact alongside the new subobject loads. To avoid
exclusivity violations, it create a new unsafe access scope for the
old load.

Fixes LLDB missing variables in certain case #62241
2022-12-19 00:02:18 -08:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01: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
875d1114b0 CanonicalizeInstruction - FIXME and option to preserve debug info
Debug information needs to be preserved at -Onone.

And it should be preserved to a reasonable extend at -O, not
completely thrown away.

This transformation does neither.

The -Onone case is more important. The FIXME explains how that could
be done.

I'm including an example of how to handle the -O case, currently under
a a flag, -sil-load-splitting-debug-info.

This -O support uses debug fragments, which currently crashes when
building SwiftPM's PackageModel module in LLVM's 'X86 Assembly
Printer', llvm::DwarfExpression::addFragmentOffset.

We don't appear to have any verification of debug fragment in either
SIL or LLVM that would catch this. And I haven't been able to reduce
the problem to a small test case.
2021-12-15 11:02:17 -08:00
Andrew Trick
8c6c88a390 Add CanonicalizeInstruction preserveDebugInfo, fix Onone debug info
Minor debug info fixes to avoid dropping debug info at -Onon.
2021-12-15 11:02:09 -08:00
Nate Chandler
ea42e2f334 Enabling copy propagation enables lexical lifetimes.
The effect of passing -enable-copy-propagation is both to enable the
CopyPropagation pass to shorten object lifetimes and also to enable
lexical lifetimes to ensure that object lifetimes aren't shortened while
a variable is still in scope and used.

Add a new flag, -enable-lexical-borrow-scopes=true to override
-enable-copy-propagation's effect (setting it to ::ExperimentalLate) on
SILOptions::LexicalLifetimes that sets it to ::Early even in the face of
-enable-copy-propagation.  The old flag -disable-lexical-lifetimes is
renamed to -enable-lexical-borrow-scopes=false but continues to set that
option to ::Off even when -enable-copy-propagation is passed.
2021-12-08 19:13:21 -08:00
Nate Chandler
ac50bb7a7c [CanonicalizeInst] Remove redundant lexical bbis.
Previously, CanonicalizeInstruction::eliminateSimpleBorrows bailed out
when encountering any any [lexical] begin_borrow.  While generally such
borrow scopes must be preserved, they may be removed if they are
redundant (when the borrowed value is guaranteed by another means: an
outer lexical borrow scope or a guaranteed function argument).  Here,
removing such redundant lexical borrow scopes is enabled.
2021-12-07 18:41:16 -08:00
Erik Eckstein
44001402dc SILOptimizer: remove some unused variables
to fix "unused variable" warnings

rdar://84035249
2021-11-16 17:25:16 +01:00
Michael Gottesman
960cbcb147 [SILGenCleanup] Do not remove trivial lexical borrow scopes.
This ensures that while in OSSA, we have in the IR information about the lexical
lifetime of let variables.
2021-10-22 14:36:33 -07:00
Andrew Trick
305054235b Add a scary warning comment to eliminateSimpleCopies
We're getting lucky that this utility isn't breaking people's code.
2021-07-01 20:49:29 -07:00
Michael Gottesman
5019e1578f [ownership] Refactor out the composition type LoadOperation from CanonicalizeInstruction into OwnershipOptUtils.
This API is useful when writing compiler code that needs to handle ossa/non-ossa
as well as load_borrow/load while in OSSA. I am going to use this in
SILMem2Reg.
2021-04-14 11:43:20 -07:00
Meghana Gupta
ddf8b459ba Fix use-after-free of deleted debug instructions in Canonicalize 2021-01-26 19:56:30 -08:00
Michael Gottesman
aa38be6d98 [inst-simplify] Hide simplifyInstruction in favor of using simplifyAndReplaceAllSimplifiedUsesAndErase.
Currently all of these places in the code base perform simplifyInstruction and
then a replaceAllSimplifiedUsesAndErase(...). This is a bad pattern since:

1. simplifyInstruction assumes its result will be passed to
   replaceAllSimplifiedUsesAndErase. So by leaving these as separate things, we
   allow for users to pointlessly make this mistake.

2. I am going to implement in a subsequent commit a utility that lifetime
   extends interior pointer bases when replacing an address with an interior
   pointer derived address. To do this efficiently, I want to reuse state I
   compute during simplifyInstruction during the actual RAUW meaning that if the
   two operations are split, that is difficult without extending the API. So by
   removing this, I can make the transform and eliminate mistakes at the same
   time.
2021-01-17 20:08:24 -08:00
Michael Gottesman
ee17f5e8f6 [ownership] Rename OwnershipForwardingInst -> OwnershipForwardingMixin and eliminate support for isa<> and dyn_cast<>.
Instead, I just added some static helper methods that perform the same
operations without needing to deal with generics/etc on OwnershipForwardingMixin
itself. The reason why I did this is that this Mixin is not part of the SILNode
heirarchy so we shouldn't use utilities tied to the SILNode hierarchy.
2021-01-13 10:43:41 -08:00
Michael Gottesman
0de00d1ce4 [sil-inst-opt] Improve performance of InstModCallbacks by eliminating indirect call along default callback path.
Specifically before this PR, if a caller did not customize a specific callback
of InstModCallbacks, we would store a static default std::function into
InstModCallbacks. This means that we always would have an indirect jump. That is
unfortunate since this code is often called in loops.

In this PR, I eliminate this problem by:

1. I made all of the actual callback std::function in InstModCallback private
   and gave them a "Func" postfix (e.x.: deleteInst -> deleteInstFunc).

2. I created public methods with the old callback names to actually call the
   callbacks. This ensured that as long as we are not escaping callbacks from
   InstModCallback, this PR would not result in the need for any source changes
   since we are changing a call of a std::function field to a call to a method.

3. I changed all of the places that were escaping inst mod's callbacks to take
   an InstModCallback. We shouldn't be doing that anyway.

4. I changed the default value of each callback in InstModCallbacks to be a
   nullptr and changed the public helper methods to check if a callback is
   null. If the callback is not null, it is called, otherwise the getter falls
   back to an inline default implementation of the operation.

All together this means that the cost of a plain InstModCallback is reduced and
one pays an indirect function cost price as one customizes it further which is
better scalability.

P.S. as a little extra thing, I added a madeChange field onto the
InstModCallback. Now that we have the helpers calling the callbacks, I can
easily insert instrumentation like this, allowing for users to pass in
InstModCallback and see if anything was RAUWed without needing to specify a
callback.
2021-01-04 12:51:55 -08:00
Michael Gottesman
041ecba21c Canonicalize single value forwarding insts that only have debug_value and destroy_value uses.
E.x.:

```
  %1 = unchecked_ref_cast %0
  destroy_value %1
->
  destroy_value %0
```

I am doing this only in non-Raw SIL to ensure that I do not disturb the
mandatory passes.
2020-12-09 19:17:03 -08:00
Michael Gottesman
1ca55774b2 Merge pull request #34559 from gottesmm/ossa-inst-simplify
[inst-simplify] Update for OSSA
2020-12-09 14:31:15 -08:00
Michael Gottesman
259d2bb182 [ownership] Commit a generic replaceAllUsesAndEraseFixingOwnership api and enable SimplifyInstruction on OSSA.
This is a generic API that when ownership is enabled allows one to replace all
uses of a value with a value with a differing ownership by transforming/lifetime
extending as appropriate.

This API supports all pairings of ownership /except/ replacing a value with
OwnershipKind::None with a value without OwnershipKind::None. This is a more
complex optimization that we do not support today. As a result, we include on
our state struct a helper routine that callers can use to know if the two values
that they want to process can be handled by the algorithm.

My moticiation is to use this to to update InstSimplify and SILCombiner in a
less bug prone way rather than just turn stuff off.

Noting that this transformation inserts ownership instructions, I have made sure
to test this API in two ways:

1. With Mandatory Combiner alone (to make sure it works period).

2. With Mandatory Combiner + Semantic ARC Opts to make sure that we can
   eliminate the extra ownership instructions it inserts.

As one can see from the tests, the optimizer today is able to handle all of
these transforms except one conditional case where I need to eliminate a dead
phi arg. I have a separate branch that hits that today but I have exposed unsafe
behavior in ClosureLifetimeFixup that I need to fix first before I can land
that. I don't want that to stop this PR since I think the current low level ARC
optimizer may be able to help me here since this is a simple transform it does
all of the time.
2020-12-09 11:53:56 -08:00
Michael Gottesman
8a6f6cbe20 [ownership][canonicalize] Canonicalize load_borrow the same we we canonicalize load. 2020-12-08 20:35:34 -08:00
Michael Gottesman
ec71713fb0 [ownership] Teach CanonicalizeInstruction how to eliminate trivial copies/borrows.
I am going to be using in inst-simplify/sil-combine/canonicalize instruction a
RAUW everything against everything API (*). This creates some extra ARC
traffic/borrows. It is going to be useful to have some simple peepholes that
gets rid of some of the extraneous traffic.

(*) Noting that we are not going to support replacing non-trivial
OwnershipKind::None values with non-trivial OwnershipKind::* values. This is a
corner case that only comes up with non-trivial enums that have a non-payloaded
or trivial enum case. It is much more complex to implement that transform, but
it is an edge case, so we are just not going to support those for now.

----

I also eliminated the dependence of SILGenCleanup on Swift/SwiftShims. This
speeds up iterating on the test case with a debug compiler since we don't need
those modules.
2020-12-02 17:25:13 -08:00
Zoe Carver
ee1d76ed44 [opt] Re-work broadenSingleElementStores to use projections. (#32318)
* Fixes loadable edge case for address-only types.
* Re-work, generalize, and simplify by using projections.
* Support `-enable-cxx-interop` in sil-opt.
2020-06-11 23:10:19 -07:00
Slava Pestov
83c90b6b2a AST: Turn NominalTypeDecl::getStoredProperties() into a request
This improves on the previous situation:

- The request ensures that the backing storage for lazy properties
  and property wrappers gets synthesized first; previously it was
  only somewhat guaranteed by callers.

- Instead of returning a range this just returns an ArrayRef,
  which simplifies clients.

- Indexing into the ArrayRef is O(1), which addresses some FIXMEs
  in the SIL optimizer.
2019-07-16 16:38:38 -04:00
Andrew Trick
320759227a Canonicalize stores in the CanonicalizeInstruction utility.
This is the complement to load canonicalization. Although store
canonicalization is not required before diagnostics, it should be
defined in the same utility.
2019-05-09 13:00:39 -07:00
Andrew Trick
52237aaaf7 Avoid else-return in splitAggregateLoad. 2019-05-06 17:23:08 -07:00
Andrew Trick
f151a96644 Add a comment on replaceUsesOfExtract per review feedback. 2019-05-06 17:23:08 -07:00
Andrew Trick
ca9ae0dda8 Canonicalize nontrivial loads.
This adds support to the load->struct_extract canonicalization for
nontrivial element types which look like:

load [copy]
borrow
struct_extract
...uses...
end_borrow
destroy
2019-05-06 17:23:08 -07:00
Andrew Trick
f395f86039 Canonicalize loads in SILGenCleanup.
Reimplement load instruction canonicalization as part of the
CanonicalizeInstruction utility.
2019-05-06 13:31:35 -07:00
Andrew Trick
9aa2523393 Add a CanonicalizeInstruction utility.
CanonicalizeInstruction will be a superset of
simplifyInstruction (once all the transforms are fixed for ownership
SIL). Additionally, it will also include simple SSA-based
canonicalization that requires new instruction creation. It may not
perform any optimization that interferes with diagnostics or increases
compile time.

Canonicalization replaces simplifyInstruction in SILCombine so we can
easily factor some existing SILCombine transforms into canonicalization.
2019-05-06 09:36:07 -07:00