The existing implementation of this peephole was miscompiling when some arguments of a partial_apply were alloc_stack, because some of they could be dead before the apply which uses the partial_apply. To fix this problem I had to re-factor the implementation. Earlier we were looking for an apply first and then for a partial_apply it uses. With this patch, we do it the other way around: we fist look for a partial_apply and then peephole all apply instructions referring to it in one go. To solve the problem with "prematurely" dead alloc_stack arguments, we introduce new temporaries with a longer lifetime and copy the original arguments into them.
The test-cases are extended with more complex examples, including usage of existentials.
This fixes the compile-time crasher in test/Interpreter/currying_generics.swift
rdar://20868728
Swift SVN r28570
Fixes <rdar://problem/20044992> Swift: Generic functions called from
class methods with type parameter inferred to Self compiles, breaks
type system under optimization
If we don't prohibit specialization then we silently miscompile by
assuming a base class instead of the dynamic type.
It is unclear to me why GenericFunctionType did not inherit any
recursive type properties from it's arguments and result. However, it
I think it makes sense to propagate DynamicSelfType into
GenericFunctionType so I've broke with convention here.
Swift SVN r28541
We don't serialize their bodies because we only want them in the stdlib dylib.
Marking them Shared changes their visibility to hidden and the linker gets angry
when it tries to link their symbol in another object.
rdar://20907669
Swift SVN r28536
If the target ObjC type of a bridged cast is not the exact type being expected, but one of its superclasses, perform an upcast (e.g. upcast NSArray to NSObject).
rdar://20869055
Swift SVN r28319
- The cast optimiser was asserting if it could not find the _forceBridgeFromObjectiveC implementations in the Foundation module (where all stdlib bridged types reside). Now it checks the module being compiled as well.
- If a bridging function cannot be found, don't assert and bail out instead. After all, it is just an optimization and even if it cannot be applied, we should not crash.
This makes Swift :: 1_stdlib/ArrayBridge.swift compile with -O.
rdar://20845536
Swift SVN r28295
emit{StrongRelease,ReleaseValue} => emit{StrongRelease,ReleaseValue}AndFold.
Then introduce a new method emit{StrongRelease,ReleaseValue} that returns a
PointerUnion containing the increment to be deleted if it exists. This obviates
the need for the callback.
Swift SVN r27804
Previously, we relied on certain types not being passed in by the users of the
given function. Since I had a lot on my plate on the time and I knew it was safe
I left it in. Now I am going to be using this function in more places so it
needs to handle everything correctly.
rdar://19552593
Swift SVN r27748
This updates the performance inliner to iterate on inlining in cases
where devirtualization or specialization after the first pass of
inlining expose new opportunities for inlining. Similarly, in some cases
inlining exposes new opportunities for devirtualization, e.g. when we
inline an initializer and can now see an alloc_ref that allows us to
devirtualize some class_methods.
The implementation currently has some inefficiencies which increase the
swift compilation time for the stdlib by around 3% (this is swift-time
only, no LLVM time, so overall time does not grow by this much).
Unfortunately the (unchanged) current implementation of the core
inlining trades off improved estimates of code growth for increased
compile time, and that plays a part in why compile time increases as
much as it does. Despite this, I have some ideas on how to win some of
that time back in future patches.
Performance differences are mixed, and this will likely require some
further inliner tuning to reduce or remove some of the losses seen here
at -O. I will open radars for the losses.
Wins:
DeltaBlue 10.2%
EditDistance 13.8%
SwiftStructuresInsertionSort 32.6%
SwiftStructuresStack 34.9%
Losses:
PopFrontArrayGeneric -12.7%
PrimeNum -19.0%
RC4 -30.7%
Sim2DArray -14.6%
There were a handful of wins and losses at Onone and Ounchecked as
well. I'll review the perf testing output and open radars accordingly.
The new test case shows an example of the power of the closer
integration here. We are able to completely devirtualize and inline a
series of class_method applies (10 deep in this case, but in theory
substantially deeper) in a single pass of the inliner, whereas before we
could only do a single level per pass of inlining & devirtualization.
Swift SVN r27561
Even when we don't know for sure if a bridged cast would succeed, we still want to lower it to produce a more efficient code that does not performs conformance checks at run-time.
This is useful when performing casts optimizations as a guaranteed optimization.
Swift SVN r27377
It was producing a checked_cast_add_br, which took a metatype inst as it's argument, which is simply wrong, as it is not an address type. SILVerifier was complaining about it. Now we produce an equivalent peephole, but with a correct instruction sequence, which makes SILVerifier happy.
Swift SVN r27375
Sometimes, during intermediate optimization steps, the operands of produced checked_cast_addr_br instructions do not actually have address types.
Don't try to optimize further in such cases. Let the optimizer clean-up those instructions.
Swift SVN r27373
I noticed under Instruments that the bridged casts opts produced a code that was leaking in some cases. Therefore I took the change to re-visit the code and to clean-up the logic for insertion of retains and releases.
Swift SVN r27371
When casts optimizations were lowering bridged casts from ObjC to Swift, they were producing internally an intermediate cast from an ObjC type into the expected ObjC type of a bridged cast, before converting this expected ObjC type into a Swift type. In many cases, this resulted in a useless intermediate cast where both types were the same and such a cast would be eliminated afterwards. E.g.
unconditional_checked_cast A to B // where A is ObjC type and B is a Swift type
was lowered into:
unconditional_checked_cast A to B. _ObjectiveCType // Often useless as A is equal to B. _ObjectiveCType already.
unconditional_checked_cast B._ObjectiveCType to B
This small inefficiency is fixed now. This problem was no observable from outside the optimization pass, it just required additional processing, therefore there is no test-case.
Swift SVN r27370
If a conformance to _BridgedToObjectiveC is statically known, generate a more efficient code by using the newly introduced library functions for bridging casts.
This covers the casts resulting from SIL optimizations.
Tests are included. I tried to cover most typical casts from ObjC types into Swift types and vice versa and to check that we always generate something more efficient than a checked_cast or unconditional_checked_cast. But probably even more tests should be written or generated by means of gyb files to make sure that nothing important is missing.
The plan is to make the bridged casts SIL optimization a guaranteed optimization. Once it is done, there is no need to lower the bridged casts in a special way inside Sema, because they all can be handled by the optimizer in a uniform way. This would apply to bridging of Error types too.
With this change, no run-time conformance checks are performed at run-time if conformances are statically known at compile-time.
As a result, the performance of rdar://19081345 is improved by about 15%. In the past, conformance checks in this test took 50% of its execution time, then after some improvements 15% and now it is 0%, as it should be.
Swift SVN r27102
swift::clearBlockBody() in Local.cpp was popping instructions rather
than erasing them, resulting in leaking any instructions removed via
this function (which is reached via removeDeadBlock(), called throughout
SimplifyCFG).
Also tweak a couple comments and remove an assert that cannot fire.
Swift SVN r27018
Add more checks and logic into emitSuccessfulIndirectUnconditionalCast and emitSuccessfulScalarUnconditionalCast, so that its clients in sil-combine can be simplified by avoiding looking into special cases.
Swift SVN r26885
threaded into IRGen; tests to follow when that's done.
I made a preliminary effort to make the inliner do the
right thing with try_apply, but otherwise tried to avoid
touching the optimizer any more than was required by the
removal of ApplyInstBase.
Swift SVN r26747
Use existing machinery of the generic specializer to produce generic specializations of closures referenced by partial_apply instructions. Thanks to the newly introduced ApplyInstBase class, the required changes in the generic specializer are very minimal.
rdar://19290942
Swift SVN r26582
We no longer need or use it since we can always refer to the same bit on
the applied function when deciding whether to inline during mandatory
inlining.
Resolves rdar://problem/19478366.
Swift SVN r26534
When creating a new apply, we were copying the transparent bit from the
old apply, as well as the referenced function from the old apply. We
should just use the transparent bit from that referenced function.
Swift SVN r26384
Transforms :
%1 = alloc_ref $B
checked_cast_br [exact] %1 : $B to $B, bb1, bb2
into
br bb1(%1 : $B)
In case when source and destination types do no match, replace by a branch to the failure bb of the checked_cast_br.
Swift SVN r26275
TerminatorInsts. Now you can walk over the successor list of a terminator
and actually modify the SILSuccessor directly, allowing better CFG
transformations. NFC.
Swift SVN r26140
This is mostly a re-factoring. It creates a new helper class CastOptimizer which contains all the logic for performing type casts optimizations. This logic is a copy of the current logic from sil-combine and simplify-cfg. Those passes will become clients of this new helper class.
Swift SVN r26122
This enables high-level SIL optimizations to speculatively specialize loops into
'fast native swift array' loops vs standard array loops.
This commits adds two semantic calls to Arrays.swift.
@semantics("array.props.isNative")
func _getArrayPropertyIsNative() -> Bool
@semantics("array.props.needsElementTypeCheck")
func _getArrayPropertyNeedsElementTypeCheck() -> Bool
checkSubscript and getElement get extra arguments to pass in the result of above
function calls. This also allow us to communicate that an array that was made
mutable is always native. The array subscript getter is changed to use the
result of these new calls:
public subscript(index: Int) -> Element {
get {
let isNative = _getArrayPropertyIsNative()
let needsTypeCheck = _getArrayPropertyNeedsElementTypeCheck()
_checkSubscript(index, isNative)
return _getElement(index, isNative, needsTypeCheck)
}
mutableAddressWithPinnedNativeOwner {
_makeMutableAndUniqueOrPinned()
// When an array was made mutable we know it is a backed by a native
// array buffer.
_checkSubscript(index, true)
return (_getElementAddress(index),
Builtin.tryPin(Builtin.castToNativeObject(_buffer.owner)))
}
}
High-level SIL optimizations will now see a loop like this:
func f(inout a : A[AClass]) {
for i in 0..a.count {
let b = a.props.isNative()
.. += _getElement(a, i, b)
}
}
After proving that ‘a’ does not escape other than to known safe functions, the
optimizer hoists the array property calls out of the loop in a loop versioned
on the array property.
func f(inout a : A[AClass]) {
let b2 = a.props.isNative()
if (!b2) {
for i in 0..a.count {
.. += _getElement(a, i, false)
}
} else {
for i in 0..a.count {
let b = a.props.isNative
.. += _getElement(a, i, b)
}
}
}
rdar://17955309
Swift SVN r25698