Commit Graph

2053 Commits

Author SHA1 Message Date
Erik Eckstein
e028239cc2 Swift Optimizer: add AllocRefInstBase.setIsStackAllocatable 2022-01-12 15:47:16 +01:00
Erik Eckstein
e152b2cb4a Swift Optimizer: add the fixStackNesting utility in PassContext
This bridges to the StackNesting utility in C++
2022-01-12 15:47:16 +01:00
Erik Eckstein
a24b17a333 Swift Optimizer: add the dominator and post-dominator tree analysis 2022-01-12 15:47:16 +01:00
Erik Eckstein
4440beb555 Swift Optimizer: add bridging to the DeadEndBlocksAnalysis 2022-01-12 15:47:16 +01:00
Erik Eckstein
40200d6544 Swift Optimizer: add BasicBlock utility data structures and rename StackList
* add `BasicBlockSet`
* add `BasicBlockWorklist`
* add `BasicBlockRange`, which defines a range of blocks from a common dominating “begin” block to a set of “end” blocks.
* add  `InstructionRange`, which is similar to `BasicBlockRange`, just on instruction level. It can be used for value lifetime analysis.
* rename `StackList` -> `Stack` and move it to `Optimizer/DataStructures`
* rename `PassContext.passContext` to `PassContext._bridged`
* add notify-functions to PassContext
2022-01-12 15:47:16 +01:00
Max Desiatov
5ef19cf0d9 libswift: add back legacy pass to fix Windows test 2022-01-10 13:10:32 +00:00
Max Desiatov
42e6fac1ea libswift: reimplement AssumeSingleThreaded pass 2022-01-10 08:47:43 +00:00
Michael Gottesman
5dc8b3879b [move-function] SILCloner/mangling changes to support converting inout_aliasable defer parameters to out parameters after move analysis. 2022-01-08 13:41:05 -08:00
Erik Eckstein
383c52aa35 SIL: rename dealloc_ref [stack] -> dealloc_stack_ref
Introduce a new instruction `dealloc_stack_ref ` and remove the `stack` flag from `dealloc_ref`.

