Commit Graph

1615 Commits

Author SHA1 Message Date
Michael Gottesman
617a0279fc Merge pull request #37208 from gottesmm/canonicalize-ossa-lifetimes-sil-combine
[sil-combine] Use canonicalizeOSSALifetimes to eliminate unnecessary copies inserted due to RAUWing
2021-05-04 09:52:31 -07:00
Michael Gottesman
387806b9c6 [ownership] Add a simple helper wrapper called canonicalizeOSSALifetimes around CanonicalizeOSSALifetime that clean up extra copies inserted when RAUWing or promoting loads.
Based on code in CopyPropagation. It is assumed that the passed in set of defs
is unique and that all such defs were found by using
CanonicalizeOSSALifetime::getCanonicalCopiedDef(copy).
2021-05-01 16:01:45 -07:00
Michael Gottesman
3ab207c303 [copy-propagation] Finish plumbing through InstModCallbacks into one deletion utility that I missed. 2021-05-01 15:58:06 -07:00
Erik Eckstein
bd5d4276cd SILCombine: fix keypath optimization with optional chaining and classes
For optional chaining a swift_enum is created.
If the sub-projection is ending a begin_access in the some-branch, it also needs to be ended in the none-branch.

Fixes a compiler crash and/or a miscompile.

https://bugs.swift.org/browse/SR-14534
rdar://77224220
2021-04-30 21:47:42 +02:00
Pavel Prokofyev
f8baffafc8 [NFC][AutoDiff] Pass AutoDiffConfig by const ref. (#37074) 2021-04-27 13:40:18 -07:00
Michael Gottesman
7b55cbc669 [sil-optimizer] Make InstructionDeleter and related APIs to use an InstModCallback instead of a notification callback.
I recently have been running into the issue that many of these APIs perform the
deletion operation themselves and notify the caller it is going to delete
instead of allowing the caller to specify how the instruction is deleted. This
causes interesting semantic issues (see the loop in deleteInstruction I
simplified) and breaks composition since many parts of the optimizer use
InstModCallbacks for this purpose.

To fix this, I added a notify will be deleted construct to InstModCallback. In a
similar way to the rest of it, if the notify is not set, we do not call any code
implying that we should have good predictable performance in loops since we will
always skip the function call.

I also changed InstModCallback::deleteInst() to notify before deleting so we
have a default safe behavior. All previous use sites of this API do not care
about being notified and the only new use sites of this API are in
InstructionDeleter that perform special notification behavior (it notifies for
certain sets of instructions it is going to delete before it deletes any of
them). To work around this, I added a bool to deleteInst to control this
behavior and defaulted to notifying. This should ensure that all other use sites
still compose correctly.
2021-04-26 16:37:43 -07:00
Michael Gottesman
c3c2b84e48 [ownership] Change CanonicalOSSALifetime to use an InstModCallback.
This enables passes to use this as a utility that properly composes with how the
pass maintains its state. If an InstModCallback isn't passed in, we use the
default InstModCallback which should be cheap (always succeeding check for
nullptr + call inline default callback).
2021-04-21 22:09:55 -07:00
Andrew Trick
ed8b1b25dd Merge pull request #36970 from atrick/destructure-conversion
CanonicalizeOSSA: Destructure canonicalization and conslidate borrow scope support for destructure
2021-04-21 19:50:00 -07:00
Andrew Trick
340feb41df CanonicalOSSALifetime: rewrite consolidateBorrowScope
It now handles looking through forwarding consumes such as
destructures.

Expected to be NFC since borrow consolidation is still disabled by
default.

TODO: Write unit tests for various forwarding consumes in addition to
destructure.
2021-04-21 14:39:48 -07:00
Andrew Trick
3c045a85d5 CanonicalOSSALifetime: Add convertExtractToDestructure utility
struct_extract and tuple_extract do not belong in OSSA (except to
workaround certain extreme cases). They completely defeat
simplification that OSSA provides for optimizing owned lifetimes.

Copy propagation uses this utility to canonicalize owned values before
canonicalizing their lifetime.
2021-04-19 23:26:16 -07:00
Azoy
9ed732f0ab Introduce isDecl and getDeclType
fix enum logic issue

fix tests

guard against null types
2021-04-20 02:22:16 -04:00
Michael Gottesman
07b568d2d3 Merge pull request #36914 from gottesmm/pr-50f9fe327da8081f9050c5c892eb164aec334530
[ownership] Refactor out the composition type LoadOperation from CanonicalizeInstruction into OwnershipOptUtils.
2021-04-14 17:37:56 -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
Erik Eckstein
6ec788ff09 SIL: remove the SILOpenedArchetypesTracker
Instead, put the archetype->instrution map into SIlModule.

SILOpenedArchetypesTracker tried to maintain and reconstruct the mapping locally, e.g. during a use of SILBuilder.
Having a "global" map in SILModule makes the whole logic _much_ simpler.

I'm wondering why we didn't do this in the first place.

This requires that opened archetypes must be unique in a module - which makes sense. This was the case anyway, except for keypath accessors (which I fixed in the previous commit) and in some sil test files.
2021-04-14 08:36:10 +02:00
Erik Eckstein
b3a7792d1d Reinstate "SIL: add a StackList data structure with zero cost operations."
... with a fix for a non-assert build crash: I used the wrong ilist type for SlabList. This does not explain the crash, though. What I think happened here is that llvm miscompiled and put the llvm_unreachable from the Slab's deleteNode function unconditionally into the SILModule destructor.
Now by using simple_ilist, there is no need for a deleteNode at all.
2021-04-13 13:49:45 +02:00
Doug Gregor
e77a27e8ed [Concurrency] Introduce runtime detection of data races.
Through various means, it is possible for a synchronous actor-isolated
function to escape to another concurrency domain and be called from
outside the actor. The problem existed previously, but has become far
easier to trigger now that `@escaping` closures and local functions
can be actor-isolated.

Introduce runtime detection of such data races, where a synchronous
actor-isolated function ends up being called from the wrong executor.
Do this by emitting an executor check in actor-isolated synchronous
functions, where we query the executor in thread-local storage and
ensure that it is what we expect. If it isn't, the runtime complains.
The runtime's complaints can be controlled with the environment
variable `SWIFT_UNEXPECTED_EXECUTOR_LOG_LEVEL`:

  0 - disable checking
  1 - warn when a data race is detected
  2 - error and abort when a data race is detected

At an implementation level, this introduces a new concurrency runtime
entry point `_checkExpectedExecutor` that checks the given executor
(on which the function should always have been called) against the
executor on which is called (which is in thread-local storage). There
is a special carve-out here for `@MainActor` code, where we check
against the OS's notion of "main thread" as well, so that `@MainActor`
code can be called via (e.g.) the Dispatch library's
`DispatchQueue.main.async`.

The new SIL instruction `extract_executor` performs the lowering of an
actor down to its executor, which is implicit in the `hop_to_executor`
instruction. Extend the LowerHopToExecutor pass to perform said
lowering.
2021-04-12 15:19:51 -07:00
Arnold Schwaighofer
ddfdf4779d Revert "SIL: add a StackList data structure with zero cost operations." 2021-04-12 12:48:16 -07:00
eeckstein
e4f406d330 Merge pull request #36862 from eeckstein/remove-mv-result-nodes
SIL: remove the sub-classes of MultipleValueInstructionResult
2021-04-12 08:23:08 +02:00
Erik Eckstein
09755659a1 SIL: remove the sub-classes of MultipleValueInstructionResult
They are not really needed, because they don't contain any stored properties and for isa-checks we can check the parent instruction.
2021-04-11 19:14:34 +02:00
Erik Eckstein
0456d95cb0 SIL: Use StackList in BasicBlockWorklist and BasicBlockSetVector
plus: I moved both data structures into a separate header file.
2021-04-11 14:07:26 +02:00
Arnold Schwaighofer
d4246b904d hop_to_executor should have no affect if we inline a [noasync] apply into a non async function.
rdar://76230423
2021-04-08 07:41:13 -07:00
Andrew Trick
e9d0b08706 Add utilities to support OSSA update after running SSAUpdater.
This directly adds support to BasicBlockCloner for updating OSSA.

It also adds a much more general-purpose GuaranteedPhiBorrowFixup
utility which can be used for more complicated SSA updates, in which
multiple phis need to be created. More generally, it handles adding
nested borrow scopes for guaranteed phis even when that phi is used by
other guaranteed phis.
2021-03-18 00:14:13 -07:00
Andrew Trick
2f34014ffc Rescue the ValueLifetimeAnalysis utility.
This is a basic SSA-based liveness algorithm. It should just do what
it says. This change rescues the core logic from the nonsense that's
been hacked in. There are now two APIs:

(1) computeLifetimeBoundary (new) only does lifetime analysis.  It
provides a new API that always succeeds and provides the last use
points so clients can do the right thing based on the user. I need
this for OSSA utilities.

(2) computeFrontier (old) emulates the original API with a simplified
version of the original logic.

Next steps:

- replace the old API with a separate utility that computes destroy
  insertion points. Completely remove DeadEndBlocks from lifetime
  analysis, because it simply has nothing to do with liveness.

- Gradually migrate clients to either the new lifetime API provided
  here or the new destroy insertion API to be provided later.
2021-03-17 23:08:11 -07:00
Andrew Trick
97ec127d25 Lower and emit debug_value [poison].
OwnershipEliminator lowers destroy_value [poison] to debug_value
[poison].

IRGen overwrites all references in shadow copies with a sentinel value
in place of debug_value [poison].

Part 2/2: rdar://75012368 (-Onone compiler support for early object
deinitialization with sentinel dead references)
2021-03-12 19:33:23 -08:00
Andrew Trick
0b3027a37e Add destroy_value [poison] support to mandatory copy propagation.
Ensure that any object lifetime that will be shortened ends in
destroy_value [poison], indicating that the reference should not be
dereferenced (e.g. by the debugger) beyond this point.

