The old invalidation lattice was incorrect because changes to control flow could cause changes to the
call graph, so we've decided to change the way passes invalidate analysis. In the new scheme, the lattice
is replaced with a list of traits that passes preserve or invalidate. The current traits are Calls and Branches.
Now, passes report which traits they preserve, which is the opposite of the previous implementation where
passes needed to report what they invalidate.
Node: I tried to limit the changes in this commit to mechanical changes to ease the review. I will cleanup some
of the code in a following commit.
Swift SVN r26449
This can only happen in the closure specializer and the generic
specializer since all other specializations either copy the linkage of
the original function (function signature opts) or clone closures/thunks
which have shared linkage.
I put in a verifier check that makes sure we do not create shared
versions of these functions. The real problem has to do with serializing
these sorts of functions, but since we always serialize shared
functions, it makes sense to just ban it.
rdar://20082696
Swift SVN r26001
Before this commit the closure specializer was broken in the following ways:
1. We assumed that the closure was always passed in at +1. This meant that we
would leak the closure in guaranteed contexts.
2. For correctness reasons we were relying on the closure having only one user,
the apply to the function we were going to specialize.
This was important since we reused the retain of the partial apply's captured
arguments as the @owned retain for each of the captured variables at the
specialized callsite. If one has multiple such specializations then one needs to
insert additional retains for each capture for each specialization.
Since the partial_apply only had one use and consumed the captured arguments,
the partial_apply could always be eliminated and we could rely on the new
partial apply in the specialized function to consume the captured arguments. If
a partial_apply has multiple uses then there are extra retain, releases. We need
to be able to identify the set of post-dominating releases of the closure and
insert releases of the captured arguments at those points.
3. The captured parameters signature in the specialized function was not being
set appropriately to be +1. If it was passed in @guaranteed or unowned into the
closure's callee function, we would reuse that signature instead of changing it
to @owned. We /were/ balancing the ref counts correctly though as mentioned
before by reusing the retains resulting from the captured arguments being passed
into the partial apply.
Now the algorithm works as follows:
1. We are no longer attempting to perform a "move" of the closure into the
specialized function. Instead we now perform a "copy". This means that we have
two phases to our algorithm. First we "copy" the closure into the specialized
function and balance out all of the relevant reference counts for the original
closure and the closure's captured arguments.
2. Then we attempt to eliminate the original closure if it is dead.
For more information see the large comment at the top of ClosureSpecialization.
I also consolidated some tests as well.
rdar://19723829
Swift SVN r25052
This will have an effect on inlining into thunks.
Currently this flag is set for witness thunks and thunks from function signature optimization.
No change in code generation, yet.
Swift SVN r24998
Since this is just a refactoring, it should be NFC.
This is to fix a dumb bug where we will propagate closures if the
closure captures variables (i.e. partial_apply), but we will not
propagate closures that do not capture any values (i.e.
thin_to_thick_function).
a.map {
return $0 + v
}
But this will not be:
a.map {
return $0 + 1
}
This will also give us the flexibility in the future to support the
propagation of function pointers (at which point we should probably
rename this pass).
Swift SVN r24759
1. Eliminate unused variable warnings.
2. Change field names to match capitalization of the rest of the field names in the file.
3. Change method names to match rest of the file.
4. Change get,set method for a field to match the field type.
Swift SVN r24501
This reverts commit 2cba2a400037431e787a1422a6a5bb1a65433037.
I'm speculatively backing this out because the builds are in terrible
shape and I can't tell if this caused an issue.
I can't easily verify because my builds are now breaking for a
different reason.
Swift SVN r24272
I am starting to reuse manglings for different passes. I want to make sure that
when we reuse functions we actually get a function created by the same pass.
Swift SVN r23924
The underlying problem is that e.g. even if a method is private but its class is public, the method can be referenced from another module - from the vtable of a derived class.
So far we handled this by setting the SILLinkage of such methods according to the visibility of the class. But this prevented dead method elimination.
Now I set the SILLinkage according to the visibility of the method. This enables dead method elimination, but it requires the following:
1) Still set the linkage in llvm so that it can be referenced from outside.
2) If the method is dead and eliminated, create a stub for it (which calls swift_reportMissingMethod).
Swift SVN r23889
without a valid SILDebugScope. An assertion in IRGenSIL prevents future
optimizations from regressing in this regard.
Introducing SILBuilderWithScope and SILBuilderwithPostprocess to ease the
transition.
This patch is large, but mostly mechanical.
<rdar://problem/18494573> Swift: Debugger is not stopping at the set breakpoint
Swift SVN r22978
Now the SILLinkage for functions and global variables is according to the swift visibility (private, internal or public).
In addition, the fact whether a function or global variable is considered as fragile, is kept in a separate flag at SIL level.
Previously the linkage was used for this (e.g. no inlining of less visible functions to more visible functions). But it had no effect,
because everything was public anyway.
For now this isFragile-flag is set for public transparent functions and for everything if a module is compiled with -sil-serialize-all,
i.e. for the stdlib.
For details see <rdar://problem/18201785> Set SILLinkage correctly and better handling of fragile functions.
The benefits of this change are:
*) Enable to eliminate unused private and internal functions
*) It should be possible now to use private in the stdlib
*) The symbol linkage is as one would expect (previously almost all symbols were public).
More details:
Specializations from fragile functions (e.g. from the stdlib) now get linkonce_odr,default
linkage instead of linkonce_odr,hidden, i.e. they have public visibility.
The reason is: if such a function is called from another fragile function (in the same module),
then it has to be visible from a third module, in case the fragile caller is inlined but not
the specialized function.
I had to update lots of test files, because many CHECK-LABEL lines include the linkage, which has changed.
The -sil-serialize-all option is now handled at SILGen and not at the Serializer.
This means that test files in sil format which are compiled with -sil-serialize-all
must have the [fragile] attribute set for all functions and globals.
The -disable-access-control option doesn't help anymore if the accessed module is not compiled
with -sil-serialize-all, because the linker will complain about unresolved symbols.
A final note: I tried to consider all the implications of this change, but it's not a low-risk change.
If you have any comments, please let me know.
Swift SVN r22215
The pass does not support this properly and given where we are in the schedule
it makes no sense to each the closure specializer how to do this at this time.
Swift SVN r22130
It is possible to teach the closure specializer to handle these cases but given
where we are in the schedule it makes no sense to try to teach the optimizer how
to handle it.
Keep in mind though that we *will* handle the case where the function being
passed the closure has out parameters. This means that generic functions like
reduce will still be able to be specialized if the closure being passed in does
not have generics in it at the AST level. This implies that we will not handle
specialized closures with indirect results either which is unfortunate.
Swift SVN r22126
This creates a nice separation in between the analysis and the dynamic part of
the specialization. Thus gatherCallSites only returns call sites that are legal
to specialize.
This makes it easier to track where all of the correctness checks are.
Swift SVN r22049
There are many instructions which do not contribute to the actual size of a
function that getFunctionCost knows to ignore. Thus this is more accurate.
rdar://18143825
Swift SVN r22007
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 let the performance inliner inline a function even if the costs are too high.
This attribute is only a hint to the inliner.
If the inliner has other good reasons not to inline a function,
it will ignore this attribute. For example if it is a recursive function (which is
currently not supported by the inliner).
Note that setting the inline threshold to 0 does disable performance inlining at all and in
this case also the @inline(__always) has no effect.
Swift SVN r21452
PerfTests -----
Before
Totals,54,93821,93821,93821,0,0
Totals,54,86755,86755,86755,0,0
After
Totals,54,93610,93610,93610,0,0
Totals,54,85780,85780,85780,0,0
We may be able to tune BoostFactor for closure in PerformanceInliner.
Swift SVN r21312
If we have function A calls function B with a closure C
func A {
B(...) {
// closure C
}
}
and the inliner decides to not inline B into A, it may be beneficial to generate
a specialized version of B to have
func A {
B_spec_with_C(..., arguments_to_closure_C)
}
SILCombine will optimize apply of partial_apply that are both in B_spec_with_C.
Then inliner can inline the closure to B_spec_with_C.
For profitability, we check the relative size of the callee B and the closure C.
We also check hotness of the callsite to B in A and callsites to the closure
inside B. For now, if closure is called inside a loop, we think it is
profitable.
I will add this to the pass manager in a follow-up patch.
rdar://16569736
Swift SVN r21216