Commit Graph

122 Commits

Author SHA1 Message Date
swift-ci
07dbf4ef57 Merge pull request #35157 from atrick/remove-deadblocks 2020-12-20 17:07:35 -08:00
Andrew Trick
fe6e87913a Remove the default DEBlocks = nullptr argument from verifyOwnership.
Passing nullptr was undefined behavior because ReborrowVerifier takes
a reference to DeadEndBlocks.
2020-12-20 14:46:43 -08:00
Michael Gottesman
368f8acc4b [sil] Eliminate a confusing optional method result by changing type dependent operands to have OwnershipKind::None instead of returning Optional::None from Operand::getOperandOwnership().
This eliminates when talking about this API an ambiguity in between
Optional::None (the C++ ADT) and OwnershipKind::None (the ownership kind).
2020-12-18 19:33:27 -08:00
swift-ci
c326194945 Merge pull request #35041 from aschwaighofer/sil_verifier_keypath_with_some 2020-12-18 09:21:10 -08:00
Andrew Trick
f777e0a70e Convert OperandOwnership from an enum class to a struct enum. 2020-12-17 21:24:41 -08:00
Andrew Trick
b1dba2554e Introduce OperandOwnership to classify OSSA uses.
Migrating to this classification was made easy by the recent rewrite
of the OSSA constraint model. It's also consistent with
instruction-level abstractions for working with different kinds of
OperandOwnership that are being designed.

This classification vastly simplifies OSSA passes that rewrite OSSA
live ranges, making it straightforward to reason about completeness
and correctness. It will allow a simple utility to canonicalize OSSA
live ranges on-the-fly.

This avoids the need for OSSA-based utilities and passes to hard-code
SIL opcodes. This will allow several of those unmaintainable pieces of
code to be replaced with a trivial OperandOwnership check.

It's extremely important for SIL maintainers to see a list of all SIL
opcodes associated with a simple OSSA classification and set of
well-specified rules for each opcode class, without needing to guess
or reverse-engineer the meaning from the implementation. This
classification does that while eliminating a pile of unreadable
macros.

This classification system is the model that CopyPropagation was
initially designed to use. Now, rather than relying on a separate
pass, a simple, lightweight utility will canonicalize OSSA
live ranges.

The major problem with writing optimizations based on OperandOwnership
is that some operations don't follow structural OSSA requirements,
such as project_box and unchecked_ownership_conversion. Those are
classified as PointerEscape which prevents the compiler from reasoning
about, or rewriting the OSSA live range.

Functional Changes:

As a side effect, this corrects many operand constraints that should
in fact require trivial operand values.
2020-12-16 01:58:53 -08:00
John McCall
d874479290 Add builtins to initialize and destroy a default-actor member.
It would be more abstractly correct if this got DI support so
that we destroy the member if the constructor terminates
abnormally, but we can get to that later.
2020-12-10 19:18:53 -05:00
Arnold Schwaighofer
1d4497a599 SILVerifier: Fix keypath verification involving opaque return types
The SIL type of the keypath instruction is lowered in the function's
type expansion context, the various types involved in patterns are
unlowered AST types.

When verifying that the types matchup apply the type expansion to both
sides.

rdar://72134937
2020-12-10 13:52:08 -08:00
Michael Gottesman
743fdb12e5 [sil] Teach the verifier that an upcast of an address isn't a consuming use.
Just a missing case.
2020-12-09 18:04:55 -08:00
Andrew Trick
f92009da98 Remove SILArgumentConvention::Direct_Deallocating 2020-12-08 13:41:47 -08:00
Alexis Laferrière
b935c4a9f7 Merge pull request #34948 from xymus/skip-sil-verify-skipped-functions
[SIL] Don't verify functions that were skipped
2020-12-04 11:13:19 -08:00
Alexis Laferrière
a218281766 [SIL] Don't verify functions whose body was skipped 2020-12-03 17:49:40 -08:00
Slava Pestov
c133e13efd Merge pull request #34916 from slavapestov/with-unsafe-continuation
Concurrency: Implement withUnsafe[Throwing]Continuation
2020-12-03 11:18:49 -05:00
Michael Gottesman
09ae2ef071 [ownership] Centralize all info about SILInstruction forwarding in the SILInstruction class hierarchy itself.
This commit is doing a few things:

1. It is centralizing all decisions about whether an operand's owner instruction
or a value's parent instruction is forwarding in each SILInstruction
itself. This will prevent this information from getting out of sync.

2. This allowed me to hide the low level queries in OwnershipUtils.h that
determined if a SILNodeKind was "forwarding". I tried to minimize the amount of
churn in this PR and thus didn't remove the
is{Owned,Ownership,Guaranteed}Forwarding{Use,Value} checks. Instead I left them
alone but added in asserts to make sure that if the old impl ever returns true,
the neew impl does as well. In a subsequent commit, I am going to remove the old
impl in favor of isa queries.

3. I also in the process discovered that there were some instructions that were
being inconsistently marked as forwarding. All of the asserts in the PR caught
these and I fixed these inconsistencies.
2020-12-01 17:36:19 -08:00
Slava Pestov
a2dbdecdab SIL: Refactor get_async_continuation[_addr] to return a RawUnsafeContinuation 2020-12-01 20:04:09 -05:00
Michael Gottesman
63e43b6b2f [ownership] Rename BorrowingOperand::visitLocalEndScope{Instruction,Use}s(Operand *)
This originally trafficked in Instructions and for some reason the name was
never changed.

I also changed the result type to be a bool and added the ability for the passed
in closure to signal failure (and iteration stop) by returning false. This also
makes it possible to use visitLocalEndScopeUses in if statements which can be
useful.
2020-11-25 21:54:47 -08:00
Erik Eckstein
80d6e6c478 SILVerifier: don't dump the whole module in case of a verifier failure.
... because modules can be _very_ large.
Only dump the module if the new option -verify-dump-module-on-failure is set.
2020-11-19 16:10:35 +01:00
Erik Eckstein
5ccf3a852c SILVerifier: don't enforce that there must be an unreachable after a no-return apply.
This condition does not hold after each pass. It's only the case after running some cleanup-passes.
This verifier condition makes it impossible to bisect the optimization passes.
2020-11-19 16:08:22 +01:00
Michael Gottesman
c35ff33a1f [ownership] Add a subclass for all OwnershipForwarding instructions and fix the classof to the various ownership abstract classes so isa/dyn_cast work.
I think what was happening here was that we were using one of the superclass
classofs and were getting lucky since in the place I was using this I was
guaranteed to have single value instructions and that is what I wrote as my
first case X ).

I also added more robust checks tieing the older isGuaranteed...* APIs to the
ForwardingOperand API. I also eliminated the notion of Branch being an owned
forwarding instruction. We only used this in one place in the compiler (when
finding owned value introducers), yet we treat a phi as an introducer, so we
would never hit a branch in our search since we would stop at the phi argument.
The bigger picture here is that this means that all "forwarding instructions"
either forward ownership for everything or for everything but owned/unowned.

And for those listening in, I did find one instruction that was from an
ownership forwarding subclass but was not marked as forwarding:
DifferentiableFunctionInst. With this change, we can no longer by mistake have
such errors enter the code base.
2020-11-18 12:34:18 -08:00
Andrew Trick
c4abccb405 Merge pull request #34742 from atrick/fix-unchecked-ownership
Specify the unchecked_ownership_conversion instruction
2020-11-16 21:13:11 -08:00
Andrew Trick
ec1f3d926b Disable an assert in LinearLifetimeChecker pending design changes.
This assert does not make sense because consumingUses in some cases
only contains the destroying uses. Owned values may not be destroyed
because they may be converted to ValueOwnershipKind::None on all paths
reaching a return. Instead, this utility needs to find liveness first
considering all uses (or at least all uses that may be on a lifetime
boundary). We probably then won't need this assert, but I'm leaving
the FIXME as a placeholder for that work.

