Commit Graph

77 Commits

Author SHA1 Message Date
Gabor Horvath
00fa738209 [cxx-interop] Fix calling convention for rvalue reference params
In C++, we always expected to invoke the dtor for moved-from objects.
This is not the case for swift. Fortunately, @inCxx calling convention
is already expressing that the caller supposed to destroy the object.
This fixes the missing dtor calls when calling C++ functions taking
rvalue references. Fixes #77894.

rdar://140786022
2025-03-03 11:47:12 +00: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
Emil Pedersen
450db6e530 [DebugInfo] Add special cases for copy forwarding 2024-04-24 18:23:39 -07:00
Erik Eckstein
92a17f8a01 Optimizer: extract the NamedReturnValueOptimization from CopyForwarding to a separate function pass
This allows to run the NamedReturnValueOptimization only late in the pipeline.
The optimization shouldn't be done before serialization, because it might prevent predictable memory optimizations in the caller after inlining.
2023-05-11 08:11:44 +02:00
Nate Chandler
ed623d7b64 [NFC] Shortened SIL [init] flag.
Instead of writing out [initalization] for some instructions, use [init]
everywhere.
2022-10-27 10:38:54 -07:00
Erik Eckstein
ecbcacdecf SIL Analysis: Rename InvalidationKind::FunctionData to InvalidationKind::Effects
This invalidation kind is used when a compute-effects pass changes function effects.
Also, let optimization passes which don't change effects only invalidate the `FunctionBody` and not `Everything`.
2022-10-20 09:20:28 +02: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
Nate Chandler
4e2667b4e7 [CopyForwarding] Removed destroy hoisting.
It has been replaced by the destroy hoisting in SSADestroyHoisting.
2022-02-14 15:56:03 -08:00
Meghana Gupta
0683b3f998 Disable NRVO for alloc_stack [dynamic_lifetime] (#39972)
NRVO for alloc_stack [lifetime] will invalidate OSSA invariants
2021-11-01 13:37:59 -07:00
Min-Yih Hsu
343d842394 [SIL][DebugInfo] PATCH 3/3: Deprecate debug_value_addr SIL instruciton
This patch removes all references to DebugValueAddrInst class and
debug_value_addr instruction in textual SIL files.
2021-08-31 12:01:04 -07:00
Min-Yih Hsu
e1023bc323 [DebugInfo] PATCH 2/3: Duplicate logics regarding debug_value_addr
This patch replace all in-memory objects of DebugValueAddrInst with
DebugValueInst + op_deref, and duplicates logics that handles
DebugValueAddrInst with the latter. All related check in the tests
have been updated as well.

Note that this patch neither remove the DebugValueAddrInst class nor
remove `debug_value_addr` syntax in the test inputs.
2021-08-31 11:57:56 -07:00
Meghana Gupta
f4b585e933 Cleanup dead debug_value_addr in CopyForwarding
After hoisting the destroy of the copy src, debug_value_addr users of the
copy src become dead, this PR cleans them so that MemoryLifetimeVerifier does not
complain later.
2021-08-18 16:58:16 -07:00
Andrew Trick
39db766257 Restrict CopyForwarding (and destroy hoisting) to OSSA SIL.
The premise of CopyForwarding was that memory locations have their own
ownership lifetime. We knew this was unmaintainable at the time, and
that was the original incentive for SIL opaque values, aided by
OSSA. In the meantime, we've been relying on SILGen producing
reasonable SIL patterns. Unfortunately, the CopyForwarding pass is
still with us while we make major changes to SIL ownership patterns
and agressively optimize ownership. That introduces risk.

Ultimately, the entire CopyForwarding pass should be redesigned for
OSSA-only and destroy hoisting should be a simple OSSA utility where
most of the work is done by AccessPath::collectUses.

But in the meantime, we should remove the source of risk by limiting
the CopyForwarding pass to OSSA. Any performance regressions will be
recovered as OSSA moves later in the pipeline. After that, opaque
values will improve even more over the current state by handling
generic SIL using the more powerful CopyPropagation pass.

Fixes rdar://71584600 (miscompile in CopyForwarding's release hoisting)

Here's an example of the kind of SIL the CopyForwarding does not
anticipate (although it only actually miscompiles in much more obscure
scenarios, which is why it's so dangerous):

bb0(%0 : $AnyObject):
  %alloc1 = alloc_stack $AnyObject
  store %0 to %objaddr : $*AnyObject
  %ref = load %objaddr : $*AnyObject
  %alloc2 = alloc_stack $ObjWrapper
  # The in-memory reference is destroyed before retaining the loaded ref.
  copy_addr [take] %alloc1 to [initialization] %alloc2 : $*ObjWrapper
  retain_value %ref : $AnyObject
2020-11-19 21:52:04 -08:00
David Zarzycki
1e940c2c7e [NFC] Fix -Wsuggest-override warnings
LLVM, as of 77e0e9e17daf0865620abcd41f692ab0642367c4, now builds with
-Wsuggest-override. Let's clean up the swift sources rather than disable
the warning locally.
2020-08-13 16:17:46 -04:00
Meghana Gupta
c042638a37 Merge pull request #33098 from meg-gupta/updatestyle
Update code as per Apple Style Guide
2020-07-25 07:44:44 -07:00
Meghana Gupta
b34791a0a0 Update code as per Apple Style Guide
whitelist -> allowlist
blacklist -> denylist
2020-07-24 11:37:15 -07:00
Meghana Gupta
f28bff1846 Enable CopyForwarding on ossa 2020-07-24 01:05:38 -07:00
Meghana Gupta
858fe6c593 Remove debug instructions on dead temporaries in CopyForwarding (#32941) 2020-07-21 18:14:58 -07:00
Andrew Trick
69c2acfd9a Loosen a CopyForwarding assert: store instead of deinit.
CopyForwarding attempts to enforce "normal" SIL address patterns using
asserts. This isn't a good strategy because it results in strange
crash diagnostics in release builds. Eventually, we should replace
this logic with a SIL address lifetime utility based on OSSA form and
enforced in the verifier.

Loosen one of these restrictions where we assume that a value
initialized with "copy_addr [initialization]" will be properly
destroyed. This assumption is violated when lowering
.int_fma_FPIEEE32, which knows that the type is trivial, so avoids
deinitialization.

The original SIL looks like this:

  copy_addr %src to [initialization] %dest : $*Float
  %fma = builtin "int_fma_FPIEEE32"(% : $Builtin.FPIEEE32, % : $Builtin.FPIEEE32, % : $Builtin.FPIEEE32) : $Builtin.FPIEEE32
  %result = struct $Float (%fma : $Builtin.FPIEEE32)
  store %result to %dest : $*Float

Fixes rdar://64671864.
2020-06-30 18:53:22 -07:00
Michael Gottesman
5e9d720a28 Move TempRValueOpt from CopyForwarding.cpp -> TempRValueElimination.cpp.
The pass is standalone from CopyForwarding and is big enough to stand on its
own.

This changes is NFC beyond clang-format + xcode rename.
2020-02-25 21:12:16 -08:00
Andrew Trick
9dc59d2967 Fix TempRValue: Add checkTempObjectDestroy bail out logic.
This avoids use-after-free bugs that can be introduced by removing a
copy without replacing all corresponding destroys.

Add more descriptive comments since multiple bugs have been introduced
in this pass.

None of this will be relevant once the pass is converted to OSSA.
2019-10-27 21:42:44 -07:00
Erik Eckstein
e7ddae6852 TempRValueOptPass: accept try_apply as user of the temporary object
So far we only handled apply, but not try_apply.
2019-10-16 13:11:02 +02:00
Erik Eckstein
aa0d60a95f TempRValueOptPass: some small cosmetic changes
1. WitnessMethodInst doesn't need to be handled as use because it's operand is a typedependent operand, which we exclude anyway when looking at the uses.
2. Replace a list of handled instructions with a default value in the switch. It's easy to forget to add an instruction here. So it's safer to have a default behavior.
2019-10-16 13:11:01 +02:00
Erik Eckstein
fb76ce299c TempRValueOptPass: fix a miscompile with open_existential_addr
The uses of open_existential_addr were not handled correctly.

rdar://problem/56130674
2019-10-15 21:20:33 +02:00
Andrew Trick
bddc69c8a6 Organize SILOptimizer/Utils headers. Remove Local.h.
The XXOptUtils.h convention is already established and parallels
the SIL/XXUtils convention.

New:
- InstOptUtils.h
- CFGOptUtils.h
- BasicBlockOptUtils.h
- ValueLifetime.h

Removed:
- Local.h
- Two conflicting CFG.h files

This reorganization is helpful before I introduce more
utilities for block cloning similar to SinkAddressProjections.

Move the control flow utilies out of Local.h, which was an
unreadable, unprincipled mess. Rename it to InstOptUtils.h, and
confine it to small APIs for working with individual instructions.
These are the optimizer's additions to /SIL/InstUtils.h.

Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now
there is only SIL/CFG.h, resolving the naming conflict within the
swift project (this has always been a problem for source tools). Limit
this header to low-level APIs for working with branches and CFG edges.

Add BasicBlockOptUtils.h for block level transforms (it makes me sad
that I can't use BBOptUtils.h, but SIL already has
BasicBlockUtils.h). These are larger APIs for cloning or removing
whole blocks.
2019-10-02 11:34:54 -07:00
Erik Eckstein
8b11e7ce23 SILOptimizer: handle copy_addr [take] in TempRValueOpt 2019-08-28 12:14:38 +02:00
Michael Gottesman
30accb058d [temp-immut-rv-forward] Handle open_existential_addr immutable_access.
Now we handle this case:

  %stack = alloc_stack $Protocol
  copy_addr %var to [initialization] %stack
  open_existential_addr immutable_access %stack
  ...
  destroy_addr %stack
  dealloc_stack %stack

We only do this if we have immutable_access. To be conservative I still only let
the normal whitelist of other instructions through.

I am adding this optimization since I am going to be eliminating a SILGen
peephole so I can enable SIL ownership verification everywhere.
2019-03-18 22:13:06 -07:00
Slava Pestov
8915f96e3e SIL: Replace SILType::isTrivial(SILModule) with isTrivial(SILFunction) 2019-03-12 01:16:04 -04:00
Andrew Trick
7176aaf8ea Add a comment to TempRValue optimization.
A recent fix added some code that is inconsistent with the design of
the pass, creates an implicit coupling between separate parts of the
optimization, and relies on incredibly subtle reasoning to ensure
correctness.

This sort of thing needs a big fat comment.
2019-02-03 14:16:31 -08:00
Michael Gottesman
d78e83c010 [ownership] Do some preliminary work for moving OME out of the diagnostics pipeline.
This disables a bunch of passes when ownership is enabled. This will allow me to
keep transparent functions in ossa and skip most of the performance pipeline without
being touched by passes that have not been updated for ownership.

This is important so that we can in -Onone code import transparent functions and
inline them into other ossa functions (you can't inline from ossa => non-ossa).
2019-01-31 13:38:05 -08:00
Erik Eckstein
f0eed8c409 SILOptimizer: fix a bug in the TempRValue optimization which causes a miscompile.
The problematic scenario is that a function receives an @in_guaranteed and @inout parameter where one is a copy of the other value. For example, when appending a container to itself.
In this case the optimization removed the copy_addr, resulting in passing the same stack location to both parameters.

rdar://problem/47632890
2019-01-30 12:38:10 -08:00
Andrew Trick
f764b8b615 Fix a bug in CopyForwarding. Bailout during destoy hoisting.
Once the algorithm has begun hoisting destroys globally, there's no
way to cleanly bailout. The previous attempt to bailout could result
in an assert or lost destroy in release mode.

This is continued fall-out from changes in the previous release to
upstream SILGen or mandatory passes, such as PredictableMemOps, that
no longer preserve natural variable lifetimes.

In this case, we end up with SIL like this before CopyForwarding:

bb(%arg)
%local_addr = alloc_stack
store %arg to %local_addr
%payload = switch_enum(%arg)
retain %arg
store %arg to %some_addr
destroy_addr %local_addr
release_value %arg

We're attempting to hoist the destroy_addr to its last use, but can't
because the lifetimes of the alloc_stack (%local_addr) and the value
being stored on the stack (%arg) have become mixed up by an upstream
pass. We actually detect this situation now in order to bail-out of
destroy hoisting. Sadly, the bailout might only partially recover in
the case of interesting control flow, as happens in the test case's
Graph.init function. This triggers an assert, but in release mode it
simply drops the destroy.

Fixed <rdar://problem/43888666> [SR-8526]: Memory leak after switch in
release configuration.
2018-08-31 18:29:15 -07:00
Andrew Trick
89ed064808 Fix several incorrect uses of ApplySite::getArgumentConvention.
At least most of these were latent bugs since the code was
unreachable in the PartialApply case. But that's no excuse to misuse
the API.

Also, whenever referring to an integer index, be explicit about
whether it is an applied argument or callee argument.
2018-07-28 00:05:40 -07:00
Bob Wilson
8e330ee344 NFC: Fix indentation around the newly renamed LLVM_DEBUG macro.
Jordan used a sed command to rename DEBUG to LLVM_DEBUG. That caused some
lines to wrap and messed up indentiation for multi-line arguments.
2018-07-21 00:56:18 -07:00
Jordan Rose
cefb0b62ba Replace old DEBUG macro with new LLVM_DEBUG
...using a sed command provided by Vedant:

$ find . -name \*.cpp -print -exec sed -i "" -E "s/ DEBUG\(/ LLVM_DEBUG(/g" {} \;
2018-07-20 14:37:26 -07:00
David Zarzycki
03b7eae9ed [SILOptimizer] NFC: Adopt reference storage type meta-programming macros 2018-06-30 06:44:33 -04:00
Arnold Schwaighofer
4525722395 SIL: Add getSingleDealloc to AllocStack and remove two copies of it
I am going to introduce a third use in a follow-up
2018-05-01 07:24:19 -07:00
Andrew Trick
8ab8ca4efa Make CopyForwarding more conservative about shrinking lifetimes.
Fixes <rdar://problem/39209102> [SR-7354]: Swift 4.1 Regression: EXC_BAD_ACCESS for Optimized Builds in Xcode 9.3

Commentary:

The underlying problem is that CopyForwarding is an inherently
dangerous pass by design that has been waiting for the SIL
representation to evolve to the point where it can be rewritten.

The regressions was caused by PredictableMemOps failing to preserve
normal patterns of ownership. When it forwards loads, it implicitly
extends the lifetime of stored value

store %val to %addr
...
retain %val
...
destroy_addr %addr

CopyForwarding already tried to detect such violations of ownership
rules and normally bypasses destroy hoisting in those cases. In this
case, it fails to detect the problem because PredictableMemOps has
already erased the load, so there's no evidence of the value's
lifetime being extended.

It might have been nice if PredictableMemOps had transformed the
retain %val into a retain %addr. However, for the immediate fix, we
don't want to change any existing behavior other than suppressing
optimization. In the long term, CopyForwarding does not really make
sense without SemanticSIL+SILOwnership and should be totally rewritten
and greatly simplified at that point.
2018-04-10 22:08:54 -07:00
Andrew Trick
1416739a64 Suppress NRVO in copy forwarding unless the copy is just a move.
Fixes <rdar://problem/39059402> CopyForwarding + Guaranteed Bug
2018-03-30 18:09:35 -07:00
Sho Ikeda
26d650292f [gardening] Use empty() over size() == 0 2018-03-05 14:43:13 +09:00
Michael Gottesman
8160913cb1 [temp-rvalue] Teach the temprvalue to ignore @in_guaranteed uses.
This is a pattern that comes up very often in an all +0 normal argument
convention world.

rdar://34222540
2018-01-09 18:25:06 -08:00
Andrew Trick
b39de959fa Fix a theoretical copy forwarding bug.
Reviewing the code with Arnold revealed a corner case where forward propagating
a copy into multiple operands of the same instruction wasn't properly detected.
I don't think this case was possible given the language rules, but nonetheless
it is valid SIL and needs to be handled.

This is confusing because in some cases we optimize that situation correctly,
and in other cases we try to assert that it doesn't happen. So, I simplified the
code to bailout anywhere that we see multiple operands of the same value. This
isn't an expected situation that needs to be optimized.
2017-12-14 09:37:12 -08:00
Andrew Trick
2caf1748a5 CopyForwarding - small redesign to fix bugs.
Copy forwarding was designed with some assumptions about symmetry of
operations. If copy_value/destroy_value are expanded somewhere for a given
value, then they should be expanded everywhere. The pass took a conservative
approach to SIL patterns that were guaranteed safe, and bailed out on unknown
patterns. However, due to some over-aggressive code factoring, the assumption
wasn't being checked in one corner case.

This redesign makes a clear distinction between the requirements for forward
vs. backward propagation.

Fixes <rdar://35646292> Swift CI: resilience bot seg faults in
stdlib/RangeReplaceable.swift.gyb
2017-12-10 01:17:13 -08:00
John McCall
ab3f77baf2 Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode.

This is in preparation for allowing instructions to have multiple
results.  It is also a somewhat more elegant representation for
instructions that have zero results.  Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction.  Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.

A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.

Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
2017-09-25 02:06:26 -04:00
Michael Gottesman
e378ad8075 [copy-forwarding] Move a DEBUG log of an instruction to before we destroy the instruction...
Found while debugging dc8b1c2c3a.
2017-09-04 10:49:15 -07:00
Jordan Rose
f8b7db4e76 Excise the terms "blacklist" and "whitelist" from Swift source. (#11687)
The etymology of these terms isn't about race, but "black" = "blocked"
and "white" = "allowed" isn't really a good look these days. In most
cases we weren't using these terms particularly precisely anyway, so
the rephrasing is actually an improvement.
2017-08-30 09:28:00 -07:00
Erik Eckstein
6c93798acc SILOptimizer: Add a new TempRValue optimization pass
This is a separate optimization that detects short-lived temporaries that can be eliminated.
This is necessary now that SILGen no longer performs basic RValue forwarding in some cases.

SR-5508: Performance regression in benchmarks caused by removing SILGen peephole for LoadExpr in +0 context
2017-08-05 17:23:51 -07:00
practicalswift
7eb7d5b109 [gardening] Fix 100 typos. 2017-04-18 17:01:42 +02:00
Andrew Trick
095083e0e8 CopyForwarding: new optimization to remove copies into dead temporaries.
A SILGen peephole currently handles the common cases. However, that peephole
is incompatible with memory access enforcement.
2017-04-14 21:05:33 -07:00
Andrew Trick
be1881aa1f Remove redundant Transform.getName() definitions.
At some point, pass definitions were heavily macro-ized. Pass
descriptive names were added in two places. This is not only redundant
but a source of confusion. You could waste a lot of time grepping for
the wrong string. I removed all the getName() overrides which, at
around 90 passes, was a fairly significant amount of code bloat.

Any pass that we want to be able to invoke by name from a tool
(sil-opt) or pipeline plan *should* have unique type name, enum value,
commend-line string, and name string. I removed a comment about the
various inliner passes that contradicted that.

Side note: We should be consistent with the policy that a pass is
identified by its type. We have a couple passes, LICM and CSE, which
currently violate that convention.
2017-04-09 15:20:28 -07:00