* rename "Name" to "Description" in the pass definition, because it's not really the pass name, but the description of a pass
* remove the getName() from Transforms (which actually returned the description of a pass)
* in debug printing, print the pass ID and not the pass description. It makes it easier to correlate the debug output to the actual pass implementation.
* remove the iteration numbering in the pass manager, because we only run a single iteration anyway.
This commit is mostly refactoring.
*) Introduce a new OptimizationMode enum and use that in SILOptions and IRGenOptions
*) Allow the optimization mode also be specified for specific SILFunctions. This is not used in this commit yet and thus still a NFC.
Also, fixes a minor bug: we didn’t run mandatory IRGen passes for functions with @_semantics("optimize.sil.never")
In the crash output 'While running pass #x SILFunctionTransform "T" on SILFunction "@F".' we printed the previous function which was handled by the pass instead of the current one.
introduce a common superclass, SILNode.
This is in preparation for allowing instructions to have multiple
results. It is also a somewhat more elegant representation for
instructions that have zero results. Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction. Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.
A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.
Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
This patch implements collection and dumping of statistics about SILModules, SILFunctions and memory consumption during the execution of SIL optimization pipelines.
The following statistics can be collected:
* For SILFunctions: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, duration of a pass
* For SILModules: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, the number of SILFunctions, the amount of memory used by the compiler, duration of a pass
By default, any collection of statistics is disabled to avoid affecting compile times.
One can enable the collection of statistics and dumping of these statistics for the whole SILModule and/or for SILFunctions.
To reduce the amount of produced data, one can set thresholds in such a way that changes in the statistics are only reported if the delta between the old and the new values are at least X%. The deltas are computed as using the following formula:
Delta = (NewValue - OldValue) / OldValue
Thresholds provide a simple way to perform a simple filtering of the collected statistics during the compilation. But if there is a need for a more complex analysis of collected data (e.g. aggregation by a pipeline stage or by the type of a transformation), it is often better to dump as much data as possible into a file using e.g. -sil-stats-dump-all -sil-stats-modules -sil-stats-functions and then e.g. use the helper scripts to store the collected data into a database and then perform complex queries on it. Many kinds of analysis can be then formulated pretty easily as SQL queries.
A pass has an ID (C++ identifier), Tag (shell identifier),
and Name (human identifier).
Command line options that identify passes should obviously be compatibile with
with the pass' command line identifier. This is also what the user is used to
typing for the -debug-only option.
At some point, pass definitions were heavily macro-ized. Pass
descriptive names were added in two places. This is not only redundant
but a source of confusion. You could waste a lot of time grepping for
the wrong string. I removed all the getName() overrides which, at
around 90 passes, was a fairly significant amount of code bloat.
Any pass that we want to be able to invoke by name from a tool
(sil-opt) or pipeline plan *should* have unique type name, enum value,
commend-line string, and name string. I removed a comment about the
various inliner passes that contradicted that.
Side note: We should be consistent with the policy that a pass is
identified by its type. We have a couple passes, LICM and CSE, which
currently violate that convention.
Previously it was part of swiftBasic.
The demangler library does not depend on llvm (except some header-only utilities like StringRef). Putting it into its own library makes sure that no llvm stuff will be linked into clients which use the demangler library.
This change also contains other refactoring, like moving demangler code into different files. This makes it easier to remove the old demangler from the runtime library when we switch to the new symbol mangling.
Also in this commit: remove some unused API functions from the demangler Context.
fixes rdar://problem/30503344
This pipeline is run as part of IRGen and has access to the IRGenModule.
Passes that run as part of this pipeline can query for the IRGenModule.
We will use it for the AllocStackHoisting pass. It wants to know if a type is of
non-fixed size.
To break the cyclic dependency between IRGen -> SILOptimizer -> IRGen that would
arise from the SILPassManager having to know about the createIRGENPASS()
function IRGen passes instead of exposing this function dynamically have to add
themselves to the pass manager.
Changes:
* Terminate all namespaces with the correct closing comment.
* Make sure argument names in comments match the corresponding parameter name.
* Remove redundant get() calls on smart pointers.
* Prefer using "override" or "final" instead of "virtual". Remove "virtual" where appropriate.
We also either remove or make private the addPass* functions on SILPassManager,
so the only way to execute passes via SILPassManager is by creating a
SILPassPipelinePlan. This beyond adding uniformity ensures that we always
resetAndRemoveTransformations properly after a pipeline is run.
When SILVerifyAll is enabled, individual functions are verified after
function passes are run upon them. This means that any functions created
by a function pass will not be verified after the pass runs. Thus
specialization errors that cause the verifier to trip will be
misattributed to the first pass that makes a change to the specialized
function. This is very misleading and increases triage time.
This change eliminates that problem by ensuring that when SILVerifyAll is
enabled, we always verify newly specialized functions as they are added to the
worklist.
rdar://28706158
An int is already constant and in general in LLVM style we do not create such
const ints. On the other hand, a constexpr I think expresses the intent slightly
better and gives the compiler more freedom anyways.
This adds the typedef and switches uses of NodeType * to NodeRef. This is in
preparation for the eventual NodeRef-ization of the GraphTraits in LLVM. NFC.
This re-instates commit de9622654d
The problem of the infinite loop should be fixed by the previous fix in FunctionSignatureOpts.
In addition this new commit implements a safety check to void such cases, even if buggy optimizations try to keep pushing new functions onto the work list.
Instead the pipeline is continued on the old function. This happens when a pass pushes a new, e.g. specialized function, on the function stack.
There is no need to repeat passes which already did run on a function.
It saves a little of compile time and I didn't see any significant impact on code size or performance.
It also simplifies the pass manager.
This ensures that when one is bisecting on pass counts, regardless of whether or
not one removes code in the test case, the pass counts being run remain the
same.
The option is supposed to be used as follows and takes a comma-seprataed list of SIL pass numbers as input:
-Xllvm -debug-only-pass-number=passnumber1[,passnumber2,..,passnumberN]
It enables the debug printing (i.e. prints inside DEBUG statements ) when one of the mentioned passes is being run.
This commit adds -sil-break-on-function and -sil-break-on-pass, both
-Xllvm options.
-sil-break-on-function stops function pass execution in the debugger
just prior to running each function pass on a particular function.
-sil-break-on-pass stops function pass execution in the debugger just
prior to running a particular pass on each function.
Used together, you can break just prior running a particular pass on a
particular function.
For example:
xcrun lldb -- $(/path/to/my/swiftc -c -O problem.swift -###) -Xllvm -sil-break-on-function=_TF7problem7problemFT_T_ -Xllvm -sil-break-on-pass='Simplify CFG'
Now when running under the debugger, we'll stop execution just prior
to each run of Simplify CFG on the function problem() in
problem.swift.
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
Allow function passes to:
1. Add new functions, to be optimized before continuing with the current
function.
2. Restart the pipeline on the current function after the current pass
completes.
This makes it possible to fully optimize callees that are the result of
specialization prior to generating interprocedural information or making
inlining choices about these callees.
It also allows us to solve a phase-ordering issue we have with generic
specialization, devirtualization, and inlining, by rescheduling the
current function after changes happen in one of these passes as opposed
to running all of these as part of the inlining pass as happens today.
Currently this is NFC since we have no passes that use this
functionality.