Commit Graph

658 Commits

Author SHA1 Message Date
Michael Gottesman
0a16cc362a [move-only] Implement an initial version of the move only address checker.
Some notes:

1. I added support for both loadable/address only types.

2. These tests are based off of porting the move only object tests for inout,
vars, mutating self, etc.

3. I did not include already written tests for address only types in this
specific merge since I need to change us to borrow move only var like types.
Without that, we get a lot of spurious error msgs and the burden of writing that
is not worth it. So instead in a forthcoming commit where I fix that issue in
SILGen, I will commit the corresponding address only tests for this work.

4. I did not include support for trivial types in this. I am going to do
object/address for that at the same time.
2022-09-11 18:57:32 -07:00
Erik Eckstein
b2b44c0d83 Swift Optimizer: add the StackProtection optimization
It decides which functions need stack protection.

It sets the `needStackProtection` flags on all function which contain stack-allocated values for which an buffer overflow could occur.

Within safe swift code there shouldn't be any buffer overflows.
But if the address of a stack variable is converted to an unsafe pointer, it's not in the control of the compiler anymore.
This means, if there is any `address_to_pointer` instruction for an `alloc_stack`, such a function is marked for stack protection.
Another case is `index_addr` for non-tail allocated memory.
This pattern appears if pointer arithmetic is done with unsafe pointers in swift code.

If the origin of an unsafe pointer can only be tracked to a function argument, the pass tries to find the root stack allocation for such an argument by doing an inter-procedural analysis.
If this is not possible, the fallback is to move the argument into a temporary `alloc_stack` and do the unsafe pointer operations on the temporary.

rdar://93677524
2022-09-08 08:42:25 +02:00
Erik Eckstein
3e1ff0a5b7 IRGen: move the EnableStackProtector option from IRGenOptions to SILOptions.
... because we need it in the SIL pass pipeline, too.
Also, add Swift bridging for that option.
2022-09-08 08:42:24 +02:00
Michael Gottesman
dca78695f0 [move-only] Move the non-trivial move only type eliminator to the end of the guaranteed pipeline.
Still being careful with it. With time I want to move it back to IRGen.
2022-09-05 20:41:45 -07:00
Michael Gottesman
9d92d40060 [move-only] Move most move only passes earlier in the pass pipeline before Mandatory Inlining, right after DI. 2022-09-05 20:41:44 -07:00
Michael Gottesman
4dc6e6ecc4 [move-keyword] Remove old implementation.
By using the keyword instead of the function, we actually get a much simpler
implementation since we avoid all of the machinery of SILGenApply. Given that we
are going down that path, I am removing the old builtin implementation since it
is dead code.

The reason why I am removing this now is that in a subsequent commit, I want to
move all of the ownership checking passes to run /before/ mandatory inlining. I
originally placed the passes after mandatory inlining since the function version
of the move keyword was transparent and needing to be inlined before we could
process it. Since we use the keyword now, that is no longer an issue.
2022-09-04 01:19:01 -07:00
Meghana Gupta
bd295d73a6 Move OwnershipLowering to just before SimplifyCFG 2022-08-30 20:50:00 -07:00
Erik Eckstein
e090bc492a PassManager: cleanup the analysis-invalidation mechanism for swift passes
This fixes a bug with module passes.
2022-08-26 18:00:10 +02:00
Erik Eckstein
fbb694bcde Swift SIL: add bridging for witness and default witness tables 2022-08-24 17:55:02 +02:00
Erik Eckstein
7816513f0d Swift SIL: add bridging for vTables 2022-08-24 17:55:02 +02:00
Erik Eckstein
87f2f41d51 Swift Optimizer: add infrastructure for module passes.
To add a module pass in `Passes.def` use the new `SWIFT_MODULE_PASS` macro.
On the swift side, create a `ModulePass`.
It’s run function receives a `ModulePassContext`, which provides access to all functions of a module.
But it doesn't provide any APIs to modify functions.
In order to modify a function, a module pass must use `ModulePassContext.transform(function:)`.
2022-08-24 17:55:02 +02:00
Erik Eckstein
de6e539a0a Swift Optimizer: make the set's insert functions return a Bool.
Returning true if the element was not contained in the set before inserting
2022-08-24 17:54:46 +02:00
Erik Eckstein
beebd5a920 PassManager: add a invalidation kind for non-body function data
E.g. used if function effects are changed. This tells the passmanager that something changed, but no SIL-specific analysis have to be invalidated.
2022-08-24 17:54:46 +02:00
Michael Gottesman
6440e16440 [move-only] Move object checking before PredMemOpts.
Otherwise in certain cases due to load promotion, we emit incorrect errors. As
an example:

