This reduces the diff in between -Onone output when stripping before/after
serialization.
We support load_borrow by translating it to the load [copy] case. Specifically,
for +1, we normally perform the following transform.
store %1 to [init] %0
...
%2 = load [copy] %0
...
use(%2)
...
destroy_value %2
=>
%1a = copy_value %1
store %1 to [init] %0
...
use(%1a)
...
destroy_value %1a
We analogously can optimize load_borrow by replacing the load with a
begin_borrow:
store %1 to [init] %0
...
%2 = load_borrow %0
...
use(%2)
...
end_borrow %2
=>
%1a = copy_value %1
store %1 to [init] %0
...
%2 = begin_borrow %1a
...
use(%2)
...
end_borrow %2
destroy_value %1a
The store from outside a loop being used by a load_borrow inside a loop is a
similar transformation as the +0 version except that we use a begin_borrow
inside the loop instead of a copy_value (making it even more efficient).
I am starting to use the linear lifetime checker in an optimizer role where it
no longer asserts but instead tells the optimizer pass what is needed to cause
the lifetime to be linear. To do so I need to be able to return richer
information to the caller such as whether or not a leak, double consume, or
use-after-free occurs.
Originally I wanted to try to use this code to optimize on ownership sil without
assuming verification passed (since the utility would check verification). In
the end, this was not useful.
A common pattern when working in ossa is the introduction of a copy for lifetime
reasons at a dominating point in a program with a single use that may not
post-dominate the use. This API gives a "tight lifetime" bound by returning the
blocks where the value needs to be destroyed to prevent leaks.
NOTE: I was not 100% sure if consume errors should still assert. It seems like a
double consume error would be user error, so an assert is probably fine.
Last week I split out operand ownership classification from the
SILOwnershipVerifier into the OperandOwnershipKindClassifier. Now move that
classifier code to another file so that SILOwnershipVerifier.cpp just consists
of the actual checker code. This makes sense since this type of classifier is
describing a separate structural aspect of SIL rather than something intrinsic
to the ownership verifier.
Keep in mind that this is not the final form of this classifier. Just an
incremental step forward.
NOTE: This is not the final form of how operand ownership restraints will be
represented. This patch is instead an incremental change that extracts out this
functionality from the ownership verifier as a pure refactor.
rdar://44667493
This does not eliminate the entrypoints on SILBuilder yet. I want to do this in
two parts so that it is functionally easier to disentangle changing the APIs
above SILBuilder and changing the underlying instruction itself.
rdar://33440767
I am doing this for two reasons:
1. I am going to use this in function signature opts to prove that a guaranteed
parameter is "consumed".
2. It puts the ownership verifier on a diet.
rdar://38196046