The `dealloc_ref [stack]` was confusing, because all it does is to mark the deallocation of the stack space for a stack promoted object.
2022-01-07 16:20:27 +01:00
Erik Eckstein
3522ba1521 SILOptimizer: rename LibswiftPassInvocation -> SwiftPassInvocation
And a few other small related changes:
* remove libswiftPassInvocation from SILInstructionWorklist (because it's not needed)
* replace start/finishPassRun with start/finishFunction/InstructionPassRun

NFC
2022-01-05 10:15:56 +01:00
swift-ci
e32105eb44 Merge pull request #40392 from atrick/destroy-hoist 2021-12-22 14:50:02 -08:00
Andrew Trick
c8a2130554 Add a SSADestroyHoisting utility and pass
Extract and rewrite the destroy hoisting algorithm originally from
CopyForwarding (in 2014).

This is now a light-weight utility for hoisting destroy_addr
instructions. Shrinking an object's memory lifetime can allow removal
of copy_addr and other optimization.

This is extremely low-overhead and can run at any optimization level
without dependency on any analysis.

This algorithm is:
- Incremental
- SSA-based
- Canonical
- Free from alias analysis

See file-level comments.

The immediate purpose is to specify and test the constraints
introduced by adding lexical variable lifetimes to SIL semantics. It
can be used as a template for end_borrow hoisting.

Ultimately, this utility can be invoked within any pass that needs to
optimize a particular uniquely identified address. It will be used to
remove much of the complexity from CopyForwarding.
2021-12-22 11:32:57 -08:00
Andrew Trick
3e532b2a8d Add a general BackwardReachability analysis.
Pessimistic, non-iterative data flow for analyzing backward reachability
from a set of last uses to their dominating def or nearest barrier.

Meet: ReachableEnd(predecessor) = intersection(ReachableBegin, successors)

Intended for frequently called utilities where minimizing the cost of
data flow is more important than analyzing reachability across
loops. Expected to visit very few blocks because barriers often occur
close to a last use.

Note: this does not require initializing bitsets for all blocks in the
function for each SSA value being analyzed.
2021-12-22 11:32:57 -08:00
Erik Eckstein
3540c01125 rename initializeLibSwift -> InitializeSwiftModules
and some updates in comments.
2021-12-22 11:31:52 +01:00
Erik Eckstein
408cf02bc8 rework cross-module-optimization
* rename the CrossModuleSerializationSetup pass to simply CrossModuleOptimization
* remove the CMO specific serializer pass. Instead run the CrossModuleSerializationSetup pass directly before the standard serializer pass.
* correctly handle shared functions (e.g. specializations)
* refactoring
2021-12-20 11:33:02 +01:00
Nate Chandler
1c106eb6e8 [ShrinkBorrowScope] Return modified copy_values.
So that CopyPropagation and other clients can react accordingly, pass
back a list of copy_value instructions that were rewritten by
ShrinkBorrowScope.  In CopyPropagation, add each modified copy to the
copy worklist.
2021-12-19 08:14:45 -08:00
Andrew Trick
0eb7f464e2 Add createDebugFragments utility API
Create debug_value fragment for a new partial value based on a
projection of an old debug_value.
2021-12-15 11:02:11 -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
Andrew Trick
0b95286ddb Add LoadOperation::getLoadInst for readability at the use sites.
And minor implementation cleanup.
2021-12-13 21:35:14 -08:00
Konrad `ktoso` Malawski
cee89ec541 [Distributed] DistributedActorSystem renaming and redesign (#40387)
* [Distributed] towards DistributedActorSystem; synthesize the id earlier, since Identifiable.id

* Fix execute signature to what Pavel is working with

* funcs are ok in sil

* fixed lifetime of id in inits

* fix distributed_actor_deinit

* distributed_actor_local

* update more tests

fixing tests

fix TBD test

fix Serialization/distributed

fix irgen test

Fix null pointer crashes

* prevent issues with null func ptrs and fix Distributed prorotocol test

* fix deinit sil test
2021-12-13 11:29:25 +09:00
Michael Gottesman
4a9c26ff96 [move-function] Make MandatoryInlining always convert builtin.move -> mark_unresolved_move_addr.
To give a bit more information, currently the way the move function is
implemented is that:

1. SILGen emits a builtin "move" that is called within the function _move in the
   stdlib.

2. Mandatory Inlining today if the final inlined type is address only, inlines
   builtin "move" as mark_unresolved_move_addr. Otherwise, if the inlined type
   is loadable, it performs a load [take] + move [diagnostic] + store [init].

3. In the diagnostic pipeline before any mem optimizations have run, we run the
   move checker for addresses. This eliminates /all/ mark_unresolved_move_addr
   as part of emitting diagnostics. In order to make this work, we perform a
   small optimization before the checker runs that moves the
   mark_unresolved_move_addr from being on temporary alloc_stacks to the true
   base underlying address we are trying to move. This optimization is necessary
   since _move is generic and often times SILGen will emit this temporary that
   we do not want.

4. Then after we have run the guaranteed mem optimizations, we run the object
   based move checker emitting diagnostics.

This PR changes the scheme above to the following:

1. SILGen emits a builtin "move" that is called within the function _move in the
   stdlib.

2. Mandatory Inlining inlines builtin "move" as mark_unresolved_move_addr.

3. In the diagnostic pipeline before we have run any mem optimizations and
   before we have run the actual move address checker, we massage the IR as we
   do above but in a separate pass where in addition we try to match this pattern:

     ```
     %temporary = alloc_stack $LoadableType
     store %1 to [init] %temporary : $*LoadableType
     mark_unresolved_move_addr %temporary to %otherAddr : $*LoadableType
     destroy_addr %temporary : $*LoadableType
     ```

   and transform it to:

     ```
     %temporary = alloc_stack $LoadableType
     %2 = move_value [allows_diagnostics] %1 : $*LoadableType
     store %2 to [init] %temporary : $*LoadableType
     destroy_addr %temporary : $*LoadableType
     ```

   ensuring that the object move checker will handle this.

4. Then after we have run the guaranteed mem optimizations, we run the object
   based move checker emitting diagnostics.
2021-12-09 12:48:29 -08:00
Nate Chandler
cde250a3e3 [CopyPropagation] Add ShrinkBorrowScope.
During copy propagation (for which -enable-copy-propagation must still
be passed), also try to shrink borrow scopes by hoisting end_borrows
using the newly added ShrinkBorrowScope utility.

Allow end_borrow instructions to be hoisted over instructions that are
not deinit barriers for the value which is borrowed.  Deinit barriers
include uses of the value, loads of memory, loads of weak references
that may be zeroed during deinit, and "synchronization points".

rdar://79149830
2021-12-07 09:43:57 -08:00
Michael Gottesman
e3f9eaca58 [move-function] Implement the move-function checker for address only lets. 2021-12-06 12:47:31 -08:00
Andrew Trick
89878a7b86 Merge pull request #40254 from atrick/fix-dead-stdlib-assert
Add isReadOnlyConstantEvaluableCall to handle stdlib asserts
2021-11-30 09:28:23 -08:00
Erik Eckstein
f97876c9e7 RLE: better handling of ref_element/tail_addr [immutable]
Rerun RLE with cutting off the base address of loads at `ref_element/tail_addr [immutable]`. This increases the chance of catching loads of immutable COW class properties or elements.
2021-11-29 09:41:05 +01:00
Erik Eckstein
5090603df0 libswift: add an instruction pass to simplify begin_cow_mutation instructions
* Replace the uniqueness result of a begin_cow_mutation of an empty Array/Set/Dictionary singleton with zero.
* Remove empty begin_cow_mutation - end_cow_mutation pairs
* Remove empty end_cow_mutation - begin_cow_mutation pairs
2021-11-29 09:41:05 +01:00
Saleem Abdulrasool
5bf4da88df SILOptimizer: avoid trawling through the directories for includes
Use the include search path for the header search rather than
constructing the path using relative paths.  This is important for
getting the interop to work properly as well.
2021-11-26 09:11:42 -08:00
Andrew Trick
f512bebf07 Add isReadOnlyConstantEvaluableCall to handle stdlib asserts
Fix isScopeAffectingInstructionDead to use this new API. A stdlib
assert, which has "program_termination" semantics, should not be
considered read-only.

isReadOnlyConstantEvaluableCall API:

/// Return true iff the \p applySite is constant-evaluable and read-only.
///
/// Functions annotated as "constant_evaluable" are assumed to be "side-effect
/// free", unless their signature and substitution map indicates otherwise. A
/// constant_evaluable function call is read only unless it:
///   (1) has generic parameters
///   (2) has inout parameters
///   (3) has indirect results
///
/// Read-only constant evaluable functions can do only the following and
/// nothing else:
///   (1) The call may read any memory location.
///   (2) The call may destroy owned parameters i.e., consume them.
///   (3) The call may write into memory locations newly created by the call.
///   (4) The call may use assertions, which traps at runtime on failure.
///   (5) The call may return a non-generic value.
///
/// Essentially, these are calls whose "effect" is visible only in their return
/// value or through the parameters that are destroyed. The return value
/// is also guaranteed to have value semantics as it is non-generic and
/// reference semantics is not constant evaluable.
2021-11-18 18:38:49 -08:00
Andrew Trick
c86d112891 Update #include for InstructionDeleter.h 2021-11-18 11:38:08 -08:00
Andrew Trick
b517cce16f Move InstructionDeleter into its own header.
Add file-level comments on the utility's purpose and intended API
usage.

Cleanup API comments.
2021-11-18 11:38:08 -08:00
Meghana Gupta
39f74bb980 Merge pull request #40002 from meg-gupta/newfixoutliner
Fix OSSA Outliner for scoped guaranteed values
2021-11-17 15:39:36 -08:00
Michael Gottesman
d526f36dc0 [moveOnly] Add a new pass called the LexicalLifetimeEliminator that runs after we finish lexical diagnostics.
NOTE: This pass is disabled when -enable-experimental-lexical-lifetimes is
enabled.

When that flag is disabled, this removes the lexical flag from begin_borrow and
alloc_stack. This ensures that we can begin using begin_borrow [lexical] and
friends to emit diagnostics without impacting performance. I am going to be
preparing a subsequent patch that causes us to emit lexical lifetimes by
default. Due to this pass, I am not expecting any issues around perf.
2021-11-12 13:17:02 -08:00
Michael Gottesman
4aa4ac3027 [moveOnly] Add checker that validates that if a let/param copyable value has _move applied to it, the let doesn't have any later uses.
This is just an initial prototype for people to play with. It is as always
behind the -enable-experimental-move-only flag.

NOTE: In this PR I implemented this only for 'local let' like things (local
lets/params). I did not implement in this PR support for local var and haven't
done anything with class ivars or globals.

rdar://83957028
2021-11-04 17:13:29 -07:00
Meghana Gupta
e9df26803b Add new api makeGuaranteedValueAvailable 2021-11-01 14:03:22 -07:00
Doug Gregor
3da14e6f65 Refactor and generalize distributed actor transport SIL generation.
Refactor the code that generates SIL to call into the distributed actor
transport to eliminate duplication and better cope with concrete actor
transports. Centralize the knowledge of which actor transport is used
with a given distributed actor type.
2021-10-30 21:49:35 -07:00
eeckstein
d5ae51130d Merge pull request #39902 from eeckstein/performance-annotations
First prototype of Performance Annotations
2021-10-29 07:39:41 +02:00
Michael Gottesman
e5d0f386e4 [moveOnly] Add a new experimental move only checker that checks noImplicitCopy variables.
NOTE: This is only available when the flag -enable-experimental-move-only. There
are no effects when the flag is disabled.

The way that this works is that it takes advantage of the following changes to
SILGen emission:

* When SILGen initializes a let with NoImplicitCopyAttribute, SILGen now emits
a begin_borrow [lexical] + copy + move_only. This is a pattern that we can check
and know that we are processing a move only value. When performing move
checking, we check move_only as a move only value and that it isn't consumed
multiple times.

* The first point works well for emitting all diagnostics except for
initializing an additional let var. To work around that I changed let
initialization to always bind to an owned value to a move of that owned
value. There is no semantic difference since that value is going to be consumed
by the binding operation anyways so we effectively just move the cleanup from
the original value we wanted to bind to the move. We still then actually borrow
the new let value with a begin_borrow [lexical] for the new let value. This
ensures that an initialization of a let value appears to be a consuming use to
the move only value checker while ensuring that the value has a proper
begin_borrow [lexical].

Some notes on functionality:

1. This attribute can only be applied to local 'let'.

2. "print" due to how we call it today with a vararg array is treated as a
   consuming use (unfortunately).

3. I have not added the builtin copy operator yet, but I recently added a _move
   skeleton attribute so one can end the lifetimes of these values early.

4. This supports all types that are not address only types (similar to
   _move). To support full on address only types we need opaque values.

rdar://83957088
2021-10-28 11:32:22 -07:00
Erik Eckstein
9f8b155c6c PerformanceDiagnostics: a pass to print errors for performance violations in annotated functions.
The PerformanceDiagnostics pass issues performance diagnostics for functions which are annotated with performance annotations, like @_noLocks, @_noAllocation.
This is done recursively for all functions which are called from performance-annotated functions.

rdar://83882635
2021-10-28 18:44:46 +02:00
Erik Eckstein
569a520db2 SILOptimizer: add a mandatory generic-specialization pass.
This pass is only used for functions with performance annotations (@_noLocks, @_noAllocation).
It runs in the mandatory pipeline and specializes all function calls in performance-annotated functions and functions which are called from such functions.
In addition, the pass also does some other related optimizations: devirtualization, constant-folding Builtin.canBeClass, inlining of transparent functions and memory access optimizations.
2021-10-28 18:43:14 +02:00
Erik Eckstein
dc8d4821dc SILOptimizer: extract predictable access and dead alloc optimizations into stand-alone utility functions 2021-10-28 18:43:14 +02:00
Erik Eckstein
7c28d7a625 migrate SILInliner to use InstructionDeleter 2021-10-28 18:43:14 +02:00
Erik Eckstein
49351c4759 SILOptimizer: extract the peephole optimization for Builtin.canBeClass into a separate utility. 2021-10-28 18:43:14 +02:00
Erik Eckstein
094494e1ed SILOptimizer: add basic block utilities ReachingReturnBlocks and NonErrorHandlingBlocks
* ReachingReturnBlocks: computes the set of blocks from which a path to the return-block exists (does not include paths to a throw-block)
* NonErrorHandlingBlocks: computes the set of blocks which are not used for error handling, i.e. not (exclusively) reachable from the error-block of a try_apply
2021-10-28 18:43:14 +02:00
Kavon Farvardin
e54fa6c6db inject actorReady calls for async dist actor ctors
Immediately after the hop_to_executor in an async, distributed
actor init, we need to notify the transport that the actor is ready.

This patch does not yet account for more complex cases. In particular,
we will need a mechanism to prevent multiple calls to actorReady,
which can happen if a loop appears in the init:

distributed actor Dactor {
  var x: Int
  init(tport: ActorTransport, count: Int) async {
    var i = count
    repeat {
      self.x = count
      // hop is injected here
      i -= 1
    } while i > 0
  }
}
2021-10-21 19:41:31 -07:00
Kavon Farvardin
51b769795a decouple the emission of actorReady from SILGen
We need to be able to inject a call to a distributed actor's
transport.actorReady, passing the actor instance to it,
during definite initialization. This means that its dependence
on SILGenFunction must be broken, hence this refactoring as
a SILOptimizer utility.
2021-10-21 19:41:31 -07:00
Slava Pestov
a9794dca55 Remove some unnecessary includes of GenericSignatureBuilder.h 2021-10-20 14:39:25 -04:00
nate-chandler
c6d908419b Merge pull request #39802 from nate-chandler/basic/graph-node-worklist-rename
[Basic] Renamed GraphNodeWorklist.
2021-10-18 14:00:02 -07:00
Andrew Trick
275c341010 Merge pull request #39740 from atrick/oou-borrow
OSSA utility incremental redesign and SILCombine fixes
2021-10-18 13:55:03 -07:00
Meghana Gupta
22aa3c5dbe Fix Escape Analysis for OSSA's pattern of array.uninitialized (#39789) 2021-10-18 09:39:19 -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