Metatypes in SIL are trivial, until we conver them to objects (mainly for cases
where one converts the metatype to an object for use in objc). Thus these
conversion functions must be treated as returning an @owned value.
This is used in SILGen in a few different cases:
1. trivial -> non-trivial. This should have unowned semantics since one should
retain before use.
2. non-trivial -> trivial. This should have trivial semantics.
3. trivial -> trivial. This should have trivial semantics.
4. non-trivial -> non-trivial. This should have forwarding semantics.
This is the first verifier for SemanticSIL. The verifier is very simple and
verifies that given a SILValue V, V->getOwnershipKind() returns an ownership
kind compatible with all of V's user instructions.
This is implemented by adding a new method to SILInstruction:
SILInstruction::verifyOperandOwnership()
This method creates an instance of the visitor OwnershipCompatibilityUseChecker
and then has the instance visit this.
The OwnershipCompatibilityUseChecker is a SILInstructionVisitor that for a given
instruction verifies that the given SILInstruction's operand SILValue's produce
ValueOwnershipKind that are compatible with the SILInstruction. The reason why
it is implemented as a visitor is to ensure that a warning is produced if a new
instruction is added and a method on the OwnershipCompatibleUseChecker isn't
added.
Keep in mind that this is just the first verifier and the full verifier (that
also verifies dataflow) is built on top of it. The reason why this separate API
to the use verifier is exposed is that exposing the checker enables us to place
an assert in SILBuilder to diagnose any places where SIL ownership is violated
immediately when the violation occurs allowing for an easy debugging experience
for compiler writers. This assert is a key tool that I am going to be using to
make SILGen conform to the SIL Ownership Model.
Again, this will be behind the -enable-semantic-sil flag, so normal development
will be unaffected by this change.
rdar://29671437
We preserve the current behavior of assuming Any ownership always and use
default arguments to hide this change most of the time. There are asserts now in
the SILBasicBlock::{create,replace,insert}{PHI,Function}Argument to ensure that
the people can only create SILFunctionArguments in entry blocks and
SILPHIArguments in non-entry blocks. This will ensure that the code in tree
maintains the API distinction even if we are not using the full distinction in
between the two.
Once the verifier is finished being upstreamed, I am going to audit the
createPHIArgument cases for the proper ownership. This is b/c I will be able to
use the verifier to properly debug the code. At that point, I will also start
serializing/printing/parsing the ownershipkind of SILPHIArguments, but lets take
things one step at a time and move incrementally.
In the process, I also discovered a CSE bug. I am not sure how it ever worked.
Basically we replace an argument with a new argument type but return the uses of
the old argument to refer to the old argument instead of a new argument.
rdar://29671437
For a long time, we have:
1. Created methods on SILArgument that only work on either function arguments or
block arguments.
2. Created code paths in the compiler that only allow for "function"
SILArguments or "block" SILArguments.
This commit refactors SILArgument into two subclasses, SILPHIArgument and
SILFunctionArgument, separates the function and block APIs onto the subclasses
(leaving the common APIs on SILArgument). It also goes through and changes all
places in the compiler that conditionalize on one of the forms of SILArgument to
just use the relevant subclass. This is made easier by the relevant APIs not
being on SILArgument anymore. If you take a quick look through you will see that
the API now expresses a lot more of its intention.
The reason why I am performing this refactoring now is that SILFunctionArguments
have a ValueOwnershipKind defined by the given function's signature. On the
other hand, SILBlockArguments have a stored ValueOwnershipKind. Rather than
store ValueOwnershipKind in both instances and in the function case have a dead
variable, I decided to just bite the bullet and fix this.
rdar://29671437
I fixed a few things. Now I am finally hitting cases where we have
guaranteed/owned arguments, so I really need to do the SILGen work. But this was
a good first step.
rdar://29671437
This is just a first pass through. We know that builtins can only be used in the
standard library and trivially so only in non-generic contexts.
This means that anything that I marked trivial that isn't really will be caught
and there are very very few builtins that traffic in ownership, so I can sight
verify them.
rdar://29671437
The implementation will rely on a SILVisitor to ensure that we properly handle
all relevant cases. Right now, there are only stubs and we assert in all of
them.
rdar://29671437
These APIs work just like getParentBB does, namely they attempt to cast
self to either SILInstruction/SILArgument and if the instance is one of
those classes, using the APIs on said classes to get the relevant
Function or Module. If the dynamic casts fail, then nullptr is returned.
SILValue.h/.cpp just defines the SIL base classes. Referring to specific instructions is a (small) kind of layering violation.
Also I want to keep SILValue small so that it is really just a type alias of ValueBase*.
NFC.
In a bunch of use-cases we use stripSinglePredecessorArgs to eliminate this
case. There is no reason to assume that this is being done in the caller of
RCIdentity. Lets make sure that we handle this case here.
rdar://24156136
This fixes type punning issues with unsafeBitCast.
The optimizer is still too aggressive with UnsafePointer. To fix that,
we first need an explicit API for circumventing type safety
(rdar://23406272).
I should be able to fix the following regressions by migrating the
stdlib away from unsafeBitCast to unsafeReferenceCast (~2 weeks).
Slowdowns:
|.Benchmark.................|..Before.|...After.|.Speedup|
|.ArrayInClass..............|...49.00.|...78.00.|.-37.2%.|
|.Sim2DArray................|..471.00.|..549.00.|.-14.2%.|
|.PrimeNum..................|.1876.00.|.1980.00.|..-5.3%.|
Speedups:
|.Benchmark.................|..Before.|...After.|.Speedup|
|.HeapSort..................|.2962.00.|.2663.00.|..11.2%.|
|.StdlibSort................|.2672.00.|.2537.00.|...5.3%.|
We have to insert instructions that are operands *before* the instruction using
them as an operand.
Also fix a bug in the same code when looking through single predecessor basic
block arguments.
Add a testcase for all three cases.
rdar://23159379
UncheckedRefCastAddr does.
This cleans up the white-list used by ARC
optimization to be a bit more conservative.
I wasn't able to observe a change in behavior.
This fixes two issues that I ran into with the devirtualizer and also
paves the path to more simplification of the devirtualizer code.
Both issues are due to having a very liberal definition of what can be
considered an upcast.
In one case, we tunnel through an unchecked_ref_cast and then fail to
devirtualize because the source type is not a class
type (rdar://problem/20115523). We would be better off sticking to the
class type we started with.
In the other case, we tunnel through an unchecked_ref_bit_cast and this
results in an attempt to insert a checked_cast_br between unrelated
types (rdar://problem/20117782).
Swift SVN r25976
Currently, the pass just calls a local version of that function. After OzU, I
will enable the full pass (which is currently disabled behind a flag).
Swift SVN r21894
The cache is needed to ensure we do not run into compile time problems once we
start looking through Phi Nodes.
The analysis is currently disabled and just returns
SILValue::stripRCIdentityPreservingOps. I am going to thread it through the rest
of the passes that use that call. Then I am going to hide
stripRCIdentityPreservingArgs. Finally post OzU, I am going to enable the pass.
rdar://18300069
Swift SVN r21891