Commit Graph

658 Commits

Author SHA1 Message Date
Erik Eckstein
2b117fd3ee Swift Optimizer: add APIs to copy from or to a global static initializer
* `Context.copyStaticInitializer(fromInitValue:, to:)`
* `FunctionPassContext.createStaticInitializer(for:,initValue:)`
2023-05-08 21:23:36 +02:00
Erik Eckstein
ee2924fd27 Inliner: don't distinguish between the "mid-level" and "late" inliner
Now that we handle inlined global initializers in LICM, CSE and the StringOptimization, we don't need to have a separate mid-level inliner pass, which treats global accessors specially.
2023-05-08 21:23:36 +02:00
Erik Eckstein
260e68b102 Passmanager: fix a problem with skipping the inliner pass
A pass is skipped if no other pass changed the function since the previous run of the same pass.
Don't do this is if a pass depends on the function bodies of called functions, e.g. the inliner.
Other passes might change the callees, e.g. function signature opts, which makes it worth to run the inliner
again, even if the function itself didn't change.
2023-05-08 21:23:36 +02:00
Erik Eckstein
3e04b8681c make ModulePassContext conform to CustomStringConvertible
and let its description return a dump of the whole module.
This is useful for debugging
2023-05-08 21:23:36 +02:00
Erik Eckstein
9b51e69dac Swift Optimizer: constant fold builtins in the simplification passes 2023-05-08 21:23:36 +02:00
Michael Gottesman
224674cad1 [move-only] Ensure that we treat captured escaping closure arguments as such even if the closure doesn't actually escape
Specifically, we already have the appropriate semantics for arguments captured
by escaping closures but in certain cases allocbox to stack is able to prove
that the closure doesn’t actually escape. This results in the capture being
converted into a non-escaping SIL form. This then causes the move checker to
emit the wrong kind of error.

The solution is to create an early allocbox to stack that doesn’t promote move
only types in boxes from heap -> stack if it is captured by an escaping closure
but does everything else normally. Then once the move checking is completed, we
run alloc box to stack an additional time to ensure that we keep the guarantee
that heap -> stack is performed in those cases.

rdar://108905586
2023-05-04 12:25:19 -07:00
Erik Eckstein
4b33b99ee2 MemoryLifetimeVerifier: be more precise with indirect function arguments.
Optimizations can rely on alias analysis to know that an in-argument (or parts of it) is not actually read.
We have to do the same in the verifier: if alias analysis says that an in-argument is not read, there is no need that the memory location is initialized.

Fixes a false verifier error.
rdar://106806899
2023-05-03 14:33:45 +02:00
Nate Chandler
90f7af22c9 [SILOpt] Run DestroyAddrHoisting in mandatory.
Run DestroyAddrHoisting in the pipeline where DestroyHoisting was
previously running.  Avoid extra ARC traffic that having no form of
destroy hoisting in the mandatory pipeline results in.

rdar://90495704
2023-04-04 11:11:34 -07:00
eeckstein
85986f4e58 Merge pull request #64635 from eeckstein/fix-inline-always
PerformanceInliner:  protect against misuse of @inline(__always)
2023-03-28 16:24:12 +02:00
Nate Chandler
1a7c4a4d12 [NFC] Renamed DestroyAddrHoisting.
It was previously named SSADestroyHoisting which is rather misleading
considering that it deals with addresses and hoists destroy_addrs.
2023-03-27 14:15:03 -07:00
Erik Eckstein
34972489cd PassManager: add an option -sil-min-pass-time to only print long running passes 2023-03-27 16:10:45 +02:00
Erik Eckstein
67299b4471 SIL bridging: work around an unresolved symbol linker error
Works around  problem https://github.com/apple/swift/issues/64502
2023-03-21 15:33:09 +01:00
Erik Eckstein
010efc1ca6 Swift Bridging: use C++ instead of C bridging for the optimizer 2023-03-21 15:33:09 +01:00
Erik Eckstein
a092ecb5c2 remove SILBridgingUtils.h 2023-03-21 15:33:09 +01:00
Erik Eckstein
4445373808 Swift Bridging: use C++ instead of C bridging for BridgedInstruction 2023-03-21 15:33:09 +01:00
Erik Eckstein
c4f5bab5b7 Swift Bridging: use C++ instead of C bridging for BridgedBasicBlock 2023-03-21 15:33:09 +01:00
Erik Eckstein
ae7770d911 Swift Bridging: use C++ instead of C bridging for BridgedFunction 2023-03-21 15:33:09 +01:00
Erik Eckstein
e469c16744 Swift Bridging: remove BridgedType and directly use the C++ SILType instead 2023-03-21 15:33:09 +01:00
Erik Eckstein
598644fb92 Swift Bridging: use C++ instead of C bridging for the bridged witness table classes 2023-03-21 15:33:09 +01:00
Erik Eckstein
151f09769f Swift Bridging: use C++ instead of C bridging for BridgedVTable and BridgedVTableEntry 2023-03-21 15:33:09 +01:00
Erik Eckstein
eecea088e7 Swift Bridging: use C++ instead of C bridging for BridgedOperand and BridgedValue 2023-03-21 15:33:09 +01:00
Nate Chandler
ade29db6bd CopyPropagation: Compute side-effects first.
Add a run of ComputeSideEffects before the first run of CopyPropagation.
Allow hoisting over applies of functions that are able to be analyzed
not to be deinit barriers at this early point.
2023-03-16 13:01:05 -07:00
Michael Gottesman
f055bdc3aa [reference-bindings] Add initial prototype of the reference binding transform pass. 2023-03-03 17:14:41 -08:00
Andrew Trick
c588c657f5 SILVerifier - option to verify with or without linear lifetime check
Add a separate 'verifyOwnership()' entry point so it's possible
to check OSSA lifetimes at various points.

