Commit Graph

166 Commits

Author SHA1 Message Date
Michael Gottesman
85965ed202 [semantic-arc] Optimize more lifetime joining when a copy_value, destroy_value are in the same block.
Specifically the optimization that is being performed here is the elimination of
lifetimes that hand off ownership in between two regions of code. Example:

```
%1 = copy_value %0
...
destroy_value %0
...
apply %consumingUser(%1)
```

We really want to handle this case since it is a natural thing that comes up in
programs and will let me eliminate the *evil* usage of emitDestroyValueOperation
in TypeLowering without needing to modify huge amounts of tests.
2020-11-25 21:57:24 -08: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
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
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
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
6c3af65fb2 [ownership] Add a simple ForwardingOperand ADT and use it in a few places. 2020-11-08 23:55:10 -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
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
Slava Pestov
7bc5c5ecb1 SIL: Fix ownership verifier to handle some missing interior pointer projections
My upcoming SILGen change introduces more stores directly into
the result of a ref_element_addr or struct_element_addr in some
cases. Make sure we handle the failing combinations flagged by
the ownership verifier.
2020-10-10 20:04:50 -04:00
Michael Gottesman
d29bca5a53 [ownership] Extract out the computation of implicit uses for BorrowingOperands and InteriorPointerOperands into utilities on those classes.
I am currently working on updating SimplifyCFG for ownership. One thing that I
am finding that I need is the ability to compute the lifetime of a guaranteed
argument from a checked_cast_br/switch_enum in order to convert said
instructions to a br. The issue comes from br acting as a consuming (lifetime
ending) use of a borrowed value, unlike checked_cast_br/switch_enum (which are
treated like forwarding instructions). This means that during the conversion we
need to insert a begin_borrow on the value before the new br instruction and
then create an end_borrow at the end of the successor block's argument's
lifetime.

By refactoring out this code from the ownership verifier, I can guarantee that
said lifetime computation will always match what the ownership verifier does
internally preventing them from getting out of sync.
2020-08-31 11:54:58 -07:00
Michael Gottesman
5e36ae1c7c [sil] Add a forwarding cast called unchecked_value_cast.
Today unchecked_bitwise_cast returns a value with ObjCUnowned ownership. This is
important to do since the instruction can truncate memory meaning we want to
treat it as a new object that must be copied before use.

This means that in OSSA we do not have a purely ossa forwarding unchecked
layout-compatible assuming cast. This role is filled by unchecked_value_cast.
2020-07-09 21:14:32 -07:00
Michael Gottesman
142aa42f0d [semantic-arc-opts] Teach semantic-arc-opts how to handle tuples with multiple non-trivial operands.
<rdar://problem/63950481>
2020-06-05 19:56:09 -07:00
Michael Gottesman
3cb33ac7ef [semantic-arc-opts] Teach semantic-arc-opts how to handle structs with multiple non-trivial values.
Just like br inst, structs are phis in the ownership graph that one can induce
on top of the def-use graph. In this commit, I basically fill in the relevant
blanks in the ADT for such phis for struct so that the optimization for branches
is generalized onto structs.

<rdar://problem/63950481>
2020-06-03 20:01:39 -07:00
Andrew Trick
18c4cdf68e Fix an assert in OwnershipUtils.
checked_cast_br may take an additional operands for the source and
target types. I'm sure the compiler forgets to check this in many
places. In this case, it was just a harmless assert.

Fixes <rdar://61122253> Assertion failed:
(termInst->getNumOperands() == 1 && "Transformation terminators should only have single operands")
2020-04-09 23:30:10 -07:00
Michael Gottesman
e1a19e4173 [sil] Split library into subfolders, while still building as a single library still.
Specifically, I split it into 3 initial categories: IR, Utils, Verifier. I just
did this quickly, we can always split it more later if we want.

I followed the model that we use in SILOptimizer: ./lib/SIL/CMakeLists.txt vends
 a macro (sil_register_sources) to the sub-folders that register the sources of
 the subdirectory with a global state variable that ./lib/SIL/CMakeLists.txt
 defines. Then after including those subdirs, the parent cmake declares the SIL
 library. So the output is the same, but we have the flexibility of having
 subdirectories to categorize source files.
2020-03-30 11:01:00 -07:00