This has no way of knowing whether the object will actually be
deallocated at this point. It conservatively avoids showing garbage to
debuggers.

Part 1/2: rdar://75012368 (-Onone compiler support for early object
deinitialization with sentinel dead references)
2021-03-12 19:32:55 -08:00
Erik Eckstein
85a5826d2c CastOptimizer: fix a small deficiency when optimizing checked_cast_addr_br instructions.
Handle destroy_addr of the destination. When replacing the cast, just remove such destroys.
In real world SIL there will always be a destroy_addr in the success-branch of the cast.
Not sure if this optimization could have ever kicked in for real world code.
2021-03-07 09:10:22 +01:00
Meghana Gupta
6e0e4dcb88 Merge pull request #36174 from meg-gupta/fixcastoptimizer
Fix verifier error in CastOptimizer
2021-03-05 21:52:27 -08:00
Slava Pestov
7ccc41a7b7 SIL: Preliminary support for 'apply [noasync]' calls
Refactor SILGen's ApplyOptions into an OptionSet, add a
DoesNotAwait flag to go with DoesNotThrow, and sink it
all down into SILInstruction.h.

Then, replace the isNonThrowing() flag in ApplyInst and
BeginApplyInst with getApplyOptions(), and plumb it
through to TryApplyInst as well.