let x = ...
var y = x
print(y)

would show an error that x is consumed twice... which is incorrect.
2022-08-21 22:46:34 -07:00
Michael Gottesman
3e52007562 [builtin] Remove "unsafeGuaranteed" and related code since Unmanaged now has an Ownership SSA based implementation that works completely in SILGen.
This isn't used in the stdlib anymore as well.
2022-08-21 01:22:36 -07:00
Michael Gottesman
e65601f592 Rename MoveOnlyChecker -> MoveOnlyObjectChecker.cpp. 2022-08-16 16:19:55 -07:00
Erik Eckstein
a30a4adbf4 PassManager: fix a small bug with performance measurments
The check for invalidation was wrong, leading to not restore from the snapshot, which can result in wrong measurements.
2022-07-29 16:05:03 +02:00
Erik Eckstein
c9c4e10e0d SILOptimizer: add an option to profile and measure the runtime of optimization passes.
When enabling the option `-sil-opt-profile-repeat=<n>`, the optimizer runs passes n times and reports the total runtime at the end of the pass pipeline.
This is useful to profile a specific optimization pass with `sil-opt`.
For example, to profile the stack promotion pass:
```
  sil-opt -stack-promotion -sil-opt-profile-repeat=10000 -o /dev/null test.sil
```
2022-07-27 17:50:03 +02:00
Egor Zhdan
0e2d438c5b [cxx-interop][SwiftCompilerSources] Use llvm::StringRef instead of BridgedStringRef
rdar://83361000
2022-07-21 16:32:16 +01:00
Erik Eckstein
f4f2ca13f6 SIL Optimizer: add the OptimizeHopToExecutor in the late pipeline.
This is important to remove redundant `hop_to_executor` instructions after inlining.

rdar://95796233
2022-07-20 21:48:44 +02:00
Erik Eckstein
49a5b3ebdc Swift SIL: add ValueSet and InstructionSet utilities.
These sets are _much_ more efficient than `Set<Value>` and `Set<Instruction>` because they bridge to the efficient `NodeSet`.
Insertions/deletions are just bit operations.
2022-07-13 14:27:50 +02:00
Erik Eckstein
1cbea04103 run the TargetConstantFolding pass also at -Onone
This is important for performance diagnostics: it’s assumed that (non-generic) MemoryLayout constants do not need to create metadata at runtime. At Onone this is only guaranteed if the TargetConstantFolding pass runs.

rdar://94836837
2022-07-07 08:35:04 +02:00
Michael Gottesman
6a24087f90 Merge pull request #59611 from gottesmm/moveonly-rebase
[no-implicit-copy] Update SILGen/move checker to work with new patterns from copyable_to_moveonly and friends.
2022-06-28 13:45:15 -07:00
Erik Eckstein
f420468b27 SILOptimizer: add a pass to perform target specific constant folding.
TargetConstantFolding performs constant folding for target-specific values:

```
  MemoryLayout<S>.size
  MemoryLayout<S>.alignment
  MemoryLayout<S>.stride
```

Constant folding those expressions in the middle of the SIL pipeline enables other optimizations to e.g. allow such expressions in statically allocated global variables (done by the GlobalOpt pass).

The implementation requires to create a temporary IRGenModule, which is used to get actual constant sizes/alignments from IRGen's type lowering.

rdar://94831524
2022-06-23 22:16:42 +02:00
Michael Gottesman
2f9d67de18 [move-only] Add a new pass called MoveOnlyTypeEliminator that runs after move only checking.
This pass lowers moveonly-ness from the IR after we have finished move only
checking. The transform can be configured in two ways: such that it only handles
trivial types and such that it does trivial and non-trivial types. For ease of
use, I created two top level transforms (TrivialMoveOnlyTypeEliminator and
MoveOnlyTypeElimintor) that invoke the two behaviors by configuring the
underlying transform slightly differently.

For now, I am running first the trivial-only and then the all of the above
lowering. The trivial only pass will remain at this part of the pipeline
forever, but with time we are going to move the lower everything pass later into
the pipeline once I have audited the optimizer pipeline to just not perform any
work on move only types. That being said, currently we do not have this
guarantee and this patch at least improves the world and lets us codegen no
implicit copy code again.
2022-06-22 15:31:57 -07:00
Erik Eckstein
ec3d9dd9c7 Optimizer: add the ObjCBridgingOptimization to optimize ObjectiveC bridging operations.
Removes redundant ObjectiveC <-> Swift bridging calls.
Basically, if a value is bridged from ObjectiveC to Swift an then back to ObjectiveC again, then just re-use the original ObjectiveC value.