Move SILGenCleanup into a SILGen pass pipeline.

After SILGen, verify incomplete OSSA.

After SILGenCleanup, verify ownership.
2023-03-01 21:41:46 -08:00
Michael Gottesman
6c922af8aa [move-only] Combine the address/object checker in the same pass so that we only run cleanups once.
Otherwise, sometimes when the object checker emits a diagnostic and cleans up
the IR, some of the cleaned up copies are copies that should have been handled
by the address checker. The end result is that the address checker does not emit
diagnostics for that IR. I found this problem was exascerbated when writing code
for escaping closures.

This commit also cleans up the passes in preparation for at a future time moving
some of the transformations into the utils folder.
2023-02-19 13:55:22 -08:00
eeckstein
df6677b1b6 Merge pull request #63494 from eeckstein/instruction-passes
Optimizer: Replace the MandatoryCombine pass with a Simplification pass, which is implemented in Swift
2023-02-09 10:03:31 +01:00
Erik Eckstein
d25b1ed834 Optimizer: Replace the MandatoryCombine pass with a Simplification pass, which is implemented in Swift
The Swift Simplification pass can do more than the old MandatoryCombine pass: simplification of more instruction types and dead code elimination.
The result is a better -Onone performance while still keeping debug info consistent.

Currently following code patterns are simplified:
* `struct` -> `struct_extract`
* `enum` -> `unchecked_enum_data`
* `partial_apply` -> `apply`
* `br` to a 1:1 related block
* `cond_br` with a constant condition
* `isConcrete` and `is_same_metadata` builtins

More simplifications can be added in the future.

rdar://96708429
rdar://104562580
2023-02-09 06:50:05 +01:00
Michael Gottesman
a624fece3e [move-only] Move MoveOnlyObjectChecker /before/ MoveOnlyAddressChecker in the pass pipeline and move post checker verification into the MoveOnlyAddressChecker.
The reason why I am doing this is that:

1. There are sometimes copy_value on move only values loaded from memory that
the MoveOnlyAddressChecker needs to eliminate.

2. Previously, the move only address checker did not rewrite copy_value ->
explicit_copy_value if it failed in diagnostics (it did handle load [copy] and
copy_addr though). This could then cause the copy_value elimination verification
in the MoveOnlyObjectChecker to then fail. So this suggested that I needed to
move the verification from the object checkt to the address checker.