Set the flag when SILGen emits a sync call to a reasync
function.

When set, this disables the SIL verifier check against
calling async functions from sync functions.

Finally, this allows us to add end-to-end tests for
rdar://problem/71098795.
2021-03-04 22:41:46 -05:00
Meghana Gupta
df93b5cba4 Fix verifier error in CastOptimizer
While removing an invalid cast and inserting traps, we are currently
inserting a store of undef to the cast destination and delete all
instructions after the cast except for dealloc_stack.
If the cast destination was an alloc_stack, the verifier could raise
an error saying the cast destination was initialized at the dealloc.

This PR deletes the store to undef, destroy_addr of the cast src,
and gets rid of the code that was retaining the dealloc_stack.
None of this is necessary anymore and the SIL is going to be legal
because we insert unreachable instruction.
2021-03-04 13:19:42 -08:00
Meghana Gupta
1f89d9ff89 Verify critical edges when -sil-verify-all is enabled 2021-03-03 23:45:56 -08:00
Andrew Trick
cb1ed89c9a [NFC] Add support for a mandatory-copy-propagation pass.
It is currently disabled so this commit is NFC.

MandatoryCopyPropagation canonicalizes all all OSSA lifetimes with
either CopyValue or DestroyValue operations. While regular
CopyPropagation only canonicalizes lifetimes with copies. This ensures
that more lifetime program bugs are found in debug builds. Eventually,
regular CopyPropagation will also canonicalize all lifetimes, but for
now, we don't want to expose optimized code to more behavior change
than necessary.

Add frontend flags for developers to easily control copy propagation:

-enable-copy-propagation: enables whatever form of copy propagation
 the current pipeline runs (mandatory-copy-propagation at -Onone,
 regular copy-propation at -O).

-disable-copy-propagation: similarly disables any form of copy
 propagation in the current pipelien.

