We can't just recursively process types without caching. Instead mark a type as
safe before we recurse and reset this assumption if we proved otherwise on the
recursive traversal.
rdar://20132313
Swift SVN r26048
Previously this was scattered in various places . Now we have a simple model that
all CallGraphEdges, CallGraphNodes, and CallGraphSCCs are owned by the CallGraph
since they are allocated by the CallGraph's BumpPtrAllocator.
This additionally fixes a problem where we were calling delete on SCC's owned by
the BumpPtrAllocator.
Swift SVN r25522
This is currently disabled by default since this verification trips on
ToT when I checked a few days ago.
The current checks that are performed are:
1. For every (SILFunction, CallGraphNode) pair FuncPair in the SILFunction to
CallGraphNode map check that:
a. FuncPair.first is a SILFunction in the current module.
b. FuncPair.first is the SILFunction inside the CallGraphNode FuncPair.second.
c. All CallGraphEdges mapped to FuncPair.second have ApplyInsts which are in
the SILFunction FuncPair.first.
2. For every pair (ApplyInst, CallGraphEdge) ApplyPair in the Apply to
CallGraphEdge map, check that:
a. ApplyPair.second.getCallSite() == ApplyPair.first.
b. ApplyPair.first->getFunction() is in the SILFunction to
CallGraphNode map and the CallGraphEdge for ApplyPair is one of
CallSiteEdges in the mapped to CallGraphNode.
<rdar://problem/19944399>
Swift SVN r25520
This makes it easy to use the callgraph to determine what the Apply
actually calls instead of attempting to ascertain it in an adhoc
manner. This allows for the call graph analysis to be used as the one
point of truth for determing what an apply inst can call.
Swift SVN r25516
Currently no passes implement this, but I am going to add support to the
callgraph. I just ran into a callgraph bug that this would have helped
to catch.
rdar://19930214
Swift SVN r25514
Small clean-up to try to improve on the clarity of the call graph code.
I think this is an overall improvement although there is still some
clunky naming that could be improved in the future.
Swift SVN r25492
The memory allocation of DenseSet had a significant contribution to the compile time.
This change reduces the time of runSILOptimizationPasses by ~25% in a stdlib build => ~2s faster.
Swift SVN r25373
One common problem in swift code is the "reforming enum problem". What
happens here is that we have some enum %0 : $Optional<T> and we break it
apart and reform it as a new enum as in the following:
bb9:
...
switch_enum %0 : $Optional<T>, #Optional.None: bb10,
#Optional.Some: bb11
bb10:
%1 = enum $Optional<U>, #Optional.None
br bb12(%1 : $Optional<U>)
bb11:
%2 = some_cast_to_u %0 : ...
%3 = enum $Optional<U>, #Optional.Some, %2 : $U
br bb12(%3 : $Optional<U>)
bb12(%4 : $Optional<U>):
retain_value %0 : $Optional<T> // id %5
release_value %4 : $Optional<U> // id %6
We really would like to know that a retain on %4 is equivalent to a
retain on %0 so we can eliminate the retain, release pair. To be able to
do that safely, we need to know that along all paths %0 and %4 either:
1. Both refer to the same RCIdentity directly. An example of this is the
edge from bb11 -> bb12).
2. Both refer to the "null" RCIdentity (i.e. do not have a payload). An
example of this is the edge from bb10 -> bb12.
Only in such cases is it safe to match up %5, %6 and eliminate them. If
this is not true along all paths like in the following:
bb9:
...
cond_br %foo, bb10, bb11
bb10:
%1 = enum $Optional<U>, #Optional.None
br bb12(%1 : $Optional<U>)
bb11:
%2 = some_cast_to_u %0 : ...
%3 = enum $Optional<U>, #Optional.Some, %2 : $U
br bb12(%3 : $Optional<U>)
bb12(%4 : $Optional<U>):
retain_value %0 : $Optional<T> // id %5
release_value %4 : $Optional<U> // id %6
then we may have that %0 is always non-payloaded coming into bb12. Then
by matching up %0 and %4, if we go from bb9 -> bb11, we will lose a
retain.
Perf Changes:
TITLE..................OLD...........NEW...........NEW/OLD
LevenshteinDistance....1398195.00....1177397.00....0.84
Memset.................26541.00......23701.00......0.89
CaptureProp............5603.00.......5031.00.......0.90
ImageProc..............1281.00.......1196.00.......0.93
InsertionSort..........109828.00.....104129.00.....0.95
StringWalk.............6813.00.......7456.00.......1.09
Chars..................27182.00......30443.00......1.12
The StringWalk, Chars are both reproducible for me. When I turn back on parts of
the recursion (I took the recursion out to make this change more conservative),
the Chars regression goes away, but the StringWalk stays. I have not had a
chance to look at what is going on with StringWalk.
rdar://19724405
Swift SVN r25339
Even though there is only one "return" from a SILFunction, there may be multiple
non-failure exits via no return functions. findAllNonFailureExitBBs
The verifier currently enforces that all no-return function applications must be
immediately followed by an unreachable. Thus to identify all such functions, we
must just visit all unreachables and visit the previous instruction of the
unreachable. If we don't have an apply in such case, then we must be in a
failure code path.
This code attempts to identify all ways of exiting a function in a non-failure
code path. Thus it places into the result vector the return from the BB and all
no-return function applications that it can not identify as a "failure"
function. The function ignores any paths that it identifies as failure paths.
Failure functions will be identified in the future via an @semantic tag but for
now we just check for functions with the appropriate "fatal error" suffix as we
do in the ARC optimizer.
I am going to use this in the closure specializer to insert releases for
"copied" closures that were originally passed in @guaranteed. Since the closure
was passed in originally @guaranteed there will be no matching -1 unless we
insert it ourselves.
Swift SVN r25051
This utility attempts to delete dead closures with a set of
post-dominating releases using the infrastructure from
getFinalReleasesForValue.
It currently only will eliminate closures that only have retain, release
uses and a final post-dominating release set.
The reason why we need the final post-dominating release set is so that
we can release any captured variables at the points where we would have
deallocated the release. This is b/c captured variables are passed in at
+1 to partial apply.
Swift SVN r25050
This is refactored code from AllocBoxToStack with some small forward
looking changes. The user passes in a ReleaseTracker object that via a
closure decides what users are acceptable. I am going to use this in
closure specialization to remove dead closures.
The main limitation currently is that the code:
1. Assumes that the user deals with any issues relating to whether or
not the value is local.
2. Only visits the direct users of the value instead of visiting the
users recursively. This is safe for my uses now since I will only accept
users that are retains or releases. These have no uses.
The reason why I am leaving in these limitations is I am trying to limit
the amount of changes to the code.
Swift SVN r25048
I am going to use this in closure specialization to remove dead closures. We
should refactor the SILCombine dead closure removal to use this code path as
well.
Additionally, we should change the valueMayBeCaptured infrastructure to take a
struct like we do in LLVM so we can ignore casts and other things like that
additionally by injecting the logic to do so via the struct.
But that is for another day.
Swift SVN r25007
We specifically only handle cases of functions that are not visible externally
and for whom all function_refs to the function only have apply inst users.
<rdar://problem/19137435>
Swift SVN r23714
optimizer freezing releases in the epilogue of functions that match to
SILArguments. This allows us to treat all such SILArguments throughout the
entire function as having a post dominating release.
<rdar://problem/18923030>
Swift SVN r23253
This adds an analysis to the compiler that identifies types that are may store
to memory on destruction.
It adds a compiler known protocol _DestructorSafeContainer that allows the
standard library to identify containers whose destructor's memory effects
depends strictly on the type parameters of the container.
Array<T> : _DestructorSafeContainer {} may not store to memory during
destruction if the bound T is a type that does not store to memory on
destruction.
This is needed to deduce that for example Array<Array<Int>> is does not store to
memory on destruction (e.g during a call to release).
rdar://18940376
Swift SVN r23242
Given a function F, this utility class attempts to match up owned arguments with
releases in the epilogue of the function.
I am refactoring this from FunctionSigOpts so I can use it in the ARC optimizer.
<rdar://problem/18923030>
Swift SVN r23219
canInstUseRefCountValues should have always been named
canInstNotUseRefCountValues. I don't remember how it get renamed as such. Even
though it is a little weird to have a "canNever" in a function name, it makes
sense here to contrast it with canUseValue which returns if a specific user can
use a ptr in a way that requires the ptr to be alive. This in contrast says that
a user can never use a ptr in a manner where the ptr must be alive. I.e. this is
a universal quantifier.
Swift SVN r22961
llvm::Optional lives in "llvm/ADT/Optional.h". Like Clang, we can get
Optional in the 'swift' namespace by including "swift/Basic/LLVM.h".
We're now fully switched over to llvm::Optional!
Swift SVN r22477
This is important since to be more aggressive we are ignoring incoming values
that are no-payload enums since as far as we are concerned they do not matter
since retains, releases on those values are no-ops.
Swift SVN r21932
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
This follows the model of dominance info and allows me to create reachability
methods on SILBasicBlock without creating dependencies from swiftSIL to
swiftSILAnalysis.
Swift SVN r21866
This will hopefully make it clearer as we onboard people that
SimplifyInstruction should not add instructions to the IR by making it clearer
that it is an analysis, not a pass.
Swift SVN r21752