Also in this commit: add an additional DCE pass before ownership elimination. It can cleanup dead code which is left behind by the ObjCBridgingOptimization.

rdar://89987440
2022-06-08 22:51:57 +02:00
Meghana Gupta
fb0be6ad97 Run AddressLowering after DI and RawSILInstLowering 2022-05-31 20:49:29 -07:00
Erik Eckstein
3b43da9637 Swift Optimizer: improve ergonomics of Builder and PassContext
* split the PassUtils.swift file into PassContext.swift and Passes.swift
* rework `Builder` bridging allowing more insertion point variations, e.g. inserting at the end of a block.
* add Builder.create functions for more instructions
* add `PassContext.splitBlock`
* move SIL modification functions from PassContext to extensions of the relevant types (e.g. instructions).
* rename `Location.bridgedLocation` -> `Location.bridged`
2022-05-12 21:48:37 +02:00
Michael Gottesman
dd5d2f49ca Merge pull request #58410 from gottesmm/move-function-dbg-info-dataflow
[debug-info] Implement a global dataflow that propagates debug info for async vars and clones the dbg info after funclet points.
2022-05-06 14:35:52 -07:00
Michael Gottesman
640d5902e6 [debug-info] Implement a global dataflow that propagates debug info for async vars and clones the dbg info after funclet points.
The overall flow of the pass is:

1. We walk over the blocks summarizing the debug info instruction the blocks gen
as well as whether or not the block had an async funclet edge with in it.

2. We then perform a simple forward iterative optimistic dataflow using
intersection at merge points. At points where we find after merging that we have
a conflict and thus need to stop propagation, we insert a debug_value undef.

3. We then walk the CFG again visiting only blocks that we know had async
funclet edges. We then walk each said block from top to bottom starting with the
propagating gen information and updating as we go, dumping the current set of
debug_info we are tracking after each coroutine funclet boundary.

rdar://85020571
2022-05-05 14:16:51 -07:00
Arnold Schwaighofer
bcf24e4715 Eager specializer: Fix pre-specialization of imported code
We must no pre-specialize imported code (except if this was explicitly
called for by the importing module).

Therefore, don't pre-specialize `shared` definitions based on their
pre-specialization attributes.

Rather, only pre-specialize if the pre-specialization is called for
using a `target: "theFunctionToSpecialize"` parameter.

Run OnonePrespecializations before serialization so that module native functions
are not yet marked `shared` and can be identified as native.

rdar://92337361
2022-05-04 08:32:41 -07:00
Joe Groff
d2fad71328 Merge pull request #42589 from jckarter/begin-partial-apply-simplification-pass
[SIL] Initial work on PartialApplySimplification pass
2022-05-02 10:20:39 -07:00
Erik Eckstein
5d3339e9a3 Swift SIL: support for sub-pass bisecting: add PassContext.continueWithNextSubpassRun 2022-04-25 11:57:02 +02:00
Erik Eckstein
eea471fe99 add the ComputeEffects pass
The ComputeEffects pass derives escape information for function arguments and adds those effects in the function.
This needs a lot of changes in check-lines in the tests, because the effects are printed in SIL
2022-04-22 09:50:07 +02:00
Saleem Abdulrasool
218ef587e6 Revert "Merge pull request #42242 from eeckstein/escapeinfo"
This reverts commit c05e064cd8, reversing
changes made to c1534d5af9.