To control a specific variant of the passes, use
   -Xllvm -disable-pass=mandatory-copy-propagation
or -Xllvm -disable-pass=copy-propagation instead.

The meaning of these flags will stay the same as we adjust the
defaults. Soon mandatory-copy-propagation will be enabled by
default. There are two reasons to do this, both related to predictable
behavior across Debug and Release builds.

1. Shortening object lifetimes can cause observable changes in program
   behavior in the presense of weak/unowned reference and
   deinitializer side effects.

2. Programmers need to know reliably whether a given code pattern will
   copy the storage for copy-on-write types (Array, Set). Eliminating
   the "unexpected" copies the same way at -Onone and -O both makes
   debugging tractable and provides assurance that the code isn't
   relying on the luck of the optimizer in a particular compiler
   release.
2021-03-02 22:19:47 -08:00
Andrew Trick
66752e9724 OSSA: Rewrite address cloning code to fix issues.
Generalize the AccessUseDefChainCloner in MemAccessUtils. It was
always meant to work this way, just needed a client.

Add a new API AccessUseDefChainCloner::canCloneUseDefChain().

Add a bailout for begin_borrow and mark_dependence. Those
projections may appear on an access path, but they can't be
individually cloned without compensating.

Delete InteriorPointerAddressRebaseUseDefChainCloner.

Add a check in OwnershipRAUWHelper for canCloneUseDefChain.

Add test cases for begin_borrow and mark_dependence.
2021-02-24 22:18:21 -08:00
Michael Gottesman
ad8e624bc9 Merge pull request #36141 from gottesmm/pr-fa4d423549d67732a05efc03383b0bcc8f15bd99
[sil-combine] Allow for storage casts to be cloned when rebasing an address def-use chain onto a new interior pointer
2021-02-24 16:03:52 -08:00
Michael Gottesman
658ce47636 [sil-combine] Allow for storage casts to be cloned when rebasing an address def-use chain onto a new interior pointer 2021-02-24 13:19:39 -08:00
Andrew Trick
ba9f52071b OSSA: simplify-cfg support for trivial block arguments.
Enable most simplify-cfg optimizations as long as the block arguments
have trivial types. Enable most simplify CFG unit tests cases.

This massively reduces the size of the CFG during OSSA passes.

Test cases that aren't supported in OSSA yet have been moved to a
separate test file for disabled OSSA tests,

Full simplify-cfg support is currently blocked on OSSA utilities which
I haven't checked in yet.
2021-02-23 22:47:59 -08:00
Andrew Trick
0c09d42447 Comment OSSA APIs makeNewValueAvailable & endLifetimeAtLeakingBlocks 2021-02-23 16:54:37 -08:00
eeckstein
841e4ee975 Merge pull request #35918 from eeckstein/diagnose-lifetime-issues
SILOptimizer: add a diagnostics pass to warn about lifetime issues with weak references.
2021-02-15 18:11:19 +01:00
Erik Eckstein
a17f8c2f3f SILOptimizer: add a diagnostics pass to warn about lifetime issues with weak references.
The DiagnoseLifetimeIssuesPass pass prints a warning if an object is stored to a weak property (or is weakly captured) and destroyed before the property (or captured reference) is ever used again.
This can happen if the programmer relies on the lexical scope to keep an object alive, but copy-propagation can shrink the object's lifetime to its last use.
For example:

  func test() {
    let k = Klass()
      // k is deallocated immediately after the closure capture (a store_weak).
      functionWithClosure({ [weak k] in
                            // crash!
                            k!.foo()
                          })
    }

Unfortunately this pass can only catch simple cases, but it's better than nothing.

rdar://73910632
2021-02-15 11:11:35 +01:00
Richard Wei
75088cde3e [AutoDiff] Mangle derivative vtable thunks.
Add the following mangling rule:
```
global ::= global generic-signature? 'TJV' AUTODIFF-FUNCTION-KIND INDEX-SUBSET 'p' INDEX-SUBSET 'r' // autodiff derivative vtable thunk
```