Fixes rdar://71240363.
2020-11-16 17:38:42 -08:00
Meghana Gupta
744767b57b Fix SILVerifier assert for witness_method with dynamic self type (#34738) 2020-11-16 10:00:06 -08:00
Meghana Gupta
91b5c4917f Allow a borrowed address to be passed as in_guaranteed arg in partial_apply [on_stack] only (#34736) 2020-11-16 09:59:14 -08:00
Michael Gottesman
a718e7d156 [ownership] Centralize the concept of isReborrow on BorrowingOperand.
A reborrow occurs when a Borrowing Operand ends the lifetime of a borrowed value
and propagates forward a new guaranteed value that continues the guaranteed
lifetime of the value.
2020-11-15 16:41:54 -08:00
Andrew Trick
976be60e01 Don't use report_fatal_error in the LoadBorrowImmutabilityChecker.
That prevents the SILVerifier from printing the context, making it
hard to quickly produce test cases from logs.

Instead, just return the failure status to the SILVerifier so it can
do its diagnostic thing.

An assert or llvm_unreachable would also be fine in addition to the
normal SILVerifier diagnostics, but I don't think that's needed here.
2020-11-13 16:34:42 -08:00
Andrew Trick
257b7e60b8 Specify the unchecked_ownership_conversion instruction.
All SIL instructions need their semantics specified in SIL.rst and their
constraints specified in SILVerifier.
2020-11-13 16:33:30 -08:00
Meghana Gupta
ce218b3f0a Fix LoadBorrowImmutabilityChecker for partial applies (#34658) 2020-11-11 21:34:52 -08:00
Michael Gottesman
58d4191470 [ownership] Try harder to make sure we do not propagate ownership info when ownership is disabled.
Specifically, I made it so that assuming our instruction is inserted into a
block already that we:

1. Return a constraint of {OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding}.
2. Return OwnershipKind::None for all values.

Noticed above I said that if the instruction is already inserted into a block
then we do this. The reason why is that if this is called before an instruction
is inserted into a block, we can't get access to the SILFunction that has the
information on whether or not we are in OSSA form. The only time this can happen
is if one is using these APIs from within SILBuilder since SILBuilder is the
only place where we allow this to happen. In SILBuilder, we already know whether
or not our function is in ossa or not and already does different things as
appropriate (namely in non-ossa does not call getOwnershipKind()). So we know
that if these APIs are called in such a situation, we will only be calling it if
we are in OSSA already. Given that, we just assume we are in OSSA if we do not
have a function.

To make sure that no mistakes are made as a result of that assumption, I put in
a verifier check that all values when ownership is disabled return a
OwnershipKind::None from getOwnershipKind().

The main upside to this is this means that we can write code for both
OSSA/non-OSSA and write code for non-None ownership without needing to check if
ownership is enabled.
2020-11-11 18:56:59 -08:00
Michael Gottesman
a294ab61ad [ownership] Eliminate OperandOwnershipKindMap in favor of OwnershipConstraint.
I also used this as a moment to clarify the lattice that related
ValueOwnershipKind and OwnershipConstraint.
2020-11-10 19:07:30 -08:00
Michael Gottesman
c026e95cce [ownership] Extract out SILOwnershipKind from ValueOwnershipKind into its own type and rename Invalid -> Any.
This makes it easier to understand conceptually why a ValueOwnershipKind with
Any ownership is invalid and also allowed me to explicitly document the lattice
that relates ownership constraints/value ownership kinds.
2020-11-10 14:29:11 -08:00
Michael Gottesman
f16c4ba203 [ownership] Convert ValueOwnershipKind to have an Invalid state instead of using optional.
At Andy's request. If it creates too much noise in covered switches, we may go
back to the original.
2020-11-10 10:34:44 -08:00
Michael Gottesman
93d1524cc0 Merge pull request #34634 from gottesmm/pr-88f0c52a3c1db5fb272598e5c5596ce3594d804c
[ownership] Make checked_cast_br, destructure_struct, and destructure_tuple real forwarding instructions
2020-11-09 15:28:45 -08:00
Michael Gottesman
c2a6f9aa5e [ownership] Fix assert to test the right thing semantically in the linear lifetime checker.
I think this assert was just testing the wrong thing. Specifically, it is trying
to say that either the given value has a consuming use or it is post-dominated
by dead end blocks.

Instead of checking that directly by using DeadEndBlocks::isDeadEnd(), it was
using a different empty check that caused the assert to actually semantically
say that:

A value must have a lifetime ending use *or* the dead end blocks analysis must
have found at least one block at all in the function that is reachable from a
function terminating terminator (e.x.: return).

This is clearly not the former and was causing the linear lifetime error to hit
this assert in certain cases.

<rdar://problem/70690127>
2020-11-09 11:49:53 -08:00
Andrew Trick
c2b13cdd51 Merge pull request #34635 from atrick/verify-critedge
Verify non-critical edges in OSSA
2020-11-09 08:59:08 -08:00
Michael Gottesman
d1b555f59a [ownership] Make destructure_{struct,tuple} true forwarding instructions instead of inferring from results/arguments. 2020-11-08 23:55:10 -08:00
Michael Gottesman
d74dbebf3b [ownership] Make checked_cast_br a true Ownership Forwarding inst instead of always inferring from the SILPhiArguments.
This is an analogous change to the previous change I just made to SwitchEnumInst.
2020-11-08 23:55:10 -08:00
Andrew Trick
0287a3d820 Verify no SIL critical edges.
There are multiple reasons this is needed.

1. Most passes do not perform CFG transformations. However, we often
need to split critical edges and remember to invalidate all SIL
analyses at the end of virtually every pass. This is very innefficient
and highly bug prone.

2. Many SIL analysis algorithms needs to reason about CFG
edges. Avoiding critical edges leads to far simpler and more efficient
designs when edges can be identified by blocks.

3. Handling block arguments on conditional branches create complexity
at the lowest level of the SIL interface. This complexity is difficult
to abstract over and bleeds until any algorithm that needs to reason
about phi operands. It's far easier to work with phis if we can easily
recover the phi operand with only a reference to the predecessor
block.

4. Attempting to preserve critical edges in high and mid level IR
blocks optimizations that otherwise have no business optimizing
branches. Branch optimization should always be defered to machine
level IR where the most relevant heuristics are employed to remove
unconditional branches. If code didn't need to be placed on a critical
edges, then a branch optimization can easily remove that code from the
critical edge.
2020-11-08 21:34:24 -08:00
Michael Gottesman
264955ccb3 [ownership] Convert switch_enum to be an ownership forwarding inst and store the forwarding ownership kind within it.
Previously, we always inferred the ownership of the switch_enum from its phi
operands. This forced us to need to model a failure to find a good
OperandOwnershipKindMap in OperandOwnership.cpp. We want to eliminate such
conditions so that we can use failing to find a constraint to mean that a value
can accept any value rather than showing a failure.
2020-11-08 20:32:20 -08:00
Michael Gottesman
642a993702 [ownership] Rename Operand::isConsumingUse() -> Operand::isLifetimeEnding().
This makes it clearer that isConsumingUse() is not an owned oriented API and
returns also for instructions that end the lifetime of guaranteed values like
end_borrow.
2020-11-08 13:23:17 -08:00
Michael Gottesman
b785a5f1d4 Merge pull request #34605 from gottesmm/pr-75f04ac2c27715c84382d9a9e4ca7c0337a3ce30
[ownership] Now that we allow reborrows eliminate isForwardingSubValue it is dead.
2020-11-06 15:18:10 -08:00
Michael Gottesman
e5c98ad2c7 [ownership] Now that we allow reborrows eliminate isForwardingSubValue it is dead. 2020-11-05 19:42:10 -08:00
Doug Gregor
9566d2e665 [Concurrency] Add a builtin to get the current task in an async function.
This introduces a new builtin, `getCurrentAsyncTask()`, that produces a
reference to the current task. This builtin can only be used within
`async` functions, and IR generation merely grabs the task argument
and packages it up.

The type of this function is `() -> Builtin.NativeObject`, because we
don't currently have a Swift-level representation of tasks, and can
probably handle everything through builtins or runtime calls.
2020-11-05 10:43:33 -08:00
Erik Eckstein
0accc022d5 [concurrency] SILVerifier: don't complain about async function pointers created in non-async functions
It's possible to materialize an async function pointer, e.g. with partial_apply, in a non-async function - as long as no async function is called.
2020-11-05 13:58:40 +01:00
Meghana Gupta
6c46841c26 Merge pull request #34438 from meg-gupta/reborrowverifier
[ownership] Add a new ReborrowVerifier
2020-11-02 19:55:10 -08:00
Meghana Gupta
288ef583e7 SILVerifier: async functions can be called from async functions only 2020-10-30 17:35:18 -07:00
Andrew Trick
fce43daab0 Merge pull request #34502 from atrick/simplifycfg-critedge
Rewrite SimplifyCFG trampoline removal to generalize it (avoid critical edges as a side-effect)
2020-10-30 12:06:25 -07:00
Meghana Gupta
601ea65b5d [ownership] Add a new ReborrowVerifier
This updates how we model reborrow's lifetimes for ownership verification.
Today we follow and combine a borrow's lifetime through phi args as well.
Owned values lifetimes end at a phi arg. This discrepency in modeling
lifetimes leads to the OwnershipVerifier raising errors incorrectly for
cases such as this, where the borrow and the base value do not dominate
the end_borrow:

bb0:
  cond_br undef, bb1, bb2
bb1:
  %copy0 = copy_value %0
  %borrow0 = begin_borrow %copy0
  br bb3(%borrow0, %copy0)
bb2:
  %copy1 = copy_value %1
  %borrow1 = begin_borrow %copy1
  br bb3(%borrow1, %copy1)
bb3(%borrow, %baseVal):
  end_borrow %borrow
  destroy_value %baseVal

This PR adds a new ReborrowVerifier. The ownership verifier collects borrow's
lifetime ending users and populates the worklist of the ReborrowVerifier
with reborrows and the corresponding base value.
ReborrowVerifier then verifies that the lifetime of the reborrow is
within the lifetime of the base value.
2020-10-29 20:46:37 -07:00
Andrew Trick
7d88d720b9 Add information to SILVerifier stack nesting diagnostic. 2020-10-29 15:25:20 -07:00
Andrew Trick
acc3398fed Add -allow-critical-edges flag.
Provide a mechanism to gradually migrate unit tests away from allowing
critical edges via -allow-critical-edges=false.

This will be the default in OSSA very soon, and will hopefully become
the default eventually for all SIL stages.

Note that not all required optimization pass changes have been
committed yet. I have pending changes in:
- SimplifyCFG
- SILCloner subclasses
- EagerSpecializer
- ArraySpecialization
- LoopUtils
- LoopRotate

There are multiple reasons we need to disallow critical edges:

1. Most passes do not perform CFG transformations. However, we often
need to split critical edges and remember to invalidate all SIL
analyses at the end of virtually every pass. This is very innefficient
and highly bug prone.

2. Many SIL analysis algorithms needs to reason about CFG
edges. Avoiding critical edges leads to far simpler and more efficient
designs when edges can be identified by blocks.

3. Handling block arguments on conditional branches create complexity
at the lowest level of the SIL interface. This complexity is difficult
to abstract over and bleeds until any algorithm that needs to reason
about phi operands. It's far easier to work with phis if we can easily
recover the phi operand with only a reference to the predecessor
block.

4. Attempting to preserve critical edges in high and mid level IR
blocks optimizations that otherwise have no business optimizing
branches. Branch optimization should always be defered to machine
level IR where the most relevant heuristics are employed to remove
unconditional branches. If code didn't need to be placed on a critical
edges, then a branch optimization can easily remove that code from the
critical edge.
2020-10-29 11:51:29 -07:00
Slava Pestov
360e406d3a SIL: Rename SILFunction::hasSelfMetadataParam()/getSelfMetadataArgument()
These are only for class types and are related to the usage of the
DynamicSelfType, so rename them to {has,get}DynamicSelfMetadata().
2020-10-23 21:35:11 -04:00