Do some preparations to split function signature into 3 function passes.
analyze() has become a dumping ground for code to analyze parameters and result.
Split it into 2 functions.
In many places, we're interested in whether a type with archetypes *might be* a superclass of another type with the right bindings, particularly in the optimizer. Provide a separate Type::isBindableToSuperclassOf method that performs this check. Use it in the devirtualizer to fix rdar://problem/24993618. Using it might unblock other places where the optimizer is conservative, but we can fix those separately.
This change includes an option on how IsLive is defined/computed. the ProjectionTree
can now choose to ignore epilogue releases and mark a node as dead if its only non-debug
user is epilogue release.
It can also mark a node as alive even its only user is epilogue release as before.
Imagine a case where one passes in an array and not access its owner
besides to release it. In such a case, we *do* want to be able to eliminate
that argument even though there is a release in the function epilogue.
This will help to get rid of the retain and release pair at the callsite. i.e.
the guaranteed paramter is elimininated.
rdar://21114206
This is safe because the closure is not allowed to capture the array according
to the documentation of 'withUnsafeMutableBuffer' and the current implementation
makes sure that any such capture would observe an empty array by swapping self
with an empty array.
Users will get "almost guaranteed" stack promotion for small arrays by writing
something like:
func testStackAllocation(p: Proto) {
var a = [p, p, p]
a.withUnsafeMutableBufferPointer {
let array = $0
work(array)
}
}
It is "almost guaranteed" because we need to statically be able to tell the size
required for the array (no unspecialized generics) and the total buffer size
must not exceed 1K.
If the copy_addr cannot release the destination then it behaves just like a load
followed by a store.
This allows us to stack promote protocol typed array literals.
protocol Proto { func at() -> Int }
func testStackAllocation(p: Proto) {
var a = [p, p, p]
for e in a {
print(e.at())
}
}
We were creating new uses of an argument just prior to erasing it from
the block argument list.
We need to replace references to that value in the side structure we
generate with references to the new value that we're replacing it with.
Fixes SR-884 / rdar://problem/25008398.
Improve when to bail while finding the final releases.
The ConsumedArgToEpilogueReleaseMatcher finds the final releases
in the following way.
1. If an instruction, which is not releaseinst nor releasevalue, that
could decrement reference count is found. bail out. This may well be the
real epilogue release.
2. If a release is found and the release that can not be mapped to any
@owned argument. bail as this release may well be the final release of
an @owned argument, but somehow rc-identity fails to prove that.
3. A release that is mapped to an argument, but we already has a release
that (partially or completely) overlaps with this release. This release
for sure is not the final release.
LSValue::reduce reduces a set of LSValues (mapped to a set of LSLocations) to
a single LSValue.
It can then be used as the forwarding value for the location.
Previously, we expand into intermediate nodes and leaf nodes and then go bottom
up, trying to create a single LSValue out of the given LSValues.
Instead, we now use a recursion to go top down. This simplifies the code. And this
is fine as we do not expect to run into type tree that are too deep.
Existing test cases ensure correctness.
This instruction creates a "virtual" address to represent a property with a behavior that supports definite initialization. The instruction holds references to functions that perform the initialization and 'set' logic for the property. It will be DI's job to rewrite assignments into this virtual address into calls to the initializer or setter based on the initialization state of the property at the time of assignment.
Previously SILDefaultWitnessTables only included "resilient" default
implementations, which are currently defined as those that appear at the
end of a protocol, after any requirements without defaults.
However, this was too inflexible. Instead, include all entries in the
SILDefaultWitnessTable, with invalid entries standing in for requirements
without defaults.
Previously, the minimum witness table size was a separate parameter, also
appearing in SIL syntax; now it can be calculated by looking at the entries
themselves. The getResilientDefaultEntries() method of SILDefaultWitnessTable
returns the same result as getEntries() did previously.
It's possible to construct programs where the optimization pass manager
will just continually execute, never making progress.
Add a check to the pass manager that only allows us to optimize a
limited number of functions with the function passes before moving on.
Unfortunately even the tiny test case that I have for this takes minutes
before we bail out with the limit I've set (which is not *that* much
bigger than the maximum that I saw in our build). I don't think it would
be prudent to add that test to the test suite, and I haven't managed to
come up with something that finishes in a more reasonable amount of time.
rdar://problem/21260480
This enables function signature handles a case of self-recursion.
With this change we convert 11 @owned return value to "not owned", while
we convert 179 @owned parameter to @guanrateed.
rdar://24022375
In theory we should be able to eliminate more loads if we run this after
the mem2reg that is after inlining. We aren't really relying heavily on
having promoted values like this prior to inlining.
Again, I see no significant performance delta, but this seems like the
best place to put this pass if we're only running it once per run of the
SSA passes.
Doing this earlier means that optimizations that are looking at SIL
values (rather than memory) have more opportunities earlier.
Minimal impact at the moment, but this may allow for removing some later
passes that are repeated.
More specifically, this handles a case of self-recursion.
With this change we convert 11 @owned return value to "not owned", while
we convert 179 @owned parameter to @guanrateed.
rdar://24022375
For forwarding on allocstacks, we can invalidate the forwable bit when we
hit the deallocate stack.
This helps compilation time as we do not need to propagate these bits down
to subsequent basic blocks.
Reinstates commit 0c2ca94ef7
With two bug fixes:
*) use after free asan crash
*) wrong check in ValueLifetimeAnalysis::isWithinLifetime
And some refactoring
The optimization should not proceed if there is more than one assignment to a let property inside an initializer.
In this case, the value of the let property is considered unknown.