This caused a regression on Windows.
2022-04-21 20:33:37 -07:00
Joe Groff
85760d5348 SIL: Add a PartialApplySimplification pass.
This will turn `partial_apply` instructions into explicit box construction and
extraction code sequences. To begin with, recognize when a private function
is only used in partial applications and directly modify the function to be
usable as a closure invocation function. This simplifies the lowering in IRGen
and avoids generating a "partial application forwarder" thunk.
2022-04-21 12:47:44 -07:00
Erik Eckstein
700412b39e add the ComputeEffects pass
The ComputeEffects pass derives escape information for function arguments and adds those effects in the function.
This needs a lot of changes in check-lines in the tests, because the effects are printed in SIL
2022-04-21 08:45:08 +02:00
eeckstein
b952184adf Merge pull request #42191 from eeckstein/small-optimizer-tweaks
Some small optimizer tweaks
2022-04-06 09:25:09 +02:00
Nate Chandler
11e5c97f45 [SILOpt] Added flag to disable destroy hoisting.
It is on by default.  The default changes with the value of the
CopyPropagation setting.  But it can still be overridden.
2022-04-05 20:01:17 -07:00
Erik Eckstein
d8bf949582 BasicCalleeAnalysis: improve finding the actual called deinits of a destroy/release instruction
* C++: add a function `getDestructors(SILType type, bool isExactType)’: if the type is a final class or `isExactType` is true, then return the one and only destructor of that class.
* swift: add `getDestructor(ofExactType type: Type)` and `getIncompleteCallees`
* swift: remove `getDestructor` from the PassContext. The API of the `calleeAnalysis` can be used instead.
2022-04-05 20:33:23 +02:00
Erik Eckstein
eaeaa02415 PassManager: disable verification of analysis with -sil-verify-none 2022-03-31 10:12:32 +02:00
Michael Gottesman
1e2b94ec04 Merge pull request #41944 from gottesmm/add_initial_dominance_impl
[move-function] Add initial support for moved lets over async funclet edges
2022-03-22 09:33:53 -07:00
Andrew Trick
406aa86d2e Merge pull request #41557 from atrick/addrlower-update
Update and reimplement AddressLowering pass (for SIL opaque values).
2022-03-21 22:15:06 -07:00
Michael Gottesman
056132cca0 [move-function] Add a new pass that propagates debug_value [moved] into coroutine func-lets.
NOTE: debug_value [moved] appearing in the source code implies a _move was
used. So this will not effect current stable swift code.

This is just a first version of this that I am using to commit/bring up tests
for IRGen supporting a full dataflow version of this patch.

Big picture is that there is a bunch of work that is done in the LLVM level in
the coroutine splitter to work around communicating live variables in the
various coroutine func-lets. This logic is all done with debug.declare and we
would need to update that logic in the coroutine splitter to handle
debug.addr. Rather than do this, after some conversation, AdrianP and I realized
that we could get the same effect of a debug.declare by just redeclaring the
current live set of debug_value after each possible coroutine funclet start. To
do this in full generality, we need a full dataflow but just to bring this up we
initially perform a dominance propagation algorithm of the following sort:

1. We walk the CFG along successors. By doing this we guarantee that we visit
   blocks after their dominators.

2. When we visit a block, we walk the block from start->end. During this walk:

   a. We grab a new block state from the centralized block->blockState map. This
      state is a [SILDebugVariable : DebugValueInst].

   b. If we see a debug_value, we map blockState[debug_value.getDbgVar()] =
      debug_value. This ensures that when we get to the bottom of the block, we
      have pairs of SILDebugVariable + last debug_value on it.

   c. If we see any coroutine funclet boundaries, we clone the current tracked
      set of our block state and then walk up the dom tree dumping in each block
      any debug_value with a SILDebugVariable that we have not already
      dumped. This is maintained by using a visited set of SILDebugVariable for
      each funclet boundary.

The end result is that at the beginning of each funclet we will basically
declare the debug info for an addr.

This is insufficient of course for moves that are in conditional control flow,
e.x.:

```
let x = Klass()
if boolValue {
  await asyncCall()
  let _ = _move(x)
}
```

but this at least lets me begin to write tests for this in lldb using straight
line code and work out the rest of the issues in CodeGen using those tests.
2022-03-21 14:20:06 -07:00
Nate Chandler
7c1c9cea94 [SILOpt] Disabled DestroyHoisting. 2022-03-16 20:45:40 -07:00
Nate Chandler
8b99b9f77b [NFC] Exported printing query function.
Allow other compilation units to refer to isFunctionSelectedForPrinting
by declaring it extern.  Maybe at some point it might be nice to put
this into a header related to printing.
2022-03-15 10:51:37 -07:00
Andrew Trick
2907c61203 SILModule::hasLoweredAddress 2022-03-09 17:18:15 -08:00
Rintaro Ishizaki
7486cd1c21 [SwiftCompiler] Move common bridging facilities to 'Basic'
A preparation for AST/DiagnosticEngine bridging
2022-02-20 22:06:39 -08:00
Andrew Trick
7aeada1151 Merge pull request #41469 from atrick/disable-mandatory-copyprop
Disable MandatoryCopyPropagation.
2022-02-19 03:38:47 -08:00
Andrew Trick
4eb7351f4d Disable MandatoryCopyPropagation.
Mandatory copy propagation was primarily a stop-gap until lexcial
lifetimes were implemented. It supposedly made variables lifetimes
more consistent between -O and -Onone builds. Now that lexical
lifetimes are enabled, it is no longer needed for that purpose (and
will never satisfactorily meet that goal anyway).

Mandatory copy propagation may be enabled again later as a -Onone "
optimization. But that requires a more careful audit of the effect on
debug information.

For now, it should be disabled.
2022-02-18 17:29:04 -08:00