Resolves rdar://74340331.
2021-02-15 00:11:50 -08:00
swift-ci
d33c79edaf Merge pull request #35847 from rxwei/72666310-mangle-ad-thunks 2021-02-13 05:07:32 -08:00
Richard Wei
f9ddecf459 [AutoDiff] Mangle linear map self-reordering thunks and subset parameters thunks.
Add the following new mangling rules.
```
global ::= from-type to-type 'TJO' AUTODIFF-FUNCTION-KIND // autodiff self-reordering reabstraction thunk
global ::= from-type 'TJS' AUTODIFF-FUNCTION-KIND INDEX-SUBSET 'p' INDEX-SUBSET 'r' INDEX-SUBSET 'P' // autodiff linear map subset parameters thunk
global ::= global to-type 'TJS' AUTODIFF-FUNCTION-KIND INDEX-SUBSET 'p' INDEX-SUBSET 'r' INDEX-SUBSET 'P' // autodiff derivative function subset parameters thunk
```

Example:
```console
$s13TangentVector16_Differentiation14DifferentiablePQzAaDQy_SdAFIegnnnr_TJSdSSSpSrSUSP ---> autodiff subset parameters thunk for differential from @escaping @callee_guaranteed (@in_guaranteed A._Differentiation.Differentiable.TangentVector, @in_guaranteed B._Differentiation.Differentiable.TangentVector, @in_guaranteed Swift.Double) -> (@out B._Differentiation.Differentiable.TangentVector) with respect to parameters {0, 1, 2} and results {0} to parameters {0, 2}
$sS2f8mangling3FooV13TangentVectorVIegydd_SfAESfIegydd_TJOp ---> autodiff self-reordering reabstraction thunk for pullback from @escaping @callee_guaranteed (@unowned Swift.Float) -> (@unowned Swift.Float, @unowned mangling.Foo.TangentVector) to @escaping @callee_guaranteed (@unowned Swift.Float) -> (@unowned mangling.Foo.TangentVector, @unowned Swift.Float)
```

Resolves rdar://72666310 / SR-13508.

Also fix a bug in `AutoDiffFunction` mangling where the original may be a global that contains more than 1 node (rdar://74151229 / SR-14106).
2021-02-13 01:38:35 -08:00
Michael Gottesman
142c3bd1fc [simplify-cfg] Enable some simple opts during ownerships on br, cond_br that do not involve objects directly.
Just to reduce the size of the CFG.
2021-02-12 23:20:17 -08:00
Erik Eckstein
fe10f98cf0 SIL: rename the SILBitfield.h header file to BasicBlockBits.h
NFC
2021-02-12 11:15:55 +01:00
Meghana Gupta
8807d44211 Remove an llvm_unreachable in ownership rauw
This PR just removes an unnecessary error raised in
OwnershipLifetimeExtender::createPlusOneCopy.
We can ownership rauw a value inside the loop with a value outside the
loop. findJointPostDominatingSet correctly helps create control
equivalent copies inside the loop for replacement.
2021-02-10 15:48:22 -08:00
Erik Eckstein
65b03f9815 SILOptimizer: prevent illegal load forwarding of function references in global variables.
We cannot replace a load from a global let-variable with a function_ref, if the referenced function would violate the resilience rules.
That means if a non-public function_ref would be inlined into a function which is serialized.
2021-02-09 19:56:43 +01:00
Erik Eckstein
542a378436 SIL: add FunctionRefInst::getReferencedFunction()
If we know that we have a FunctionRefInst (and not another variant of FunctionRefBaseInst), we know that getting the referenced function will not be null (in contrast to FunctionRefBaseInst::getReferencedFunctionOrNull).

NFC
2021-02-09 19:56:43 +01:00
Andrew Trick
950bcd1f43 Merge pull request #35834 from atrick/fix-copyprop-reborrow2
Fix copy-propagation: bail-out on reborrows.
2021-02-08 21:15:18 -08:00
Varun Gandhi
caf1a55eea Merge pull request #35229 from mininny/switch-find-to-contains
[NFC] Replace uses of find(x) != end() idiom with contains(x) for StringRef and Set-like types
2021-02-08 13:57:43 -08:00
Andrew Trick
82c79b72ec Fix copy-propagation: bail-out on reborrows.
The simple logic for discovering pruned liveness and skipping over
nested borrow scopes assumed a dominating definition. This isn't the
case for arbitrary reborrows and would potentially lead to OSSA
verification errors.

Rather than add support to handle certain cases, bail-out on this
situation, which is rare enough that it isn't a priority to optimize
yet.

Noticed by inspection while working on the OSSA utilities.
2021-02-08 13:52:47 -08:00
Minhyuk Kim
e924cf6104 Replace usages of StringRef.find(Key) != StringRef::npos to StringRef.contains(Key) 2021-02-04 00:42:04 +09:00