3. If we run the verification in the address checker, then the object checker
(which previously ran before the address checker) naturally needed to run
/before/ the address checker.
2023-02-08 13:29:39 -08:00
Michael Gottesman
48546fd6d3 [move-only] Move BorrowToDestructureTransform back into the Object Checker rather than as a separate pass.
The reason that I am doing this is I discovered that we emit worse quality
diagnostics since if we emit an error while running the borrow to destructure
transform, we want to do a complete cleanup to be safe (e.x.: converting
copy_value -> explicit_copy_value). This causes the object checker to then not
emit any additional diagnostics for other variables that were not impacted by
the BorrowToDestructureTransform, reducing the quality of diagnostics in a
significant way that isn't needed.
2023-01-31 15:24:17 -08:00
Michael Gottesman
c9ce3a9722 Merge pull request #63270 from gottesmm/pr-58e55bb70e30107d86e3c437c972c9f0adbce7b4
[move-only] Rather than calling the borrow to destructure transform from the MoveOnlyObjectChecker, make its own pass.
2023-01-27 17:18:21 -08:00
Michael Gottesman
96140ddfe9 [move-only] Rather than calling the borrow to destructure transform from the MoveOnlyObjectChecker, make its own pass.
This is a cleaner separation of concerns. The reason why I did not do this
originally is that I thought I would need to reuse this functionality in the
address checker, but this issue actually does not come up there since we project
the address and then load instead of load and then project.
2023-01-27 14:23:53 -08:00
Michael Gottesman
3a538282ff [consume-operator] Rename checker passes to have ConsumeOperator in the name to reduce confusion with MoveChecking passes.
Just trying to eliminate potential confusion.
2023-01-27 13:46:32 -08:00
Erik Eckstein
3645becada PassManager: infrastructure to disable or enable a specific instruction simplification
* for testing: add the option `-simplify-instruction=<instruction-name>` to only run simplification passes for that instruction type
* on the swift side, add `Options.enableSimplification`
2023-01-16 19:00:09 +01:00
Erik Eckstein
230c93df30 SIL Optimizer: add some SIL modification APIs
* `MutatingContext.notifyInvalidatedStackNesting` and `MutatingContext.needFixStackNesting`
* `MutatingContext.tryDeleteDeadClosure`
* `MutatingContext.erase(block:)`
* `Undef.get`
* `BasicBlock.moveAllInstructions`
* `BasicBlock.eraseAllArguments`
* `BasicBlock.moveAllArguments`
* `TermInst.replaceBranchTarget`
2023-01-16 19:00:09 +01:00
Erik Eckstein
cc68bd98c9 Swift Optimizer: rework pass context types and instruction passes
* split the `PassContext` into multiple protocols and structs: `Context`, `MutatingContext`, `FunctionPassContext` and `SimplifyContext`
* change how instruction passes work: implement the `simplify` function in conformance to `SILCombineSimplifyable`
* add a mechanism to add a callback for inserted instructions
2023-01-16 15:11:34 +01:00
swift-ci
ec2d7fc847 Merge pull request #62198 from nate-chandler/opaque-values/3/20221118
[AddressLowering] Don't end_borrow trivial args.
2022-11-29 17:07:24 -08:00
Erik Eckstein
096f02b3ef SILOptimizer: rename ANALYSIS macro to SIL_ANALYSIS
Avoids a conflict with clang's `ANALYSIS` macro.

Fixes a macro redefinition warning.
2022-11-21 19:22:15 +01:00
Nate Chandler
42aa21cc81 [NFC] Moved inlining printing to PassManager. 2022-11-18 16:29:51 -08:00
Erik Eckstein
1f4ac2b542 A few more deprecated iterator fixes
std::iterator is deprecated in C++17
2022-11-14 20:37:00 +01:00
Erik Eckstein
ef302ce4ac SILOptimizer: enable stack protection by default
The pass to decide which functions should get stack protection was added in https://github.com/apple/swift/pull/60933, but was disabled by default.

This PR enables stack protection by default, but not the possibility to move arguments into temporaries - to keep the risk low.
Moving to temporaries can be enabled with the new frontend option `-enable-move-inout-stack-protector`.

rdar://93677524
2022-11-11 17:14:08 +01:00
Joe Groff
9eefc2ec65 Merge pull request #61772 from jckarter/move-passes-after-closure-lifetime-fixup
SIL: Perform move-only diag passes after ClosureLifetimeFixup.
2022-10-28 10:26:36 -07:00
Joe Groff
394e6e42d7 SIL: Perform move-only diag passes after ClosureLifetimeFixup.
ClosureLifetimeFixup finalizes the lifetimes of nonescaping closures,
which allows us to analyze their captures as borrows and permit move-
only types to be captured by them.
2022-10-27 13:46:34 -07:00
Michael Gottesman
50163aad3b Make the option sil-stop-optzns-before-lowering-ownership work at -Onone.
Just wanted to look at -Onone codegen before ownership was lowered and realized
that this optimization did not work at -Onone.
2022-10-24 19:09:20 -07:00
Erik Eckstein
ed54253d29 SIL Optimizer: remove legacy C++ passes
They were used as a backup during the transition to Swift passes. Now they are not needed anymore.
2022-10-20 18:31:06 +02: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
Erik Eckstein
741c6c38df Swift Optimizer: add the ComputeSideEffects pass.
Computes the side effects for a function, which consists of argument- and global effects.
This is similar to the ComputeEscapeEffects pass, just for side-effects.
2022-10-05 07:38:11 +02:00
Erik Eckstein
e1c65bd1d6 Swift Optimizer: rename the ComputeEffects pass to ComputeEscapeEffects 2022-10-05 07:38:11 +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
Michael Gottesman
b1738c63c7 [move-only] Implement MoveOnlyDeinitInsertion that converts destroy_value of known deinit move only types to call the deinit directly.
NOTE: If one does not define a deinit on a move only type, if a destroy_value
lasts until IRGen time we will assert since I haven't implemented support in
IRGen for the destroy value witness for move only types. That being said, just
creating a deinit by adding to such a type:

```
deinit {}
```

is pretty low overhead for the experiments we want to use this for.
2022-09-20 15:19:31 -07:00
Egor Zhdan
710443ae6f [cxx-interop][SwiftCompilerSources] Use swift::SubstitutionMap instead of BridgedSubstitutionMap
rdar://83361087
2022-09-15 14:18:31 +01:00