This method returns argument lists, not arguments! We should add in the future
an additional API that returns a flap mapped range over all such argument lists
to cleanup some of this code. But at least now the name is more accurate.
The `SILSuccessor` type does not permit copy or move initialization.
Direct initialization is required, however, GCC7 seems unable to cope
with the direct initialization of the array of non-copyable UDTs. Use a
`std::array` which can be direct-initialized. This enables building
with GCC7.
VS2015 had an issue with the deletion of an operator. Since VS2017 is
the minimum version that LLVM uses, we can assume that VS2017+ is in use
(_MSC_VER >= 1910). Clean up the now defunct workaround.
SIL type lowering erases DynamicSelfType, so we generate
incorrect code when casting to DynamicSelfType. Fixing this
requires a fair amount of plumbing, but most of the
changes are mechanical.
Note that the textual SIL syntax for casts has changed
slightly; the target type is now a formal type without a '$',
not a SIL type.
Also, the unconditional_checked_cast_value and
checked_cast_value_br instructions now take the _source_
formal type as well, just like the *_addr forms they are
intended to replace.
Fixes a potential real bug in the case that SinkAddressProjections moves
projections without notifying SimplifyCFG of the change. This could
fail to update Analyses (probably won't break anything in practice).
Introduce SILInstruction::isPure. Among other things, this can tell
you if it's safe to duplicate instructions at their
uses. SinkAddressProjections should check this before sinking uses. I
couldn't find a way to expose this as a real bug, but it is a
theoretical bug.
Add the SinkAddressProjections functionality to the BasicBlockCloner
utility. Enable address projection sinking for all BasicBlockCloner
clients (the four different kinds of jump-threading that use it). This
brings the compiler much closer to banning all address phis.
The "bugs" were originally introduced a week ago here:
commit f22371bf0b (fork/fix-address-phi, fix-address-phi)
Author: Andrew Trick <atrick@apple.com>
Date: Tue Sep 17 16:45:51 2019
Add SIL SinkAddressProjections utility to avoid address phis.
Enable this utility during jump-threading in SimplifyCFG.
Ultimately, the SIL verifier should prevent all address-phis and we'll
need to use this utility in a few more places.
Fixes <rdar://problem/55320867> SIL verification failed: Unknown
formal access pattern: storage
I found this to be really useful outside of the inliner since this is exactly
what I needed to ensure that borrowed values used by a begin_apply, have the
end_apply/abort_apply as uses. I am adding that in a forthcoming commit.
NFC.
We have already been forwarding ownership in terms of ValueOwnership and
OwnershipUtils, I just had not setup certain parts of the ownership utils to
recognize mark_dependence as forwarding of guaranteed values. We did not hit
this before since we have not had been late enough in the pipeline to get
mark_dependence on guaranteed values.
In the future, we want to move to mark_dependence only taking guaranteed
values. This is a first step in that direction that at the same time allows me
to enable ownership lowering after diagnostics sooner since fixing the bigger
issue would be a relatively medium sized project.
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711
This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:
- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
of the function to its concrete implementation. This will allow, for instance, a protocol
witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
to the protocol interface without relying on the pile of hacks that is the `witness_method`
protocol.
- A bool for whether the generic signature of the function is "implied" by the substitutions.
If true, the generic signature isn't really part of the calling convention of the function.
This will allow closure types to distinguish a closure being passed to a generic function, like
`<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
which will make it easier for us to differentiate the representation of those as types, for
instance by giving them different pointer authentication discriminators to harden arm64e
code.
This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.
This does bifurcate some existing APIs:
- SILFunctionType now has two accessors to get its generic signature.
`getSubstGenericSignature` gets the generic signature that is used to apply its
substitution map, if any. `getInvocationGenericSignature` gets the generic signature
used to invoke the function at apply sites. These differ if the generic signature is
implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
and results of the function. They now have two APIs to get that type. `getInterfaceType`
returns the unsubstituted type of the generic interface, and
`getArgumentType`/`getReturnValueType` produce the substituted type that is used at
apply sites.
While tightening the requirements of the debug info generator in
IRGenSIL I noticed that SILCloner didn't correctly transfer variable
debug info on alloc_box and alloc_stack instructions. In order to make
these mistakes easier to find I added an assertion to SILBuilder and
fixed all issues uncovered by that assertion, too.
The result is a moderate increase in debug info coverage in optimized code.
On stdlib/public/core/OSX/x86_64/Swift.o "variables with location"
increases from 60134 to 60299.
I am doing some refactoring on BranchPropagatedUser that is requiring me to work
a lot more with arguments and I found a need for this to avoid trafficing in
operand indices.
As part of this I also needed to write the helper getConditionOperand() to get
the underlying operand. I refactored the already preset getCondition() to use
this helper instead since it was just semantically that method + get operand's
value.
I need this for some refactorings I am doing around BranchPropagatedUser.
We already had ApplySite::getCallee() which just returned the value of the
operand. I refactored it to call this instead.
Specifically, this transforms:
builtin "generic_add"<Builtin.Vec4xInt32>(
->
builtin "add_Vec4xInt32"(
If we do not have a static overload for the type, we just leave the generic call
alone. If the generic builtin takes addresses as its arguments (i.e. 2x
in_guaranteed + 1x out), we load the arguments, evaluate the static overloaded
builtin and then store the result into the out parameter.
This mostly requires changing various entry points to pass around a
TypeConverter instead of a SILModule. I've left behind entry points
that take a SILModule for a few methods like SILType::subst() to
avoid creating even more churn.
For some time now we have had the API ValueBase::getSingleUserOfType<T>() but we
never implemented getUsersOfType<T>() using transform/filter iterators.
Since there wasn't a specific API, several incarnations of this API have been
created for BeginBorrow, LoadBorrow, BeginAccess.
In this commit, I introduce the API and use it to excise the redundant code in
those above mentioned 3 instructions.
DestroyHoisting moves destroys of memory locations up the control flow as far as possible.
Beside destroy_addr, also "store [assign]" is considered a destroy, because is is equivalent to an destroy_addr + a "store [init]".
The main purpose of this optimization is to minimize copy-on-write operations for arrays, etc. Especially if such COW containers are used as enum payloads and modified in-place. E.g.
switch e {
case .A(var arr):
arr.append(x)
self = .A(arr)
...
In such a case DestroyHoisting can move the destroy of the self-assignment up before the switch and thus let the array buffer only be single-referenced at the time of the append.
When we have ownership SIL throughout the pass pipeline this optimization will replace the current destroy hoisting optimization in CopyForwarding.
For now, this optimization only runs in the mandatory pipeline (but not for -Onone) where we already have ownership SIL.
SR-10605
rdar://problem/50463362
This provides a singular instruction for convert an unmanaged value to a ref,
then strong_retain it. I expanded the definition of UNCHECKED_REF_STORAGE to
include these copy like instructions. This instruction is valid in all SIL.
The reason why I am adding this instruction is that currently when we emit an
access to an unowned (unsafe) ivar, we use an unmanaged_to_ref and a strong
retain. This can look to the optimizer like a strong retain that can potentially
be optimized. By combining the two together into a new instruction, we can avoid
this potential problem since the pattern matching will break.
In analogy to the ownership verifier, the MemoryLifetimeVerifier checks the lifetime of memory locations.
It's based on MemoryLocations and MemoryDataflow, which are general utilities for analysing memory locations and calculating the lifetime of locations.
Memory locations are limited to addresses which are guaranteed to be not aliased, like @in/inout parameters or alloc_stack.
This flag is set by DefinitInitialization if the lifetime of the stored value is controlled dynamically.
If the flag is set, it's not (easily) possibly to statically calculate the lifetime of the stored value.
This improves on the previous situation:
- The request ensures that the backing storage for lazy properties
and property wrappers gets synthesized first; previously it was
only somewhat guaranteed by callers.
- Instead of returning a range this just returns an ArrayRef,
which simplifies clients.
- Indexing into the ArrayRef is O(1), which addresses some FIXMEs
in the SIL optimizer.