2015-03-07 17:02:36 +08:00
|
|
|
//===- Parsing, selection, and construction of pass pipelines -------------===//
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
///
|
2015-03-07 17:02:36 +08:00
|
|
|
/// This file provides the implementation of the PassBuilder based on our
|
|
|
|
/// static pass registry as well as related functionality. It also provides
|
|
|
|
/// helpers to aid in analyzing, debugging, and testing passes and pass
|
|
|
|
/// pipelines.
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-03-07 17:02:36 +08:00
|
|
|
#include "llvm/Passes/PassBuilder.h"
|
2016-02-29 06:16:03 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2016-02-14 07:32:00 +08:00
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
2016-02-20 11:46:03 +08:00
|
|
|
#include "llvm/Analysis/AliasAnalysisEvaluator.h"
|
2016-12-19 16:22:17 +08:00
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
2016-02-14 07:46:24 +08:00
|
|
|
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
2016-05-06 05:13:27 +08:00
|
|
|
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
2016-05-05 10:59:57 +08:00
|
|
|
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
2016-09-17 00:56:30 +08:00
|
|
|
#include "llvm/Analysis/CFGPrinter.h"
|
2016-07-06 08:26:41 +08:00
|
|
|
#include "llvm/Analysis/CFLAndersAliasAnalysis.h"
|
|
|
|
#include "llvm/Analysis/CFLSteensAliasAnalysis.h"
|
2014-04-21 19:12:00 +08:00
|
|
|
#include "llvm/Analysis/CGSCCPassManager.h"
|
2016-03-10 19:24:11 +08:00
|
|
|
#include "llvm/Analysis/CallGraph.h"
|
2016-04-19 07:55:01 +08:00
|
|
|
#include "llvm/Analysis/DemandedBits.h"
|
2016-05-13 06:19:39 +08:00
|
|
|
#include "llvm/Analysis/DependenceAnalysis.h"
|
2016-02-26 01:54:15 +08:00
|
|
|
#include "llvm/Analysis/DominanceFrontier.h"
|
2016-03-11 17:15:11 +08:00
|
|
|
#include "llvm/Analysis/GlobalsModRef.h"
|
2016-07-17 06:51:33 +08:00
|
|
|
#include "llvm/Analysis/IVUsers.h"
|
2014-02-06 12:37:03 +08:00
|
|
|
#include "llvm/Analysis/LazyCallGraph.h"
|
2016-06-14 06:01:25 +08:00
|
|
|
#include "llvm/Analysis/LazyValueInfo.h"
|
2016-07-03 05:18:40 +08:00
|
|
|
#include "llvm/Analysis/LoopAccessAnalysis.h"
|
2015-01-20 18:58:50 +08:00
|
|
|
#include "llvm/Analysis/LoopInfo.h"
|
2016-03-10 08:55:30 +08:00
|
|
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
2017-04-12 04:06:36 +08:00
|
|
|
#include "llvm/Analysis/MemorySSA.h"
|
2016-08-12 21:53:02 +08:00
|
|
|
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
|
2017-10-10 07:19:02 +08:00
|
|
|
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
2018-06-28 22:13:06 +08:00
|
|
|
#include "llvm/Analysis/PhiValues.h"
|
2016-02-26 01:54:07 +08:00
|
|
|
#include "llvm/Analysis/PostDominators.h"
|
2016-06-04 06:54:26 +08:00
|
|
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
2016-02-26 01:54:25 +08:00
|
|
|
#include "llvm/Analysis/RegionInfo.h"
|
[PM] Port ScalarEvolution to the new pass manager.
This change makes ScalarEvolution a stand-alone object and just produces
one from a pass as needed. Making this work well requires making the
object movable, using references instead of overwritten pointers in
a number of places, and other refactorings.
I've also wired it up to the new pass manager and added a RUN line to
a test to exercise it under the new pass manager. This includes basic
printing support much like with other analyses.
But there is a big and somewhat scary change here. Prior to this patch
ScalarEvolution was never *actually* invalidated!!! Re-running the pass
just re-wired up the various other analyses and didn't remove any of the
existing entries in the SCEV caches or clear out anything at all. This
might seem OK as everything in SCEV that can uses ValueHandles to track
updates to the values that serve as SCEV keys. However, this still means
that as we ran SCEV over each function in the module, we kept
accumulating more and more SCEVs into the cache. At the end, we would
have a SCEV cache with every value that we ever needed a SCEV for in the
entire module!!! Yowzers. The releaseMemory routine would dump all of
this, but that isn't realy called during normal runs of the pipeline as
far as I can see.
To make matters worse, there *is* actually a key that we don't update
with value handles -- there is a map keyed off of Loop*s. Because
LoopInfo *does* release its memory from run to run, it is entirely
possible to run SCEV over one function, then over another function, and
then lookup a Loop* from the second function but find an entry inserted
for the first function! Ouch.
To make matters still worse, there are plenty of updates that *don't*
trip a value handle. It seems incredibly unlikely that today GVN or
another pass that invalidates SCEV can update values in *just* such
a way that a subsequent run of SCEV will incorrectly find lookups in
a cache, but it is theoretically possible and would be a nightmare to
debug.
With this refactoring, I've fixed all this by actually destroying and
recreating the ScalarEvolution object from run to run. Technically, this
could increase the amount of malloc traffic we see, but then again it is
also technically correct. ;] I don't actually think we're suffering from
tons of malloc traffic from SCEV because if we were, the fact that we
never clear the memory would seem more likely to have come up as an
actual problem before now. So, I've made the simple fix here. If in fact
there are serious issues with too much allocation and deallocation,
I can work on a clever fix that preserves the allocations (while
clearing the data) between each run, but I'd prefer to do that kind of
optimization with a test case / benchmark that shows why we need such
cleverness (and that can test that we actually make it faster). It's
possible that this will make some things faster by making the SCEV
caches have higher locality (due to being significantly smaller) so
until there is a clear benchmark, I think the simple change is best.
Differential Revision: http://reviews.llvm.org/D12063
llvm-svn: 245193
2015-08-17 10:08:17 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolution.h"
|
2016-02-20 12:01:45 +08:00
|
|
|
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
2016-02-20 12:03:06 +08:00
|
|
|
#include "llvm/Analysis/ScopedNoAliasAA.h"
|
2018-11-27 05:57:47 +08:00
|
|
|
#include "llvm/Analysis/StackSafetyAnalysis.h"
|
2015-01-15 19:39:46 +08:00
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
2015-02-01 18:11:22 +08:00
|
|
|
#include "llvm/Analysis/TargetTransformInfo.h"
|
2016-02-20 12:04:52 +08:00
|
|
|
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
|
2016-06-25 04:13:42 +08:00
|
|
|
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
|
2016-07-08 11:32:49 +08:00
|
|
|
#include "llvm/CodeGen/UnreachableBlockElim.h"
|
2015-01-14 18:19:28 +08:00
|
|
|
#include "llvm/IR/Dominators.h"
|
2014-01-12 20:15:39 +08:00
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
#include "llvm/IR/PassManager.h"
|
2019-03-31 18:15:39 +08:00
|
|
|
#include "llvm/IR/SafepointIRVerifier.h"
|
2014-01-20 19:34:08 +08:00
|
|
|
#include "llvm/IR/Verifier.h"
|
2014-01-12 20:15:39 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2018-10-17 18:36:23 +08:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
2016-02-29 06:16:03 +08:00
|
|
|
#include "llvm/Support/Regex.h"
|
2015-02-01 18:11:22 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2018-01-25 20:06:32 +08:00
|
|
|
#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
|
[PM] Port the always inliner to the new pass manager in a much more
minimal and boring form than the old pass manager's version.
This pass does the very minimal amount of work necessary to inline
functions declared as always-inline. It doesn't support a wide array of
things that the legacy pass manager did support, but is alse ... about
20 lines of code. So it has that going for it. Notably things this
doesn't support:
- Array alloca merging
- To support the above, bottom-up inlining with careful history
tracking and call graph updates
- DCE of the functions that become dead after this inlining.
- Inlining through call instructions with the always_inline attribute.
Instead, it focuses on inlining functions with that attribute.
The first I've omitted because I'm hoping to just turn it off for the
primary pass manager. If that doesn't pan out, I can add it here but it
will be reasonably expensive to do so.
The second should really be handled by running global-dce after the
inliner. I don't want to re-implement the non-trivial logic necessary to
do comdat-correct DCE of functions. This means the -O0 pipeline will
have to be at least 'always-inline,global-dce', but that seems
reasonable to me. If others are seriously worried about this I'd like to
hear about it and understand why. Again, this is all solveable by
factoring that logic into a utility and calling it here, but I'd like to
wait to do that until there is a clear reason why the existing
pass-based factoring won't work.
The final point is a serious one. I can fairly easily add support for
this, but it seems both costly and a confusing construct for the use
case of the always inliner running at -O0. This attribute can of course
still impact the normal inliner easily (although I find that
a questionable re-use of the same attribute). I've started a discussion
to sort out what semantics we want here and based on that can figure out
if it makes sense ta have this complexity at O0 or not.
One other advantage of this design is that it should be quite a bit
faster due to checking for whether the function is a viable candidate
for inlining exactly once per function instead of doing it for each call
site.
Anyways, hopefully a reasonable starting point for this pass.
Differential Revision: https://reviews.llvm.org/D23299
llvm-svn: 278896
2016-08-17 10:56:20 +08:00
|
|
|
#include "llvm/Transforms/IPO/AlwaysInliner.h"
|
2017-02-10 07:46:27 +08:00
|
|
|
#include "llvm/Transforms/IPO/ArgumentPromotion.h"
|
2017-10-25 21:40:08 +08:00
|
|
|
#include "llvm/Transforms/IPO/CalledValuePropagation.h"
|
2016-05-05 08:51:09 +08:00
|
|
|
#include "llvm/Transforms/IPO/ConstantMerge.h"
|
2016-07-09 11:25:35 +08:00
|
|
|
#include "llvm/Transforms/IPO/CrossDSOCFI.h"
|
2016-06-12 17:16:39 +08:00
|
|
|
#include "llvm/Transforms/IPO/DeadArgumentElimination.h"
|
2016-05-05 10:37:32 +08:00
|
|
|
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
|
2015-12-27 16:13:45 +08:00
|
|
|
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
|
2016-02-18 19:03:11 +08:00
|
|
|
#include "llvm/Transforms/IPO/FunctionAttrs.h"
|
2016-07-19 05:22:24 +08:00
|
|
|
#include "llvm/Transforms/IPO/FunctionImport.h"
|
2016-05-04 03:39:15 +08:00
|
|
|
#include "llvm/Transforms/IPO/GlobalDCE.h"
|
2016-04-26 08:28:01 +08:00
|
|
|
#include "llvm/Transforms/IPO/GlobalOpt.h"
|
2016-11-21 08:28:23 +08:00
|
|
|
#include "llvm/Transforms/IPO/GlobalSplit.h"
|
2018-10-03 13:55:20 +08:00
|
|
|
#include "llvm/Transforms/IPO/HotColdSplitting.h"
|
2015-12-27 16:41:34 +08:00
|
|
|
#include "llvm/Transforms/IPO/InferFunctionAttrs.h"
|
[PM] Provide an initial, minimal port of the inliner to the new pass manager.
This doesn't implement *every* feature of the existing inliner, but
tries to implement the most important ones for building a functional
optimization pipeline and beginning to sort out bugs, regressions, and
other problems.
Notable, but intentional omissions:
- No alloca merging support. Why? Because it isn't clear we want to do
this at all. Active discussion and investigation is going on to remove
it, so for simplicity I omitted it.
- No support for trying to iterate on "internally" devirtualized calls.
Why? Because it adds what I suspect is inappropriate coupling for
little or no benefit. We will have an outer iteration system that
tracks devirtualization including that from function passes and
iterates already. We should improve that rather than approximate it
here.
- Optimization remarks. Why? Purely to make the patch smaller, no other
reason at all.
The last one I'll probably work on almost immediately. But I wanted to
skip it in the initial patch to try to focus the change as much as
possible as there is already a lot of code moving around and both of
these *could* be skipped without really disrupting the core logic.
A summary of the different things happening here:
1) Adding the usual new PM class and rigging.
2) Fixing minor underlying assumptions in the inline cost analysis or
inline logic that don't generally hold in the new PM world.
3) Adding the core pass logic which is in essence a loop over the calls
in the nodes in the call graph. This is a bit duplicated from the old
inliner, but only a handful of lines could realistically be shared.
(I tried at first, and it really didn't help anything.) All told,
this is only about 100 lines of code, and most of that is the
mechanics of wiring up analyses from the new PM world.
4) Updating the LazyCallGraph (in the new PM) based on the *newly
inlined* calls and references. This is very minimal because we cannot
form cycles.
5) When inlining removes the last use of a function, eagerly nuking the
body of the function so that any "one use remaining" inline cost
heuristics are immediately refined, and queuing these functions to be
completely deleted once inlining is complete and the call graph
updated to reflect that they have become dead.
6) After all the inlining for a particular function, updating the
LazyCallGraph and the CGSCC pass manager to reflect the
function-local simplifications that are done immediately and
internally by the inline utilties. These are the exact same
fundamental set of CG updates done by arbitrary function passes.
7) Adding a bunch of test cases to specifically target CGSCC and other
subtle aspects in the new PM world.
Many thanks to the careful review from Easwaran and Sanjoy and others!
Differential Revision: https://reviews.llvm.org/D24226
llvm-svn: 290161
2016-12-20 11:15:32 +08:00
|
|
|
#include "llvm/Transforms/IPO/Inliner.h"
|
2016-04-27 04:15:52 +08:00
|
|
|
#include "llvm/Transforms/IPO/Internalize.h"
|
2016-07-12 02:10:06 +08:00
|
|
|
#include "llvm/Transforms/IPO/LowerTypeTests.h"
|
2016-06-28 00:50:18 +08:00
|
|
|
#include "llvm/Transforms/IPO/PartialInlining.h"
|
2016-05-06 05:05:36 +08:00
|
|
|
#include "llvm/Transforms/IPO/SCCP.h"
|
2018-03-23 06:42:44 +08:00
|
|
|
#include "llvm/Transforms/IPO/SampleProfile.h"
|
2015-10-31 07:28:12 +08:00
|
|
|
#include "llvm/Transforms/IPO/StripDeadPrototypes.h"
|
2018-01-10 03:39:35 +08:00
|
|
|
#include "llvm/Transforms/IPO/SyntheticCountsPropagation.h"
|
2016-06-15 05:44:19 +08:00
|
|
|
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
|
2015-12-27 16:13:45 +08:00
|
|
|
#include "llvm/Transforms/InstCombine/InstCombine.h"
|
[NewPM] Port Msan
Summary:
Keeping msan a function pass requires replacing the module level initialization:
That means, don't define a ctor function which calls __msan_init, instead just
declare the init function at the first access, and add that to the global ctors
list.
Changes:
- Pull the actual sanitizer and the wrapper pass apart.
- Add a newpm msan pass. The function pass inserts calls to runtime
library functions, for which it inserts declarations as necessary.
- Update tests.
Caveats:
- There is one test that I dropped, because it specifically tested the
definition of the ctor.
Reviewers: chandlerc, fedor.sergeev, leonardchan, vitalybuka
Subscribers: sdardis, nemanjai, javed.absar, hiraditya, kbarton, bollu, atanasyan, jsji
Differential Revision: https://reviews.llvm.org/D55647
llvm-svn: 350305
2019-01-03 21:42:44 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation.h"
|
2019-02-14 06:22:48 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
|
2017-11-14 09:30:04 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
|
2018-11-27 05:57:47 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/CGProfile.h"
|
2018-09-05 01:19:13 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"
|
2018-06-30 07:36:03 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
|
2019-03-01 04:13:38 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
|
2018-06-30 07:36:03 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
|
[NewPM] Port Msan
Summary:
Keeping msan a function pass requires replacing the module level initialization:
That means, don't define a ctor function which calls __msan_init, instead just
declare the init function at the first access, and add that to the global ctors
list.
Changes:
- Pull the actual sanitizer and the wrapper pass apart.
- Add a newpm msan pass. The function pass inserts calls to runtime
library functions, for which it inserts declarations as necessary.
- Update tests.
Caveats:
- There is one test that I dropped, because it specifically tested the
definition of the ctor.
Reviewers: chandlerc, fedor.sergeev, leonardchan, vitalybuka
Subscribers: sdardis, nemanjai, javed.absar, hiraditya, kbarton, bollu, atanasyan, jsji
Differential Revision: https://reviews.llvm.org/D55647
llvm-svn: 350305
2019-01-03 21:42:44 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
2018-03-24 06:11:06 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
|
2019-02-14 06:22:48 +08:00
|
|
|
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
2015-10-31 07:13:18 +08:00
|
|
|
#include "llvm/Transforms/Scalar/ADCE.h"
|
2016-06-15 14:18:01 +08:00
|
|
|
#include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
|
2016-05-25 09:57:04 +08:00
|
|
|
#include "llvm/Transforms/Scalar/BDCE.h"
|
Recommit r317351 : Add CallSiteSplitting pass
This recommit r317351 after fixing a buildbot failure.
Original commit message:
Summary:
This change add a pass which tries to split a call-site to pass
more constrained arguments if its argument is predicated in the control flow
so that we can expose better context to the later passes (e.g, inliner, jump
threading, or IPA-CP based function cloning, etc.).
As of now we support two cases :
1) If a call site is dominated by an OR condition and if any of its arguments
are predicated on this OR condition, try to split the condition with more
constrained arguments. For example, in the code below, we try to split the
call site since we can predicate the argument (ptr) based on the OR condition.
Split from :
if (!ptr || c)
callee(ptr);
to :
if (!ptr)
callee(null ptr) // set the known constant value
else if (c)
callee(nonnull ptr) // set non-null attribute in the argument
2) We can also split a call-site based on constant incoming values of a PHI
For example,
from :
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2, label %BB1
BB1:
br label %BB2
BB2:
%p = phi i32 [ 0, %BB0 ], [ 1, %BB1 ]
call void @bar(i32 %p)
to
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2-split0, label %BB1
BB1:
br label %BB2-split1
BB2-split0:
call void @bar(i32 0)
br label %BB2
BB2-split1:
call void @bar(i32 1)
br label %BB2
BB2:
%p = phi i32 [ 0, %BB2-split0 ], [ 1, %BB2-split1 ]
llvm-svn: 317362
2017-11-04 04:41:16 +08:00
|
|
|
#include "llvm/Transforms/Scalar/CallSiteSplitting.h"
|
2016-07-19 00:29:17 +08:00
|
|
|
#include "llvm/Transforms/Scalar/ConstantHoisting.h"
|
2016-07-07 07:26:29 +08:00
|
|
|
#include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h"
|
2016-04-23 03:40:41 +08:00
|
|
|
#include "llvm/Transforms/Scalar/DCE.h"
|
2016-05-18 05:38:13 +08:00
|
|
|
#include "llvm/Transforms/Scalar/DeadStoreElimination.h"
|
2017-09-09 21:38:18 +08:00
|
|
|
#include "llvm/Transforms/Scalar/DivRemPairs.h"
|
2015-02-01 18:51:23 +08:00
|
|
|
#include "llvm/Transforms/Scalar/EarlyCSE.h"
|
2016-06-25 07:32:02 +08:00
|
|
|
#include "llvm/Transforms/Scalar/Float2Int.h"
|
2016-06-04 06:54:26 +08:00
|
|
|
#include "llvm/Transforms/Scalar/GVN.h"
|
2016-06-14 08:49:23 +08:00
|
|
|
#include "llvm/Transforms/Scalar/GuardWidening.h"
|
2017-01-11 17:43:56 +08:00
|
|
|
#include "llvm/Transforms/Scalar/IVUsersPrinter.h"
|
2016-06-06 02:01:19 +08:00
|
|
|
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
|
2018-03-15 19:01:19 +08:00
|
|
|
#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
|
2018-06-30 07:36:03 +08:00
|
|
|
#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
|
2016-06-14 08:51:09 +08:00
|
|
|
#include "llvm/Transforms/Scalar/JumpThreading.h"
|
2016-07-13 06:42:24 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LICM.h"
|
2017-01-11 17:43:56 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
|
2016-08-13 12:11:27 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"
|
2016-07-15 02:28:29 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopDeletion.h"
|
2016-07-19 00:29:27 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopDistribute.h"
|
2016-07-13 02:45:51 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopIdiomRecognize.h"
|
2018-05-25 09:32:36 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopInstSimplify.h"
|
2017-01-27 09:32:26 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopLoadElimination.h"
|
2017-01-11 17:43:56 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
2017-01-26 00:00:44 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopPredication.h"
|
2016-05-04 06:02:31 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopRotation.h"
|
2016-05-04 05:47:32 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
|
2017-01-20 16:42:19 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopSink.h"
|
2016-07-19 05:41:50 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"
|
2018-07-01 20:47:30 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"
|
2016-07-20 07:54:23 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LoopUnrollPass.h"
|
2016-05-14 06:52:35 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LowerAtomic.h"
|
2015-01-24 19:13:02 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
|
2016-07-29 06:08:41 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
|
2019-01-31 17:10:17 +08:00
|
|
|
#include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
|
Introduce llvm.experimental.widenable_condition intrinsic
This patch introduces a new instinsic `@llvm.experimental.widenable_condition`
that allows explicit representation for guards. It is an alternative to using
`@llvm.experimental.guard` intrinsic that does not contain implicit control flow.
We keep finding places where `@llvm.experimental.guard` is not supported or
treated too conservatively, and there are 2 reasons to that:
- `@llvm.experimental.guard` has memory write side effect to model implicit control flow,
and this sometimes confuses passes and analyzes that work with memory;
- Not all passes and analysis are aware of the semantics of guards. These passes treat them
as regular throwing call and have no idea that the condition of guard may be used to prove
something. One well-known place which had caused us troubles in the past is explicit loop
iteration count calculation in SCEV. Another example is new loop unswitching which is not
aware of guards. Whenever a new pass appears, we potentially have this problem there.
Rather than go and fix all these places (and commit to keep track of them and add support
in future), it seems more reasonable to leverage the existing optimizer's logic as much as possible.
The only significant difference between guards and regular explicit branches is that guard's condition
can be widened. It means that a guard contains (explicitly or implicitly) a `deopt` block successor,
and it is always legal to go there no matter what the guard condition is. The other successor is
a guarded block, and it is only legal to go there if the condition is true.
This patch introduces a new explicit form of guards alternative to `@llvm.experimental.guard`
intrinsic. Now a widenable guard can be represented in the CFG explicitly like this:
%widenable_condition = call i1 @llvm.experimental.widenable.condition()
%new_condition = and i1 %cond, %widenable_condition
br i1 %new_condition, label %guarded, label %deopt
guarded:
; Guarded instructions
deopt:
call type @llvm.experimental.deoptimize(<args...>) [ "deopt"(<deopt_args...>) ]
The new intrinsic `@llvm.experimental.widenable.condition` has semantics of an
`undef`, but the intrinsic prevents the optimizer from folding it early. This form
should exploit all optimization boons provided to `br` instuction, and it still can be
widened by replacing the result of `@llvm.experimental.widenable.condition()`
with `and` with any arbitrary boolean value (as long as the branch that is taken when
it is `false` has a deopt and has no side-effects).
For more motivation, please check llvm-dev discussion "[llvm-dev] Giving up using
implicit control flow in guards".
This patch introduces this new intrinsic with respective LangRef changes and a pass
that converts old-style guards (expressed as intrinsics) into the new form.
The naming discussion is still ungoing. Merging this to unblock further items. We can
later change the name of this intrinsic.
Reviewed By: reames, fedor.sergeev, sanjoy
Differential Revision: https://reviews.llvm.org/D51207
llvm-svn: 348593
2018-12-07 22:39:46 +08:00
|
|
|
#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"
|
2016-06-14 10:44:55 +08:00
|
|
|
#include "llvm/Transforms/Scalar/MemCpyOptimizer.h"
|
2016-06-18 03:10:09 +08:00
|
|
|
#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"
|
2016-07-22 06:28:52 +08:00
|
|
|
#include "llvm/Transforms/Scalar/NaryReassociate.h"
|
2016-12-23 00:35:02 +08:00
|
|
|
#include "llvm/Transforms/Scalar/NewGVN.h"
|
2016-05-26 07:38:53 +08:00
|
|
|
#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
|
2016-04-27 07:39:29 +08:00
|
|
|
#include "llvm/Transforms/Scalar/Reassociate.h"
|
2017-12-15 17:32:11 +08:00
|
|
|
#include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h"
|
2016-05-18 23:18:25 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SCCP.h"
|
2015-09-12 17:09:14 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SROA.h"
|
2018-11-21 22:00:17 +08:00
|
|
|
#include "llvm/Transforms/Scalar/Scalarizer.h"
|
[PM/LoopUnswitch] Introduce a new, simpler loop unswitch pass.
Currently, this pass only focuses on *trivial* loop unswitching. At that
reduced problem it remains significantly better than the current loop
unswitch:
- Old pass is worse than cubic complexity. New pass is (I think) linear.
- New pass is much simpler in its design by focusing on full unswitching. (See
below for details on this).
- New pass doesn't carry state for thresholds between pass iterations.
- New pass doesn't carry state for correctness (both miscompile and
infloop) between pass iterations.
- New pass produces substantially better code after unswitching.
- New pass can handle more trivial unswitch cases.
- New pass doesn't recompute the dominator tree for the entire function
and instead incrementally updates it.
I've ported all of the trivial unswitching test cases from the old pass
to the new one to make sure that major functionality isn't lost in the
process. For several of the test cases I've worked to improve the
precision and rigor of the CHECKs, but for many I've just updated them
to handle the new IR produced.
My initial motivation was the fact that the old pass carried state in
very unreliable ways between pass iterations, and these mechansims were
incompatible with the new pass manager. However, I discovered many more
improvements to make along the way.
This pass makes two very significant assumptions that enable most of these
improvements:
1) Focus on *full* unswitching -- that is, completely removing whatever
control flow construct is being unswitched from the loop. In the case
of trivial unswitching, this means removing the trivial (exiting)
edge. In non-trivial unswitching, this means removing the branch or
switch itself. This is in opposition to *partial* unswitching where
some part of the unswitched control flow remains in the loop. Partial
unswitching only really applies to switches and to folded branches.
These are very similar to full unrolling and partial unrolling. The
full form is an effective canonicalization, the partial form needs
a complex cost model, cannot be iterated, isn't canonicalizing, and
should be a separate pass that runs very late (much like unrolling).
2) Leverage LLVM's Loop machinery to the fullest. The original unswitch
dates from a time when a great deal of LLVM's loop infrastructure was
missing, ineffective, and/or unreliable. As a consequence, a lot of
complexity was added which we no longer need.
With these two overarching principles, I think we can build a fast and
effective unswitcher that fits in well in the new PM and in the
canonicalization pipeline. Some of the remaining functionality around
partial unswitching may not be relevant today (not many test cases or
benchmarks I can find) but if they are I'd like to add support for them
as a separate layer that runs very late in the pipeline.
Purely to make reviewing and introducing this code more manageable, I've
split this into first a trivial-unswitch-only pass and in the next patch
I'll add support for full non-trivial unswitching against a *fixed*
threshold, exactly like full unrolling. I even plan to re-use the
unrolling thresholds, as these are incredibly similar cost tradeoffs:
we're cloning a loop body in order to end up with simplified control
flow. We should only do that when the total growth is reasonably small.
One of the biggest changes with this pass compared to the previous one
is that previously, each individual trivial exiting edge from a switch
was unswitched separately as a branch. Now, we unswitch the entire
switch at once, with cases going to the various destinations. This lets
us unswitch multiple exiting edges in a single operation and also avoids
numerous extremely bad behaviors, where we would introduce 1000s of
branches to test for thousands of possible values, all of which would
take the exact same exit path bypassing the loop. Now we will use
a switch with 1000s of cases that can be efficiently lowered into
a jumptable. This avoids relying on somehow forming a switch out of the
branches or getting horrible code if that fails for any reason.
Another significant change is that this pass actively updates the CFG
based on unswitching. For trivial unswitching, this is actually very
easy because of the definition of loop simplified form. Doing this makes
the code coming out of loop unswitch dramatically more friendly. We
still should run loop-simplifycfg (at the least) after this to clean up,
but it will have to do a lot less work.
Finally, this pass makes much fewer attempts to simplify instructions
based on the unswitch. Something like loop-instsimplify, instcombine, or
GVN can be used to do increasingly powerful simplifications based on the
now dominating predicate. The old simplifications are things that
something like loop-instsimplify should get today or a very, very basic
loop-instcombine could get. Keeping that logic separate is a big
simplifying technique.
Most of the code in this pass that isn't in the old one has to do with
achieving specific goals:
- Updating the dominator tree as we go
- Unswitching all cases in a switch in a single step.
I think it is still shorter than just the trivial unswitching code in
the old pass despite having this functionality.
Differential Revision: https://reviews.llvm.org/D32409
llvm-svn: 301576
2017-04-28 02:45:20 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"
|
2015-12-27 16:13:45 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
|
2016-04-23 03:54:10 +08:00
|
|
|
#include "llvm/Transforms/Scalar/Sink.h"
|
Add a new pass to speculate around PHI nodes with constant (integer) operands when profitable.
The core idea is to (re-)introduce some redundancies where their cost is
hidden by the cost of materializing immediates for constant operands of
PHI nodes. When the cost of the redundancies is covered by this,
avoiding materializing the immediate has numerous benefits:
1) Less register pressure
2) Potential for further folding / combining
3) Potential for more efficient instructions due to immediate operand
As a motivating example, consider the remarkably different cost on x86
of a SHL instruction with an immediate operand versus a register
operand.
This pattern turns up surprisingly frequently, but is somewhat rarely
obvious as a significant performance problem.
The pass is entirely target independent, but it does rely on the target
cost model in TTI to decide when to speculate things around the PHI
node. I've included x86-focused tests, but any target that sets up its
immediate cost model should benefit from this pass.
There is probably more that can be done in this space, but the pass
as-is is enough to get some important performance on our internal
benchmarks, and should be generally performance neutral, but help with
more extensive benchmarking is always welcome.
One awkward part is that this pass has to be scheduled after
*everything* that can eliminate these kinds of redundancies. This
includes SimplifyCFG, GVN, etc. I'm open to suggestions about better
places to put this. We could in theory make it part of the codegen pass
pipeline, but there doesn't really seem to be a good reason for that --
it isn't "lowering" in any sense and only relies on pretty standard cost
model based TTI queries, so it seems to fit well with the "optimization"
pipeline model. Still, further thoughts on the pipeline position are
welcome.
I've also only implemented this in the new pass manager. If folks are
very interested, I can try to add it to the old PM as well, but I didn't
really see much point (my use case is already switched over to the new
PM).
I've tested this pretty heavily without issue. A wide range of
benchmarks internally show no change outside the noise, and I don't see
any significant changes in SPEC either. However, the size class
computation in tcmalloc is substantially improved by this, which turns
into a 2% to 4% win on the hottest path through tcmalloc for us, so
there are definitely important cases where this is going to make
a substantial difference.
Differential revision: https://reviews.llvm.org/D37467
llvm-svn: 319164
2017-11-28 19:32:31 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SpeculateAroundPHIs.h"
|
2016-08-02 05:48:33 +08:00
|
|
|
#include "llvm/Transforms/Scalar/SpeculativeExecution.h"
|
2016-07-07 07:48:41 +08:00
|
|
|
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
|
[Unroll/UnrollAndJam/Vectorizer/Distribute] Add followup loop attributes.
When multiple loop transformation are defined in a loop's metadata, their order of execution is defined by the order of their respective passes in the pass pipeline. For instance, e.g.
#pragma clang loop unroll_and_jam(enable)
#pragma clang loop distribute(enable)
is the same as
#pragma clang loop distribute(enable)
#pragma clang loop unroll_and_jam(enable)
and will try to loop-distribute before Unroll-And-Jam because the LoopDistribute pass is scheduled after UnrollAndJam pass. UnrollAndJamPass only supports one inner loop, i.e. it will necessarily fail after loop distribution. It is not possible to specify another execution order. Also,t the order of passes in the pipeline is subject to change between versions of LLVM, optimization options and which pass manager is used.
This patch adds 'followup' attributes to various loop transformation passes. These attributes define which attributes the resulting loop of a transformation should have. For instance,
!0 = !{!0, !1, !2}
!1 = !{!"llvm.loop.unroll_and_jam.enable"}
!2 = !{!"llvm.loop.unroll_and_jam.followup_inner", !3}
!3 = !{!"llvm.loop.distribute.enable"}
defines a loop ID (!0) to be unrolled-and-jammed (!1) and then the attribute !3 to be added to the jammed inner loop, which contains the instruction to distribute the inner loop.
Currently, in both pass managers, pass execution is in a fixed order and UnrollAndJamPass will not execute again after LoopDistribute. We hope to fix this in the future by allowing pass managers to run passes until a fixpoint is reached, use Polly to perform these transformations, or add a loop transformation pass which takes the order issue into account.
For mandatory/forced transformations (e.g. by having been declared by #pragma omp simd), the user must be notified when a transformation could not be performed. It is not possible that the responsible pass emits such a warning because the transformation might be 'hidden' in a followup attribute when it is executed, or it is not present in the pipeline at all. For this reason, this patche introduces a WarnMissedTransformations pass, to warn about orphaned transformations.
Since this changes the user-visible diagnostic message when a transformation is applied, two test cases in the clang repository need to be updated.
To ensure that no other transformation is executed before the intended one, the attribute `llvm.loop.disable_nonforced` can be added which should disable transformation heuristics before the intended transformation is applied. E.g. it would be surprising if a loop is distributed before a #pragma unroll_and_jam is applied.
With more supported code transformations (loop fusion, interchange, stripmining, offloading, etc.), transformations can be used as building blocks for more complex transformations (e.g. stripmining+stripmining+interchange -> tiling).
Reviewed By: hfinkel, dmgreen
Differential Revision: https://reviews.llvm.org/D49281
Differential Revision: https://reviews.llvm.org/D55288
llvm-svn: 348944
2018-12-13 01:32:52 +08:00
|
|
|
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
|
2016-06-16 05:51:30 +08:00
|
|
|
#include "llvm/Transforms/Utils/AddDiscriminators.h"
|
2016-07-23 02:04:25 +08:00
|
|
|
#include "llvm/Transforms/Utils/BreakCriticalEdges.h"
|
[ThinLTO] Handle chains of aliases
At -O0, globalopt is not run during the compile step, and we can have a
chain of an alias having an immediate aliasee of another alias. The
summaries are constructed assuming aliases in a canonical form
(flattened chains), and as a result only the base object but no
intermediate aliases were preserved.
Fix by adding a pass that canonicalize aliases, which ensures each
alias is a direct alias of the base object.
Reviewers: pcc, davidxl
Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54507
llvm-svn: 350423
2019-01-05 03:04:54 +08:00
|
|
|
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
|
2017-11-15 05:09:45 +08:00
|
|
|
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
|
2016-06-10 03:44:46 +08:00
|
|
|
#include "llvm/Transforms/Utils/LCSSA.h"
|
Conditionally eliminate library calls where the result value is not used
Summary:
This pass shrink-wraps a condition to some library calls where the call
result is not used. For example:
sqrt(val);
is transformed to
if (val < 0)
sqrt(val);
Even if the result of library call is not being used, the compiler cannot
safely delete the call because the function can set errno on error
conditions.
Note in many functions, the error condition solely depends on the incoming
parameter. In this optimization, we can generate the condition can lead to
the errno to shrink-wrap the call. Since the chances of hitting the error
condition is low, the runtime call is effectively eliminated.
These partially dead calls are usually results of C++ abstraction penalty
exposed by inlining. This optimization hits 108 times in 19 C/C++ programs
in SPEC2006.
Reviewers: hfinkel, mehdi_amini, davidxl
Subscribers: modocache, mgorny, mehdi_amini, xur, llvm-commits, beanz
Differential Revision: https://reviews.llvm.org/D24414
llvm-svn: 284542
2016-10-19 05:36:27 +08:00
|
|
|
#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
|
2016-07-09 11:03:01 +08:00
|
|
|
#include "llvm/Transforms/Utils/LoopSimplify.h"
|
2016-08-13 01:28:27 +08:00
|
|
|
#include "llvm/Transforms/Utils/LowerInvoke.h"
|
2016-06-14 11:22:22 +08:00
|
|
|
#include "llvm/Transforms/Utils/Mem2Reg.h"
|
2016-09-17 00:56:30 +08:00
|
|
|
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
|
2016-07-26 04:52:00 +08:00
|
|
|
#include "llvm/Transforms/Utils/SymbolRewriter.h"
|
2018-12-07 16:23:37 +08:00
|
|
|
#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"
|
2016-07-10 06:56:50 +08:00
|
|
|
#include "llvm/Transforms/Vectorize/LoopVectorize.h"
|
2016-07-09 11:11:29 +08:00
|
|
|
#include "llvm/Transforms/Vectorize/SLPVectorizer.h"
|
2016-06-14 11:22:22 +08:00
|
|
|
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2017-02-12 13:38:04 +08:00
|
|
|
static cl::opt<unsigned> MaxDevirtIterations("pm-max-devirt-iterations",
|
|
|
|
cl::ReallyHidden, cl::init(4));
|
2017-05-23 00:41:57 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
RunPartialInlining("enable-npm-partial-inlining", cl::init(false),
|
|
|
|
cl::Hidden, cl::ZeroOrMore,
|
|
|
|
cl::desc("Run Partial inlinining pass"));
|
2017-02-12 13:38:04 +08:00
|
|
|
|
2017-05-23 07:41:40 +08:00
|
|
|
static cl::opt<bool>
|
2017-05-23 07:47:11 +08:00
|
|
|
RunNewGVN("enable-npm-newgvn", cl::init(false),
|
2017-05-23 07:41:40 +08:00
|
|
|
cl::Hidden, cl::ZeroOrMore,
|
|
|
|
cl::desc("Run NewGVN instead of GVN"));
|
|
|
|
|
2017-06-10 23:20:03 +08:00
|
|
|
static cl::opt<bool> EnableEarlyCSEMemSSA(
|
2017-06-28 06:25:02 +08:00
|
|
|
"enable-npm-earlycse-memssa", cl::init(true), cl::Hidden,
|
|
|
|
cl::desc("Enable the EarlyCSE w/ MemorySSA pass for the new PM (default = on)"));
|
2017-06-10 23:20:03 +08:00
|
|
|
|
2017-04-27 08:28:03 +08:00
|
|
|
static cl::opt<bool> EnableGVNHoist(
|
2018-10-02 02:57:08 +08:00
|
|
|
"enable-npm-gvn-hoist", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Enable the GVN hoisting pass for the new PM (default = off)"));
|
2017-04-27 08:28:03 +08:00
|
|
|
|
2017-06-04 07:18:29 +08:00
|
|
|
static cl::opt<bool> EnableGVNSink(
|
|
|
|
"enable-npm-gvn-sink", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Enable the GVN hoisting pass for the new PM (default = off)"));
|
|
|
|
|
2018-07-01 20:47:30 +08:00
|
|
|
static cl::opt<bool> EnableUnrollAndJam(
|
|
|
|
"enable-npm-unroll-and-jam", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Enable the Unroll and Jam pass for the new PM (default = off)"));
|
|
|
|
|
2018-01-10 03:39:35 +08:00
|
|
|
static cl::opt<bool> EnableSyntheticCounts(
|
|
|
|
"enable-npm-synthetic-counts", cl::init(false), cl::Hidden, cl::ZeroOrMore,
|
|
|
|
cl::desc("Run synthetic function entry count generation "
|
|
|
|
"pass"));
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
static Regex DefaultAliasRegex(
|
|
|
|
"^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");
|
2016-02-29 06:16:03 +08:00
|
|
|
|
2018-09-05 01:19:13 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
EnableCHR("enable-chr-npm", cl::init(true), cl::Hidden,
|
|
|
|
cl::desc("Enable control height reduction optimization (CHR)"));
|
|
|
|
|
2018-10-03 13:55:20 +08:00
|
|
|
extern cl::opt<bool> EnableHotColdSplit;
|
2019-03-01 04:13:38 +08:00
|
|
|
extern cl::opt<bool> EnableOrderFileInstrumentation;
|
2018-10-03 13:55:20 +08:00
|
|
|
|
2019-01-18 04:48:34 +08:00
|
|
|
extern cl::opt<bool> FlattenedProfileUsed;
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
static bool isOptimizingForSize(PassBuilder::OptimizationLevel Level) {
|
|
|
|
switch (Level) {
|
|
|
|
case PassBuilder::O0:
|
|
|
|
case PassBuilder::O1:
|
|
|
|
case PassBuilder::O2:
|
|
|
|
case PassBuilder::O3:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case PassBuilder::Os:
|
|
|
|
case PassBuilder::Oz:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid optimization level!");
|
|
|
|
}
|
|
|
|
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
namespace {
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op module pass which does nothing.
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
struct NoOpModulePass {
|
2016-08-09 08:28:38 +08:00
|
|
|
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
|
2016-06-17 08:11:01 +08:00
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|
2014-01-11 19:52:05 +08:00
|
|
|
static StringRef name() { return "NoOpModulePass"; }
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op module analysis.
|
2016-03-11 18:33:22 +08:00
|
|
|
class NoOpModuleAnalysis : public AnalysisInfoMixin<NoOpModuleAnalysis> {
|
|
|
|
friend AnalysisInfoMixin<NoOpModuleAnalysis>;
|
2016-11-24 01:53:26 +08:00
|
|
|
static AnalysisKey Key;
|
2016-03-11 18:22:49 +08:00
|
|
|
|
|
|
|
public:
|
2015-01-06 10:50:06 +08:00
|
|
|
struct Result {};
|
2016-08-09 08:28:38 +08:00
|
|
|
Result run(Module &, ModuleAnalysisManager &) { return Result(); }
|
2015-01-06 10:50:06 +08:00
|
|
|
static StringRef name() { return "NoOpModuleAnalysis"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op CGSCC pass which does nothing.
|
2014-04-21 19:12:00 +08:00
|
|
|
struct NoOpCGSCCPass {
|
[PM] Introduce basic update capabilities to the new PM's CGSCC pass
manager, including both plumbing and logic to handle function pass
updates.
There are three fundamentally tied changes here:
1) Plumbing *some* mechanism for updating the CGSCC pass manager as the
CG changes while passes are running.
2) Changing the CGSCC pass manager infrastructure to have support for
the underlying graph to mutate mid-pass run.
3) Actually updating the CG after function passes run.
I can separate them if necessary, but I think its really useful to have
them together as the needs of #3 drove #2, and that in turn drove #1.
The plumbing technique is to extend the "run" method signature with
extra arguments. We provide the call graph that intrinsically is
available as it is the basis of the pass manager's IR units, and an
output parameter that records the results of updating the call graph
during an SCC passes's run. Note that "...UpdateResult" isn't a *great*
name here... suggestions very welcome.
I tried a pretty frustrating number of different data structures and such
for the innards of the update result. Every other one failed for one
reason or another. Sometimes I just couldn't keep the layers of
complexity right in my head. The thing that really worked was to just
directly provide access to the underlying structures used to walk the
call graph so that their updates could be informed by the *particular*
nature of the change to the graph.
The technique for how to make the pass management infrastructure cope
with mutating graphs was also something that took a really, really large
number of iterations to get to a place where I was happy. Here are some
of the considerations that drove the design:
- We operate at three levels within the infrastructure: RefSCC, SCC, and
Node. In each case, we are working bottom up and so we want to
continue to iterate on the "lowest" node as the graph changes. Look at
how we iterate over nodes in an SCC running function passes as those
function passes mutate the CG. We continue to iterate on the "lowest"
SCC, which is the one that continues to contain the function just
processed.
- The call graph structure re-uses SCCs (and RefSCCs) during mutation
events for the *highest* entry in the resulting new subgraph, not the
lowest. This means that it is necessary to continually update the
current SCC or RefSCC as it shifts. This is really surprising and
subtle, and took a long time for me to work out. I actually tried
changing the call graph to provide the opposite behavior, and it
breaks *EVERYTHING*. The graph update algorithms are really deeply
tied to this particualr pattern.
- When SCCs or RefSCCs are split apart and refined and we continually
re-pin our processing to the bottom one in the subgraph, we need to
enqueue the newly formed SCCs and RefSCCs for subsequent processing.
Queuing them presents a few challenges:
1) SCCs and RefSCCs use wildly different iteration strategies at
a high level. We end up needing to converge them on worklist
approaches that can be extended in order to be able to handle the
mutations.
2) The order of the enqueuing need to remain bottom-up post-order so
that we don't get surprising order of visitation for things like
the inliner.
3) We need the worklists to have set semantics so we don't duplicate
things endlessly. We don't need a *persistent* set though because
we always keep processing the bottom node!!!! This is super, super
surprising to me and took a long time to convince myself this is
correct, but I'm pretty sure it is... Once we sink down to the
bottom node, we can't re-split out the same node in any way, and
the postorder of the current queue is fixed and unchanging.
4) We need to make sure that the "current" SCC or RefSCC actually gets
enqueued here such that we re-visit it because we continue
processing a *new*, *bottom* SCC/RefSCC.
- We also need the ability to *skip* SCCs and RefSCCs that get merged
into a larger component. We even need the ability to skip *nodes* from
an SCC that are no longer part of that SCC.
This led to the design you see in the patch which uses SetVector-based
worklists. The RefSCC worklist is always empty until an update occurs
and is just used to handle those RefSCCs created by updates as the
others don't even exist yet and are formed on-demand during the
bottom-up walk. The SCC worklist is pre-populated from the RefSCC, and
we push new SCCs onto it and blacklist existing SCCs on it to get the
desired processing.
We then *directly* update these when updating the call graph as I was
never able to find a satisfactory abstraction around the update
strategy.
Finally, we need to compute the updates for function passes. This is
mostly used as an initial customer of all the update mechanisms to drive
their design to at least cover some real set of use cases. There are
a bunch of interesting things that came out of doing this:
- It is really nice to do this a function at a time because that
function is likely hot in the cache. This means we want even the
function pass adaptor to support online updates to the call graph!
- To update the call graph after arbitrary function pass mutations is
quite hard. We have to build a fairly comprehensive set of
data structures and then process them. Fortunately, some of this code
is related to the code for building the cal graph in the first place.
Unfortunately, very little of it makes any sense to share because the
nature of what we're doing is so very different. I've factored out the
one part that made sense at least.
- We need to transfer these updates into the various structures for the
CGSCC pass manager. Once those were more sanely worked out, this
became relatively easier. But some of those needs necessitated changes
to the LazyCallGraph interface to make it significantly easier to
extract the changed SCCs from an update operation.
- We also need to update the CGSCC analysis manager as the shape of the
graph changes. When an SCC is merged away we need to clear analyses
associated with it from the analysis manager which we didn't have
support for in the analysis manager infrsatructure. New SCCs are easy!
But then we have the case that the original SCC has its shape changed
but remains in the call graph. There we need to *invalidate* the
analyses associated with it.
- We also need to invalidate analyses after we *finish* processing an
SCC. But the analyses we need to invalidate here are *only those for
the newly updated SCC*!!! Because we only continue processing the
bottom SCC, if we split SCCs apart the original one gets invalidated
once when its shape changes and is not processed farther so its
analyses will be correct. It is the bottom SCC which continues being
processed and needs to have the "normal" invalidation done based on
the preserved analyses set.
All of this is mostly background and context for the changes here.
Many thanks to all the reviewers who helped here. Especially Sanjoy who
caught several interesting bugs in the graph algorithms, David, Sean,
and others who all helped with feedback.
Differential Revision: http://reviews.llvm.org/D21464
llvm-svn: 279618
2016-08-24 17:37:14 +08:00
|
|
|
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &,
|
|
|
|
LazyCallGraph &, CGSCCUpdateResult &UR) {
|
2014-04-21 19:12:00 +08:00
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|
|
|
|
static StringRef name() { return "NoOpCGSCCPass"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op CGSCC analysis.
|
2016-03-11 18:33:22 +08:00
|
|
|
class NoOpCGSCCAnalysis : public AnalysisInfoMixin<NoOpCGSCCAnalysis> {
|
|
|
|
friend AnalysisInfoMixin<NoOpCGSCCAnalysis>;
|
2016-11-24 01:53:26 +08:00
|
|
|
static AnalysisKey Key;
|
2016-03-11 18:22:49 +08:00
|
|
|
|
|
|
|
public:
|
2015-01-06 10:50:06 +08:00
|
|
|
struct Result {};
|
[PM] Introduce basic update capabilities to the new PM's CGSCC pass
manager, including both plumbing and logic to handle function pass
updates.
There are three fundamentally tied changes here:
1) Plumbing *some* mechanism for updating the CGSCC pass manager as the
CG changes while passes are running.
2) Changing the CGSCC pass manager infrastructure to have support for
the underlying graph to mutate mid-pass run.
3) Actually updating the CG after function passes run.
I can separate them if necessary, but I think its really useful to have
them together as the needs of #3 drove #2, and that in turn drove #1.
The plumbing technique is to extend the "run" method signature with
extra arguments. We provide the call graph that intrinsically is
available as it is the basis of the pass manager's IR units, and an
output parameter that records the results of updating the call graph
during an SCC passes's run. Note that "...UpdateResult" isn't a *great*
name here... suggestions very welcome.
I tried a pretty frustrating number of different data structures and such
for the innards of the update result. Every other one failed for one
reason or another. Sometimes I just couldn't keep the layers of
complexity right in my head. The thing that really worked was to just
directly provide access to the underlying structures used to walk the
call graph so that their updates could be informed by the *particular*
nature of the change to the graph.
The technique for how to make the pass management infrastructure cope
with mutating graphs was also something that took a really, really large
number of iterations to get to a place where I was happy. Here are some
of the considerations that drove the design:
- We operate at three levels within the infrastructure: RefSCC, SCC, and
Node. In each case, we are working bottom up and so we want to
continue to iterate on the "lowest" node as the graph changes. Look at
how we iterate over nodes in an SCC running function passes as those
function passes mutate the CG. We continue to iterate on the "lowest"
SCC, which is the one that continues to contain the function just
processed.
- The call graph structure re-uses SCCs (and RefSCCs) during mutation
events for the *highest* entry in the resulting new subgraph, not the
lowest. This means that it is necessary to continually update the
current SCC or RefSCC as it shifts. This is really surprising and
subtle, and took a long time for me to work out. I actually tried
changing the call graph to provide the opposite behavior, and it
breaks *EVERYTHING*. The graph update algorithms are really deeply
tied to this particualr pattern.
- When SCCs or RefSCCs are split apart and refined and we continually
re-pin our processing to the bottom one in the subgraph, we need to
enqueue the newly formed SCCs and RefSCCs for subsequent processing.
Queuing them presents a few challenges:
1) SCCs and RefSCCs use wildly different iteration strategies at
a high level. We end up needing to converge them on worklist
approaches that can be extended in order to be able to handle the
mutations.
2) The order of the enqueuing need to remain bottom-up post-order so
that we don't get surprising order of visitation for things like
the inliner.
3) We need the worklists to have set semantics so we don't duplicate
things endlessly. We don't need a *persistent* set though because
we always keep processing the bottom node!!!! This is super, super
surprising to me and took a long time to convince myself this is
correct, but I'm pretty sure it is... Once we sink down to the
bottom node, we can't re-split out the same node in any way, and
the postorder of the current queue is fixed and unchanging.
4) We need to make sure that the "current" SCC or RefSCC actually gets
enqueued here such that we re-visit it because we continue
processing a *new*, *bottom* SCC/RefSCC.
- We also need the ability to *skip* SCCs and RefSCCs that get merged
into a larger component. We even need the ability to skip *nodes* from
an SCC that are no longer part of that SCC.
This led to the design you see in the patch which uses SetVector-based
worklists. The RefSCC worklist is always empty until an update occurs
and is just used to handle those RefSCCs created by updates as the
others don't even exist yet and are formed on-demand during the
bottom-up walk. The SCC worklist is pre-populated from the RefSCC, and
we push new SCCs onto it and blacklist existing SCCs on it to get the
desired processing.
We then *directly* update these when updating the call graph as I was
never able to find a satisfactory abstraction around the update
strategy.
Finally, we need to compute the updates for function passes. This is
mostly used as an initial customer of all the update mechanisms to drive
their design to at least cover some real set of use cases. There are
a bunch of interesting things that came out of doing this:
- It is really nice to do this a function at a time because that
function is likely hot in the cache. This means we want even the
function pass adaptor to support online updates to the call graph!
- To update the call graph after arbitrary function pass mutations is
quite hard. We have to build a fairly comprehensive set of
data structures and then process them. Fortunately, some of this code
is related to the code for building the cal graph in the first place.
Unfortunately, very little of it makes any sense to share because the
nature of what we're doing is so very different. I've factored out the
one part that made sense at least.
- We need to transfer these updates into the various structures for the
CGSCC pass manager. Once those were more sanely worked out, this
became relatively easier. But some of those needs necessitated changes
to the LazyCallGraph interface to make it significantly easier to
extract the changed SCCs from an update operation.
- We also need to update the CGSCC analysis manager as the shape of the
graph changes. When an SCC is merged away we need to clear analyses
associated with it from the analysis manager which we didn't have
support for in the analysis manager infrsatructure. New SCCs are easy!
But then we have the case that the original SCC has its shape changed
but remains in the call graph. There we need to *invalidate* the
analyses associated with it.
- We also need to invalidate analyses after we *finish* processing an
SCC. But the analyses we need to invalidate here are *only those for
the newly updated SCC*!!! Because we only continue processing the
bottom SCC, if we split SCCs apart the original one gets invalidated
once when its shape changes and is not processed farther so its
analyses will be correct. It is the bottom SCC which continues being
processed and needs to have the "normal" invalidation done based on
the preserved analyses set.
All of this is mostly background and context for the changes here.
Many thanks to all the reviewers who helped here. Especially Sanjoy who
caught several interesting bugs in the graph algorithms, David, Sean,
and others who all helped with feedback.
Differential Revision: http://reviews.llvm.org/D21464
llvm-svn: 279618
2016-08-24 17:37:14 +08:00
|
|
|
Result run(LazyCallGraph::SCC &, CGSCCAnalysisManager &, LazyCallGraph &G) {
|
2016-06-17 08:11:01 +08:00
|
|
|
return Result();
|
|
|
|
}
|
2015-01-06 10:50:06 +08:00
|
|
|
static StringRef name() { return "NoOpCGSCCAnalysis"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op function pass which does nothing.
|
2014-01-12 17:34:22 +08:00
|
|
|
struct NoOpFunctionPass {
|
2016-08-09 08:28:15 +08:00
|
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {
|
2016-06-17 08:11:01 +08:00
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|
2014-01-12 17:34:22 +08:00
|
|
|
static StringRef name() { return "NoOpFunctionPass"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op function analysis.
|
2016-03-11 18:33:22 +08:00
|
|
|
class NoOpFunctionAnalysis : public AnalysisInfoMixin<NoOpFunctionAnalysis> {
|
|
|
|
friend AnalysisInfoMixin<NoOpFunctionAnalysis>;
|
2016-11-24 01:53:26 +08:00
|
|
|
static AnalysisKey Key;
|
2016-03-11 18:22:49 +08:00
|
|
|
|
|
|
|
public:
|
2015-01-06 10:50:06 +08:00
|
|
|
struct Result {};
|
2016-08-09 08:28:15 +08:00
|
|
|
Result run(Function &, FunctionAnalysisManager &) { return Result(); }
|
2015-01-06 10:50:06 +08:00
|
|
|
static StringRef name() { return "NoOpFunctionAnalysis"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op loop pass which does nothing.
|
2016-02-25 15:23:08 +08:00
|
|
|
struct NoOpLoopPass {
|
2017-01-11 14:23:21 +08:00
|
|
|
PreservedAnalyses run(Loop &L, LoopAnalysisManager &,
|
|
|
|
LoopStandardAnalysisResults &, LPMUpdater &) {
|
2016-06-17 08:11:01 +08:00
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|
2016-02-25 15:23:08 +08:00
|
|
|
static StringRef name() { return "NoOpLoopPass"; }
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// No-op loop analysis.
|
2016-03-11 18:33:22 +08:00
|
|
|
class NoOpLoopAnalysis : public AnalysisInfoMixin<NoOpLoopAnalysis> {
|
|
|
|
friend AnalysisInfoMixin<NoOpLoopAnalysis>;
|
2016-11-24 01:53:26 +08:00
|
|
|
static AnalysisKey Key;
|
2016-03-11 18:22:49 +08:00
|
|
|
|
|
|
|
public:
|
2016-02-25 15:23:08 +08:00
|
|
|
struct Result {};
|
2017-01-11 14:23:21 +08:00
|
|
|
Result run(Loop &, LoopAnalysisManager &, LoopStandardAnalysisResults &) {
|
|
|
|
return Result();
|
|
|
|
}
|
2016-02-25 15:23:08 +08:00
|
|
|
static StringRef name() { return "NoOpLoopAnalysis"; }
|
|
|
|
};
|
|
|
|
|
2016-11-24 01:53:26 +08:00
|
|
|
AnalysisKey NoOpModuleAnalysis::Key;
|
|
|
|
AnalysisKey NoOpCGSCCAnalysis::Key;
|
|
|
|
AnalysisKey NoOpFunctionAnalysis::Key;
|
|
|
|
AnalysisKey NoOpLoopAnalysis::Key;
|
2016-03-11 18:22:49 +08:00
|
|
|
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
} // End anonymous namespace.
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
void PassBuilder::invokePeepholeEPCallbacks(
|
|
|
|
FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
|
|
|
|
for (auto &C : PeepholeEPCallbacks)
|
|
|
|
C(FPM, Level);
|
|
|
|
}
|
|
|
|
|
2015-03-07 17:02:36 +08:00
|
|
|
void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
|
2016-06-17 15:15:29 +08:00
|
|
|
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
2016-02-18 17:45:17 +08:00
|
|
|
MAM.registerPass([&] { return CREATE_PASS; });
|
2015-01-06 10:21:37 +08:00
|
|
|
#include "PassRegistry.def"
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : ModuleAnalysisRegistrationCallbacks)
|
|
|
|
C(MAM);
|
2015-01-06 10:21:37 +08:00
|
|
|
}
|
|
|
|
|
2015-03-07 17:02:36 +08:00
|
|
|
void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
|
2016-06-17 15:15:29 +08:00
|
|
|
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
|
2016-02-18 17:45:17 +08:00
|
|
|
CGAM.registerPass([&] { return CREATE_PASS; });
|
2015-01-06 10:21:37 +08:00
|
|
|
#include "PassRegistry.def"
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : CGSCCAnalysisRegistrationCallbacks)
|
|
|
|
C(CGAM);
|
2015-01-06 10:21:37 +08:00
|
|
|
}
|
|
|
|
|
2015-03-07 17:02:36 +08:00
|
|
|
void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
|
2016-06-17 15:15:29 +08:00
|
|
|
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
2016-02-18 17:45:17 +08:00
|
|
|
FAM.registerPass([&] { return CREATE_PASS; });
|
2015-01-06 10:21:37 +08:00
|
|
|
#include "PassRegistry.def"
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : FunctionAnalysisRegistrationCallbacks)
|
|
|
|
C(FAM);
|
2015-01-06 10:21:37 +08:00
|
|
|
}
|
|
|
|
|
2016-02-25 15:23:08 +08:00
|
|
|
void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
|
2016-06-17 15:15:29 +08:00
|
|
|
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
|
2016-02-25 15:23:08 +08:00
|
|
|
LAM.registerPass([&] { return CREATE_PASS; });
|
|
|
|
#include "PassRegistry.def"
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : LoopAnalysisRegistrationCallbacks)
|
|
|
|
C(LAM);
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
FunctionPassManager
|
|
|
|
PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
|
2017-07-30 12:55:39 +08:00
|
|
|
ThinLTOPhase Phase,
|
|
|
|
bool DebugLogging) {
|
2016-12-22 14:59:15 +08:00
|
|
|
assert(Level != O0 && "Must request optimizations!");
|
|
|
|
FunctionPassManager FPM(DebugLogging);
|
|
|
|
|
|
|
|
// Form SSA out of local memory accesses after breaking apart aggregates into
|
|
|
|
// scalars.
|
|
|
|
FPM.addPass(SROA());
|
|
|
|
|
|
|
|
// Catch trivial redundancies
|
2017-06-10 23:20:03 +08:00
|
|
|
FPM.addPass(EarlyCSEPass(EnableEarlyCSEMemSSA));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2017-06-02 07:08:14 +08:00
|
|
|
// Hoisting of scalars and load expressions.
|
|
|
|
if (EnableGVNHoist)
|
|
|
|
FPM.addPass(GVNHoistPass());
|
|
|
|
|
2017-06-04 07:18:29 +08:00
|
|
|
// Global value numbering based sinking.
|
|
|
|
if (EnableGVNSink) {
|
|
|
|
FPM.addPass(GVNSinkPass());
|
|
|
|
FPM.addPass(SimplifyCFGPass());
|
|
|
|
}
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Speculative execution if the target has divergent branches; otherwise nop.
|
|
|
|
FPM.addPass(SpeculativeExecutionPass());
|
|
|
|
|
|
|
|
// Optimize based on known information about branches, and cleanup afterward.
|
|
|
|
FPM.addPass(JumpThreadingPass());
|
|
|
|
FPM.addPass(CorrelatedValuePropagationPass());
|
|
|
|
FPM.addPass(SimplifyCFGPass());
|
2018-01-25 20:06:32 +08:00
|
|
|
if (Level == O3)
|
|
|
|
FPM.addPass(AggressiveInstCombinePass());
|
2016-12-22 14:59:15 +08:00
|
|
|
FPM.addPass(InstCombinePass());
|
|
|
|
|
|
|
|
if (!isOptimizingForSize(Level))
|
|
|
|
FPM.addPass(LibCallsShrinkWrapPass());
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(FPM, Level);
|
|
|
|
|
2017-10-24 06:21:29 +08:00
|
|
|
// For PGO use pipeline, try to optimize memory intrinsics such as memcpy
|
|
|
|
// using the size value profile. Don't perform this when optimizing for size.
|
2019-03-05 04:21:27 +08:00
|
|
|
if (PGOOpt && PGOOpt->Action == PGOOptions::IRUse &&
|
2017-10-24 06:21:29 +08:00
|
|
|
!isOptimizingForSize(Level))
|
|
|
|
FPM.addPass(PGOMemOPSizeOpt());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
FPM.addPass(TailCallElimPass());
|
|
|
|
FPM.addPass(SimplifyCFGPass());
|
|
|
|
|
|
|
|
// Form canonically associated expression trees, and simplify the trees using
|
|
|
|
// basic mathematical properties. For example, this will form (nearly)
|
|
|
|
// minimal multiplication trees.
|
|
|
|
FPM.addPass(ReassociatePass());
|
|
|
|
|
|
|
|
// Add the primary loop simplification pipeline.
|
|
|
|
// FIXME: Currently this is split into two loop pass pipelines because we run
|
2018-05-30 10:46:45 +08:00
|
|
|
// some function passes in between them. These can and should be removed
|
|
|
|
// and/or replaced by scheduling the loop pass equivalents in the correct
|
|
|
|
// positions. But those equivalent passes aren't powerful enough yet.
|
|
|
|
// Specifically, `SimplifyCFGPass` and `InstCombinePass` are currently still
|
|
|
|
// used. We have `LoopSimplifyCFGPass` which isn't yet powerful enough yet to
|
|
|
|
// fully replace `SimplifyCFGPass`, and the closest to the other we have is
|
|
|
|
// `LoopInstSimplify`.
|
2016-12-22 14:59:15 +08:00
|
|
|
LoopPassManager LPM1(DebugLogging), LPM2(DebugLogging);
|
|
|
|
|
2018-05-30 10:46:45 +08:00
|
|
|
// Simplify the loop body. We do this initially to clean up after other loop
|
|
|
|
// passes run, either when iterating on a loop or on inner loops with
|
|
|
|
// implications on the outer loop.
|
|
|
|
LPM1.addPass(LoopInstSimplifyPass());
|
|
|
|
LPM1.addPass(LoopSimplifyCFGPass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Rotate Loop - disable header duplication at -Oz
|
|
|
|
LPM1.addPass(LoopRotatePass(Level != Oz));
|
|
|
|
LPM1.addPass(LICMPass());
|
2017-05-26 09:24:11 +08:00
|
|
|
LPM1.addPass(SimpleLoopUnswitchPass());
|
2016-12-22 14:59:15 +08:00
|
|
|
LPM2.addPass(IndVarSimplifyPass());
|
2017-01-27 07:21:17 +08:00
|
|
|
LPM2.addPass(LoopIdiomRecognizePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : LateLoopOptimizationsEPCallbacks)
|
|
|
|
C(LPM2, Level);
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
LPM2.addPass(LoopDeletionPass());
|
2017-07-30 12:55:39 +08:00
|
|
|
// Do not enable unrolling in PreLinkThinLTO phase during sample PGO
|
2017-07-08 04:53:10 +08:00
|
|
|
// because it changes IR to makes profile annotation in back compile
|
|
|
|
// inaccurate.
|
2019-03-05 04:21:27 +08:00
|
|
|
if (Phase != ThinLTOPhase::PreLink || !PGOOpt ||
|
|
|
|
PGOOpt->Action != PGOOptions::SampleUse)
|
2017-08-03 04:35:29 +08:00
|
|
|
LPM2.addPass(LoopFullUnrollPass(Level));
|
2017-01-27 07:21:17 +08:00
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : LoopOptimizerEndEPCallbacks)
|
|
|
|
C(LPM2, Level);
|
|
|
|
|
2017-02-10 07:54:57 +08:00
|
|
|
// We provide the opt remark emitter pass for LICM to use. We only need to do
|
|
|
|
// this once as it is immutable.
|
|
|
|
FPM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>());
|
2017-12-29 16:16:06 +08:00
|
|
|
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), DebugLogging));
|
2016-12-22 14:59:15 +08:00
|
|
|
FPM.addPass(SimplifyCFGPass());
|
|
|
|
FPM.addPass(InstCombinePass());
|
2017-12-29 16:16:06 +08:00
|
|
|
FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), DebugLogging));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
|
|
|
// Eliminate redundancies.
|
|
|
|
if (Level != O1) {
|
|
|
|
// These passes add substantial compile time so skip them at O1.
|
|
|
|
FPM.addPass(MergedLoadStoreMotionPass());
|
2017-05-23 07:41:40 +08:00
|
|
|
if (RunNewGVN)
|
|
|
|
FPM.addPass(NewGVNPass());
|
|
|
|
else
|
|
|
|
FPM.addPass(GVN());
|
2016-12-22 14:59:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Specially optimize memory movement as it doesn't look like dataflow in SSA.
|
|
|
|
FPM.addPass(MemCpyOptPass());
|
|
|
|
|
|
|
|
// Sparse conditional constant propagation.
|
|
|
|
// FIXME: It isn't clear why we do this *after* loop passes rather than
|
|
|
|
// before...
|
|
|
|
FPM.addPass(SCCPPass());
|
|
|
|
|
|
|
|
// Delete dead bit computations (instcombine runs after to fold away the dead
|
|
|
|
// computations, and then ADCE will run later to exploit any new DCE
|
|
|
|
// opportunities that creates).
|
|
|
|
FPM.addPass(BDCEPass());
|
|
|
|
|
|
|
|
// Run instcombine after redundancy and dead bit elimination to exploit
|
|
|
|
// opportunities opened up by them.
|
|
|
|
FPM.addPass(InstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(FPM, Level);
|
2016-12-22 14:59:15 +08:00
|
|
|
|
|
|
|
// Re-consider control flow based optimizations after redundancy elimination,
|
|
|
|
// redo DCE, etc.
|
|
|
|
FPM.addPass(JumpThreadingPass());
|
|
|
|
FPM.addPass(CorrelatedValuePropagationPass());
|
|
|
|
FPM.addPass(DSEPass());
|
2017-12-29 16:16:06 +08:00
|
|
|
FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass(), DebugLogging));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : ScalarOptimizerLateEPCallbacks)
|
|
|
|
C(FPM, Level);
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Finally, do an expensive DCE pass to catch all the dead code exposed by
|
|
|
|
// the simplifications and basic cleanup after all the simplifications.
|
|
|
|
FPM.addPass(ADCEPass());
|
|
|
|
FPM.addPass(SimplifyCFGPass());
|
|
|
|
FPM.addPass(InstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(FPM, Level);
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2018-09-05 01:19:13 +08:00
|
|
|
if (EnableCHR && Level == O3 && PGOOpt &&
|
2019-03-05 04:21:27 +08:00
|
|
|
(PGOOpt->Action == PGOOptions::IRUse ||
|
|
|
|
PGOOpt->Action == PGOOptions::SampleUse))
|
2018-09-05 01:19:13 +08:00
|
|
|
FPM.addPass(ControlHeightReductionPass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
return FPM;
|
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging,
|
|
|
|
PassBuilder::OptimizationLevel Level,
|
2019-03-05 04:21:27 +08:00
|
|
|
bool RunProfileGen, bool IsCS,
|
|
|
|
std::string ProfileFile,
|
Add a flag to remap manglings when reading profile data information.
This can be used to preserve profiling information across codebase
changes that have widespread impact on mangled names, but across which
most profiling data should still be usable. For example, when switching
from libstdc++ to libc++, or from the old libstdc++ ABI to the new ABI,
or even from a 32-bit to a 64-bit build.
The user can provide a remapping file specifying parts of mangled names
that should be treated as equivalent (eg, std::__1 should be treated as
equivalent to std::__cxx11), and profile data will be treated as
applying to a particular function if its name is equivalent to the name
of a function in the profile data under the provided equivalences. See
the documentation change for a description of how this is configured.
Remapping is supported for both sample-based profiling and instruction
profiling. We do not support remapping indirect branch target
information, but all other profile data should be remapped
appropriately.
Support is only added for the new pass manager. If someone wants to also
add support for this for the old pass manager, doing so should be
straightforward.
This is the LLVM side of Clang r344199.
Reviewers: davidxl, tejohnson, dlj, erik.pilkington
Subscribers: mehdi_amini, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51249
llvm-svn: 344200
2018-10-11 07:13:47 +08:00
|
|
|
std::string ProfileRemappingFile) {
|
2017-02-13 23:26:22 +08:00
|
|
|
// Generally running simplification passes and the inliner with an high
|
|
|
|
// threshold results in smaller executables, but there may be cases where
|
|
|
|
// the size grows, so let's be conservative here and skip this simplification
|
2019-03-05 04:21:27 +08:00
|
|
|
// at -Os/Oz. We will not do this inline for context sensistive PGO (when
|
|
|
|
// IsCS is true).
|
|
|
|
if (!isOptimizingForSize(Level) && !IsCS) {
|
2017-02-13 23:26:22 +08:00
|
|
|
InlineParams IP;
|
|
|
|
|
|
|
|
// In the old pass manager, this is a cl::opt. Should still this be one?
|
|
|
|
IP.DefaultThreshold = 75;
|
|
|
|
|
|
|
|
// FIXME: The hint threshold has the same value used by the regular inliner.
|
|
|
|
// This should probably be lowered after performance testing.
|
|
|
|
// FIXME: this comment is cargo culted from the old pass manager, revisit).
|
|
|
|
IP.HintThreshold = 325;
|
|
|
|
|
|
|
|
CGSCCPassManager CGPipeline(DebugLogging);
|
|
|
|
|
|
|
|
CGPipeline.addPass(InlinerPass(IP));
|
|
|
|
|
|
|
|
FunctionPassManager FPM;
|
|
|
|
FPM.addPass(SROA());
|
|
|
|
FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies.
|
|
|
|
FPM.addPass(SimplifyCFGPass()); // Merge & remove basic blocks.
|
|
|
|
FPM.addPass(InstCombinePass()); // Combine silly sequences.
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(FPM, Level);
|
2017-02-13 23:26:22 +08:00
|
|
|
|
|
|
|
CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM)));
|
|
|
|
|
|
|
|
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPipeline)));
|
|
|
|
}
|
|
|
|
|
2017-05-25 15:15:09 +08:00
|
|
|
// Delete anything that is now dead to make sure that we don't instrument
|
|
|
|
// dead code. Instrumentation can end up keeping dead code around and
|
|
|
|
// dramatically increase code size.
|
|
|
|
MPM.addPass(GlobalDCEPass());
|
|
|
|
|
2017-02-13 23:26:22 +08:00
|
|
|
if (RunProfileGen) {
|
2019-03-05 04:21:27 +08:00
|
|
|
MPM.addPass(PGOInstrumentationGen(IsCS));
|
2017-02-13 23:26:22 +08:00
|
|
|
|
2017-06-25 08:26:43 +08:00
|
|
|
FunctionPassManager FPM;
|
2017-12-29 16:16:06 +08:00
|
|
|
FPM.addPass(
|
|
|
|
createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging));
|
2017-06-25 08:26:43 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
|
|
|
|
2017-02-13 23:26:22 +08:00
|
|
|
// Add the profile lowering pass.
|
|
|
|
InstrProfOptions Options;
|
2019-03-05 04:21:27 +08:00
|
|
|
if (!ProfileFile.empty())
|
|
|
|
Options.InstrProfileOutput = ProfileFile;
|
2017-06-25 08:26:43 +08:00
|
|
|
Options.DoCounterPromotion = true;
|
2019-03-05 04:21:27 +08:00
|
|
|
Options.UseBFIInPromotion = IsCS;
|
|
|
|
MPM.addPass(InstrProfiling(Options, IsCS));
|
|
|
|
} else if (!ProfileFile.empty())
|
|
|
|
MPM.addPass(PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS));
|
2017-02-13 23:26:22 +08:00
|
|
|
}
|
|
|
|
|
2017-06-28 21:33:49 +08:00
|
|
|
static InlineParams
|
|
|
|
getInlineParamsFromOptLevel(PassBuilder::OptimizationLevel Level) {
|
|
|
|
auto O3 = PassBuilder::O3;
|
|
|
|
unsigned OptLevel = Level > O3 ? 2 : Level;
|
|
|
|
unsigned SizeLevel = Level > O3 ? Level - O3 : 0;
|
|
|
|
return getInlineParams(OptLevel, SizeLevel);
|
|
|
|
}
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
ModulePassManager
|
2017-06-01 19:39:39 +08:00
|
|
|
PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
|
2017-07-30 12:55:39 +08:00
|
|
|
ThinLTOPhase Phase,
|
|
|
|
bool DebugLogging) {
|
2016-12-22 14:59:15 +08:00
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
2019-03-05 04:21:27 +08:00
|
|
|
bool HasSampleProfile = PGOOpt && (PGOOpt->Action == PGOOptions::SampleUse);
|
2019-02-05 12:09:19 +08:00
|
|
|
|
|
|
|
// In ThinLTO mode, when flattened profile is used, all the available
|
|
|
|
// profile information will be annotated in PreLink phase so there is
|
|
|
|
// no need to load the profile again in PostLink.
|
|
|
|
bool LoadSampleProfile =
|
|
|
|
HasSampleProfile &&
|
|
|
|
!(FlattenedProfileUsed && Phase == ThinLTOPhase::PostLink);
|
|
|
|
|
|
|
|
// During the ThinLTO backend phase we perform early indirect call promotion
|
|
|
|
// here, before globalopt. Otherwise imported available_externally functions
|
|
|
|
// look unreferenced and are removed. If we are going to load the sample
|
|
|
|
// profile then defer until later.
|
|
|
|
// TODO: See if we can move later and consolidate with the location where
|
|
|
|
// we perform ICP when we are loading a sample profile.
|
|
|
|
// TODO: We pass HasSampleProfile (whether there was a sample profile file
|
|
|
|
// passed to the compile) to the SamplePGO flag of ICP. This is used to
|
|
|
|
// determine whether the new direct calls are annotated with prof metadata.
|
|
|
|
// Ideally this should be determined from whether the IR is annotated with
|
|
|
|
// sample profile, and not whether the a sample profile was provided on the
|
|
|
|
// command line. E.g. for flattened profiles where we will not be reloading
|
|
|
|
// the sample profile in the ThinLTO backend, we ideally shouldn't have to
|
|
|
|
// provide the sample profile file.
|
|
|
|
if (Phase == ThinLTOPhase::PostLink && !LoadSampleProfile)
|
|
|
|
MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */, HasSampleProfile));
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Do basic inference of function attributes from known properties of system
|
|
|
|
// libraries and other oracles.
|
|
|
|
MPM.addPass(InferFunctionAttrsPass());
|
|
|
|
|
|
|
|
// Create an early function pass manager to cleanup the output of the
|
|
|
|
// frontend.
|
2016-02-29 06:16:03 +08:00
|
|
|
FunctionPassManager EarlyFPM(DebugLogging);
|
|
|
|
EarlyFPM.addPass(SimplifyCFGPass());
|
|
|
|
EarlyFPM.addPass(SROA());
|
|
|
|
EarlyFPM.addPass(EarlyCSEPass());
|
|
|
|
EarlyFPM.addPass(LowerExpectIntrinsicPass());
|
Recommit r317351 : Add CallSiteSplitting pass
This recommit r317351 after fixing a buildbot failure.
Original commit message:
Summary:
This change add a pass which tries to split a call-site to pass
more constrained arguments if its argument is predicated in the control flow
so that we can expose better context to the later passes (e.g, inliner, jump
threading, or IPA-CP based function cloning, etc.).
As of now we support two cases :
1) If a call site is dominated by an OR condition and if any of its arguments
are predicated on this OR condition, try to split the condition with more
constrained arguments. For example, in the code below, we try to split the
call site since we can predicate the argument (ptr) based on the OR condition.
Split from :
if (!ptr || c)
callee(ptr);
to :
if (!ptr)
callee(null ptr) // set the known constant value
else if (c)
callee(nonnull ptr) // set non-null attribute in the argument
2) We can also split a call-site based on constant incoming values of a PHI
For example,
from :
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2, label %BB1
BB1:
br label %BB2
BB2:
%p = phi i32 [ 0, %BB0 ], [ 1, %BB1 ]
call void @bar(i32 %p)
to
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2-split0, label %BB1
BB1:
br label %BB2-split1
BB2-split0:
call void @bar(i32 0)
br label %BB2
BB2-split1:
call void @bar(i32 1)
br label %BB2
BB2:
%p = phi i32 [ 0, %BB2-split0 ], [ 1, %BB2-split1 ]
llvm-svn: 317362
2017-11-04 04:41:16 +08:00
|
|
|
if (Level == O3)
|
|
|
|
EarlyFPM.addPass(CallSiteSplittingPass());
|
|
|
|
|
2017-08-08 04:23:20 +08:00
|
|
|
// In SamplePGO ThinLTO backend, we need instcombine before profile annotation
|
|
|
|
// to convert bitcast to direct calls so that they can be inlined during the
|
|
|
|
// profile annotation prepration step.
|
|
|
|
// More details about SamplePGO design can be found in:
|
|
|
|
// https://research.google.com/pubs/pub45290.html
|
|
|
|
// FIXME: revisit how SampleProfileLoad/Inliner/ICP is structured.
|
2019-02-05 12:09:19 +08:00
|
|
|
if (LoadSampleProfile)
|
2017-08-08 04:23:20 +08:00
|
|
|
EarlyFPM.addPass(InstCombinePass());
|
2016-02-29 06:16:03 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM)));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2019-02-05 12:09:19 +08:00
|
|
|
if (LoadSampleProfile) {
|
2017-08-08 04:23:20 +08:00
|
|
|
// Annotate sample profile right after early FPM to ensure freshness of
|
|
|
|
// the debug info.
|
2019-03-05 04:21:27 +08:00
|
|
|
MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile,
|
2019-02-05 12:09:19 +08:00
|
|
|
PGOOpt->ProfileRemappingFile,
|
|
|
|
Phase == ThinLTOPhase::PreLink));
|
2017-08-08 04:23:20 +08:00
|
|
|
// Do not invoke ICP in the ThinLTOPrelink phase as it makes it hard
|
|
|
|
// for the profile annotation to be accurate in the ThinLTO backend.
|
|
|
|
if (Phase != ThinLTOPhase::PreLink)
|
|
|
|
// We perform early indirect call promotion here, before globalopt.
|
|
|
|
// This is important for the ThinLTO backend phase because otherwise
|
|
|
|
// imported available_externally functions look unreferenced and are
|
|
|
|
// removed.
|
|
|
|
MPM.addPass(PGOIndirectCallPromotion(Phase == ThinLTOPhase::PostLink,
|
2019-02-05 12:09:19 +08:00
|
|
|
true /* SamplePGO */));
|
2017-08-08 04:23:20 +08:00
|
|
|
}
|
|
|
|
|
2018-01-24 18:33:39 +08:00
|
|
|
// Interprocedural constant propagation now that basic cleanup has occurred
|
2016-12-22 14:59:15 +08:00
|
|
|
// and prior to optimizing globals.
|
|
|
|
// FIXME: This position in the pipeline hasn't been carefully considered in
|
|
|
|
// years, it should be re-analyzed.
|
|
|
|
MPM.addPass(IPSCCPPass());
|
|
|
|
|
2017-10-25 21:40:08 +08:00
|
|
|
// Attach metadata to indirect call sites indicating the set of functions
|
|
|
|
// they may target at run-time. This should follow IPSCCP.
|
|
|
|
MPM.addPass(CalledValuePropagationPass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Optimize globals to try and fold them into constants.
|
|
|
|
MPM.addPass(GlobalOptPass());
|
|
|
|
|
|
|
|
// Promote any localized globals to SSA registers.
|
|
|
|
// FIXME: Should this instead by a run of SROA?
|
|
|
|
// FIXME: We should probably run instcombine and simplify-cfg afterward to
|
|
|
|
// delete control flows that are dead once globals have been folded to
|
|
|
|
// constants.
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass()));
|
|
|
|
|
|
|
|
// Remove any dead arguments exposed by cleanups and constand folding
|
|
|
|
// globals.
|
|
|
|
MPM.addPass(DeadArgumentEliminationPass());
|
|
|
|
|
|
|
|
// Create a small function pass pipeline to cleanup after all the global
|
|
|
|
// optimizations.
|
|
|
|
FunctionPassManager GlobalCleanupPM(DebugLogging);
|
|
|
|
GlobalCleanupPM.addPass(InstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(GlobalCleanupPM, Level);
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
GlobalCleanupPM.addPass(SimplifyCFGPass());
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM)));
|
|
|
|
|
2017-08-02 09:28:31 +08:00
|
|
|
// Add all the requested passes for instrumentation PGO, if requested.
|
|
|
|
if (PGOOpt && Phase != ThinLTOPhase::PostLink &&
|
2019-03-05 04:21:27 +08:00
|
|
|
(PGOOpt->Action == PGOOptions::IRInstr ||
|
|
|
|
PGOOpt->Action == PGOOptions::IRUse)) {
|
|
|
|
addPGOInstrPasses(MPM, DebugLogging, Level,
|
|
|
|
/* RunProfileGen */ PGOOpt->Action == PGOOptions::IRInstr,
|
|
|
|
/* IsCS */ false, PGOOpt->ProfileFile,
|
Add a flag to remap manglings when reading profile data information.
This can be used to preserve profiling information across codebase
changes that have widespread impact on mangled names, but across which
most profiling data should still be usable. For example, when switching
from libstdc++ to libc++, or from the old libstdc++ ABI to the new ABI,
or even from a 32-bit to a 64-bit build.
The user can provide a remapping file specifying parts of mangled names
that should be treated as equivalent (eg, std::__1 should be treated as
equivalent to std::__cxx11), and profile data will be treated as
applying to a particular function if its name is equivalent to the name
of a function in the profile data under the provided equivalences. See
the documentation change for a description of how this is configured.
Remapping is supported for both sample-based profiling and instruction
profiling. We do not support remapping indirect branch target
information, but all other profile data should be remapped
appropriately.
Support is only added for the new pass manager. If someone wants to also
add support for this for the old pass manager, doing so should be
straightforward.
This is the LLVM side of Clang r344199.
Reviewers: davidxl, tejohnson, dlj, erik.pilkington
Subscribers: mehdi_amini, steven_wu, dexonsmith, llvm-commits
Differential Revision: https://reviews.llvm.org/D51249
llvm-svn: 344200
2018-10-11 07:13:47 +08:00
|
|
|
PGOOpt->ProfileRemappingFile);
|
2017-08-02 09:28:31 +08:00
|
|
|
MPM.addPass(PGOIndirectCallPromotion(false, false));
|
2017-06-01 19:39:39 +08:00
|
|
|
}
|
2019-03-05 04:21:27 +08:00
|
|
|
if (PGOOpt && Phase != ThinLTOPhase::PostLink &&
|
|
|
|
PGOOpt->CSAction == PGOOptions::CSIRInstr)
|
|
|
|
MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile));
|
2017-02-13 23:26:22 +08:00
|
|
|
|
2018-01-10 03:39:35 +08:00
|
|
|
// Synthesize function entry counts for non-PGO compilation.
|
|
|
|
if (EnableSyntheticCounts && !PGOOpt)
|
|
|
|
MPM.addPass(SyntheticCountsPropagation());
|
|
|
|
|
2017-02-12 13:34:04 +08:00
|
|
|
// Require the GlobalsAA analysis for the module so we can query it within
|
|
|
|
// the CGSCC pipeline.
|
|
|
|
MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>());
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2017-05-05 00:58:45 +08:00
|
|
|
// Require the ProfileSummaryAnalysis for the module so we can query it within
|
|
|
|
// the inliner pass.
|
|
|
|
MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Now begin the main postorder CGSCC pipeline.
|
|
|
|
// FIXME: The current CGSCC pipeline has its origins in the legacy pass
|
|
|
|
// manager and trying to emulate its precise behavior. Much of this doesn't
|
|
|
|
// make a lot of sense and we should revisit the core CGSCC structure.
|
|
|
|
CGSCCPassManager MainCGPipeline(DebugLogging);
|
|
|
|
|
|
|
|
// Note: historically, the PruneEH pass was run first to deduce nounwind and
|
|
|
|
// generally clean up exception handling overhead. It isn't clear this is
|
|
|
|
// valuable as the inliner doesn't currently care whether it is inlining an
|
|
|
|
// invoke or a call.
|
|
|
|
|
|
|
|
// Run the inliner first. The theory is that we are walking bottom-up and so
|
|
|
|
// the callees have already been fully optimized, and we want to inline them
|
|
|
|
// into the callers so that our optimizations can reflect that.
|
2017-07-30 12:55:39 +08:00
|
|
|
// For PreLinkThinLTO pass, we disable hot-caller heuristic for sample PGO
|
2017-07-08 04:53:10 +08:00
|
|
|
// because it makes profile annotation in the backend inaccurate.
|
|
|
|
InlineParams IP = getInlineParamsFromOptLevel(Level);
|
2019-03-05 04:21:27 +08:00
|
|
|
if (Phase == ThinLTOPhase::PreLink && PGOOpt &&
|
|
|
|
PGOOpt->Action == PGOOptions::SampleUse)
|
2017-07-08 04:53:10 +08:00
|
|
|
IP.HotCallSiteThreshold = 0;
|
|
|
|
MainCGPipeline.addPass(InlinerPass(IP));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
|
|
|
// Now deduce any function attributes based in the current code.
|
|
|
|
MainCGPipeline.addPass(PostOrderFunctionAttrsPass());
|
|
|
|
|
2017-02-10 07:54:57 +08:00
|
|
|
// When at O3 add argument promotion to the pass pipeline.
|
|
|
|
// FIXME: It isn't at all clear why this should be limited to O3.
|
|
|
|
if (Level == O3)
|
|
|
|
MainCGPipeline.addPass(ArgumentPromotionPass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Lastly, add the core function simplification pipeline nested inside the
|
|
|
|
// CGSCC walk.
|
|
|
|
MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor(
|
2017-07-30 12:55:39 +08:00
|
|
|
buildFunctionSimplificationPipeline(Level, Phase, DebugLogging)));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : CGSCCOptimizerLateEPCallbacks)
|
|
|
|
C(MainCGPipeline, Level);
|
|
|
|
|
2017-02-12 13:38:04 +08:00
|
|
|
// We wrap the CGSCC pipeline in a devirtualization repeater. This will try
|
|
|
|
// to detect when we devirtualize indirect calls and iterate the SCC passes
|
|
|
|
// in that case to try and catch knock-on inlining or function attrs
|
|
|
|
// opportunities. Then we add it to the module pipeline by walking the SCCs
|
|
|
|
// in postorder (or bottom-up).
|
2016-12-22 14:59:15 +08:00
|
|
|
MPM.addPass(
|
2017-02-12 13:38:04 +08:00
|
|
|
createModuleToPostOrderCGSCCPassAdaptor(createDevirtSCCRepeatedPass(
|
2017-08-11 13:47:13 +08:00
|
|
|
std::move(MainCGPipeline), MaxDevirtIterations)));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
return MPM;
|
|
|
|
}
|
|
|
|
|
2019-02-16 02:46:44 +08:00
|
|
|
ModulePassManager PassBuilder::buildModuleOptimizationPipeline(
|
|
|
|
OptimizationLevel Level, bool DebugLogging, bool LTOPreLink) {
|
2017-06-01 19:39:39 +08:00
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
|
|
|
// Optimize globals now that the module is fully simplified.
|
|
|
|
MPM.addPass(GlobalOptPass());
|
2017-10-06 02:36:01 +08:00
|
|
|
MPM.addPass(GlobalDCEPass());
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2017-05-23 00:41:57 +08:00
|
|
|
// Run partial inlining pass to partially inline functions that have
|
|
|
|
// large bodies.
|
|
|
|
if (RunPartialInlining)
|
|
|
|
MPM.addPass(PartialInlinerPass());
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
// Remove avail extern fns and globals definitions since we aren't compiling
|
|
|
|
// an object file for later LTO. For LTO we want to preserve these so they
|
|
|
|
// are eligible for inlining at link-time. Note if they are unreferenced they
|
|
|
|
// will be removed by GlobalDCE later, so this only impacts referenced
|
|
|
|
// available externally globals. Eventually they will be suppressed during
|
|
|
|
// codegen, but eliminating here enables more opportunity for GlobalDCE as it
|
|
|
|
// may make globals referenced by available external functions dead and saves
|
|
|
|
// running remaining passes on the eliminated functions.
|
2016-12-22 14:59:15 +08:00
|
|
|
MPM.addPass(EliminateAvailableExternallyPass());
|
|
|
|
|
2019-03-01 04:13:38 +08:00
|
|
|
if (EnableOrderFileInstrumentation)
|
|
|
|
MPM.addPass(InstrOrderFilePass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Do RPO function attribute inference across the module to forward-propagate
|
|
|
|
// attributes where applicable.
|
|
|
|
// FIXME: Is this really an optimization rather than a canonicalization?
|
|
|
|
MPM.addPass(ReversePostOrderFunctionAttrsPass());
|
|
|
|
|
2019-03-05 04:21:27 +08:00
|
|
|
// Do a post inline PGO instrumentation and use pass. This is a context
|
|
|
|
// sensitive PGO pass. We don't want to do this in LTOPreLink phrase as
|
|
|
|
// cross-module inline has not been done yet. The context sensitive
|
|
|
|
// instrumentation is after all the inlines are done.
|
|
|
|
if (!LTOPreLink && PGOOpt) {
|
|
|
|
if (PGOOpt->CSAction == PGOOptions::CSIRInstr)
|
|
|
|
addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ true,
|
|
|
|
/* IsCS */ true, PGOOpt->CSProfileGenFile,
|
|
|
|
PGOOpt->ProfileRemappingFile);
|
|
|
|
else if (PGOOpt->CSAction == PGOOptions::CSIRUse)
|
|
|
|
addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ false,
|
|
|
|
/* IsCS */ true, PGOOpt->ProfileFile,
|
|
|
|
PGOOpt->ProfileRemappingFile);
|
|
|
|
}
|
|
|
|
|
2017-02-12 13:34:04 +08:00
|
|
|
// Re-require GloblasAA here prior to function passes. This is particularly
|
2016-12-22 14:59:15 +08:00
|
|
|
// useful as the above will have inlined, DCE'ed, and function-attr
|
|
|
|
// propagated everything. We should at this point have a reasonably minimal
|
|
|
|
// and richly annotated call graph. By computing aliasing and mod/ref
|
|
|
|
// information for all local globals here, the late loop passes and notably
|
|
|
|
// the vectorizer will be able to use them to help recognize vectorizable
|
|
|
|
// memory operations.
|
2017-02-12 13:34:04 +08:00
|
|
|
MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>());
|
2016-12-22 14:59:15 +08:00
|
|
|
|
|
|
|
FunctionPassManager OptimizePM(DebugLogging);
|
|
|
|
OptimizePM.addPass(Float2IntPass());
|
|
|
|
// FIXME: We need to run some loop optimizations to re-rotate loops after
|
|
|
|
// simplify-cfg and others undo their rotation.
|
|
|
|
|
|
|
|
// Optimize the loop execution. These passes operate on entire loop nests
|
|
|
|
// rather than on each loop in an inside-out manner, and so they are actually
|
|
|
|
// function passes.
|
2017-01-27 08:50:21 +08:00
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : VectorizerStartEPCallbacks)
|
|
|
|
C(OptimizePM, Level);
|
|
|
|
|
2017-01-27 08:50:21 +08:00
|
|
|
// First rotate loops that may have been un-rotated by prior passes.
|
2017-12-29 16:16:06 +08:00
|
|
|
OptimizePM.addPass(
|
|
|
|
createFunctionToLoopPassAdaptor(LoopRotatePass(), DebugLogging));
|
2017-01-27 08:50:21 +08:00
|
|
|
|
|
|
|
// Distribute loops to allow partial vectorization. I.e. isolate dependences
|
|
|
|
// into separate loop that would otherwise inhibit vectorization. This is
|
|
|
|
// currently only performed for loops marked with the metadata
|
|
|
|
// llvm.loop.distribute=true or when -enable-loop-distribute is specified.
|
2016-12-22 14:59:15 +08:00
|
|
|
OptimizePM.addPass(LoopDistributePass());
|
2017-01-27 08:50:21 +08:00
|
|
|
|
|
|
|
// Now run the core loop vectorizer.
|
2016-12-22 14:59:15 +08:00
|
|
|
OptimizePM.addPass(LoopVectorizePass());
|
2017-01-27 08:50:21 +08:00
|
|
|
|
2017-01-27 09:32:26 +08:00
|
|
|
// Eliminate loads by forwarding stores from the previous iteration to loads
|
|
|
|
// of the current iteration.
|
|
|
|
OptimizePM.addPass(LoopLoadEliminationPass());
|
2017-01-27 08:50:21 +08:00
|
|
|
|
|
|
|
// Cleanup after the loop optimization passes.
|
2016-12-22 14:59:15 +08:00
|
|
|
OptimizePM.addPass(InstCombinePass());
|
|
|
|
|
2017-01-27 08:50:21 +08:00
|
|
|
// Now that we've formed fast to execute loop structures, we do further
|
|
|
|
// optimizations. These are run afterward as they might block doing complex
|
|
|
|
// analyses and transforms such as what are needed for loop vectorization.
|
|
|
|
|
2017-12-15 06:05:20 +08:00
|
|
|
// Cleanup after loop vectorization, etc. Simplification passes like CVP and
|
2017-11-16 00:33:11 +08:00
|
|
|
// GVN, loop transforms, and others have already run, so it's now better to
|
|
|
|
// convert to more optimized IR using more aggressive simplify CFG options.
|
2017-12-15 06:05:20 +08:00
|
|
|
// The extra sinking transform can create larger basic blocks, so do this
|
|
|
|
// before SLP vectorization.
|
2017-11-16 00:33:11 +08:00
|
|
|
OptimizePM.addPass(SimplifyCFGPass(SimplifyCFGOptions().
|
2017-12-15 06:05:20 +08:00
|
|
|
forwardSwitchCondToPhi(true).
|
|
|
|
convertSwitchToLookupTable(true).
|
|
|
|
needCanonicalLoops(false).
|
|
|
|
sinkCommonInsts(true)));
|
|
|
|
|
|
|
|
// Optimize parallel scalar instruction chains into SIMD instructions.
|
|
|
|
OptimizePM.addPass(SLPVectorizerPass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
OptimizePM.addPass(InstCombinePass());
|
|
|
|
|
|
|
|
// Unroll small loops to hide loop backedge latency and saturate any parallel
|
2017-01-27 08:50:21 +08:00
|
|
|
// execution resources of an out-of-order processor. We also then need to
|
|
|
|
// clean up redundancies and loop invariant code.
|
|
|
|
// FIXME: It would be really good to use a loop-integrated instruction
|
|
|
|
// combiner for cleanup here so that the unrolling and LICM can be pipelined
|
|
|
|
// across the loop nests.
|
2018-07-01 20:47:30 +08:00
|
|
|
// We do UnrollAndJam in a separate LPM to ensure it happens before unroll
|
|
|
|
if (EnableUnrollAndJam) {
|
|
|
|
OptimizePM.addPass(
|
|
|
|
createFunctionToLoopPassAdaptor(LoopUnrollAndJamPass(Level)));
|
|
|
|
}
|
2018-10-31 22:33:14 +08:00
|
|
|
OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level)));
|
[Unroll/UnrollAndJam/Vectorizer/Distribute] Add followup loop attributes.
When multiple loop transformation are defined in a loop's metadata, their order of execution is defined by the order of their respective passes in the pass pipeline. For instance, e.g.
#pragma clang loop unroll_and_jam(enable)
#pragma clang loop distribute(enable)
is the same as
#pragma clang loop distribute(enable)
#pragma clang loop unroll_and_jam(enable)
and will try to loop-distribute before Unroll-And-Jam because the LoopDistribute pass is scheduled after UnrollAndJam pass. UnrollAndJamPass only supports one inner loop, i.e. it will necessarily fail after loop distribution. It is not possible to specify another execution order. Also,t the order of passes in the pipeline is subject to change between versions of LLVM, optimization options and which pass manager is used.
This patch adds 'followup' attributes to various loop transformation passes. These attributes define which attributes the resulting loop of a transformation should have. For instance,
!0 = !{!0, !1, !2}
!1 = !{!"llvm.loop.unroll_and_jam.enable"}
!2 = !{!"llvm.loop.unroll_and_jam.followup_inner", !3}
!3 = !{!"llvm.loop.distribute.enable"}
defines a loop ID (!0) to be unrolled-and-jammed (!1) and then the attribute !3 to be added to the jammed inner loop, which contains the instruction to distribute the inner loop.
Currently, in both pass managers, pass execution is in a fixed order and UnrollAndJamPass will not execute again after LoopDistribute. We hope to fix this in the future by allowing pass managers to run passes until a fixpoint is reached, use Polly to perform these transformations, or add a loop transformation pass which takes the order issue into account.
For mandatory/forced transformations (e.g. by having been declared by #pragma omp simd), the user must be notified when a transformation could not be performed. It is not possible that the responsible pass emits such a warning because the transformation might be 'hidden' in a followup attribute when it is executed, or it is not present in the pipeline at all. For this reason, this patche introduces a WarnMissedTransformations pass, to warn about orphaned transformations.
Since this changes the user-visible diagnostic message when a transformation is applied, two test cases in the clang repository need to be updated.
To ensure that no other transformation is executed before the intended one, the attribute `llvm.loop.disable_nonforced` can be added which should disable transformation heuristics before the intended transformation is applied. E.g. it would be surprising if a loop is distributed before a #pragma unroll_and_jam is applied.
With more supported code transformations (loop fusion, interchange, stripmining, offloading, etc.), transformations can be used as building blocks for more complex transformations (e.g. stripmining+stripmining+interchange -> tiling).
Reviewed By: hfinkel, dmgreen
Differential Revision: https://reviews.llvm.org/D49281
Differential Revision: https://reviews.llvm.org/D55288
llvm-svn: 348944
2018-12-13 01:32:52 +08:00
|
|
|
OptimizePM.addPass(WarnMissedTransformationsPass());
|
2017-01-27 08:50:21 +08:00
|
|
|
OptimizePM.addPass(InstCombinePass());
|
2017-02-10 07:54:57 +08:00
|
|
|
OptimizePM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>());
|
2017-12-29 16:16:06 +08:00
|
|
|
OptimizePM.addPass(createFunctionToLoopPassAdaptor(LICMPass(), DebugLogging));
|
2016-12-22 14:59:15 +08:00
|
|
|
|
|
|
|
// Now that we've vectorized and unrolled loops, we may have more refined
|
|
|
|
// alignment information, try to re-derive it here.
|
|
|
|
OptimizePM.addPass(AlignmentFromAssumptionsPass());
|
|
|
|
|
2019-02-16 02:46:44 +08:00
|
|
|
// Split out cold code. Splitting is done late to avoid hiding context from
|
|
|
|
// other optimizations and inadvertently regressing performance. The tradeoff
|
|
|
|
// is that this has a higher code size cost than splitting early.
|
|
|
|
if (EnableHotColdSplit && !LTOPreLink)
|
|
|
|
MPM.addPass(HotColdSplittingPass());
|
|
|
|
|
2017-01-27 08:50:21 +08:00
|
|
|
// LoopSink pass sinks instructions hoisted by LICM, which serves as a
|
|
|
|
// canonicalization pass that enables other optimizations. As a result,
|
|
|
|
// LoopSink pass needs to be a very late IR pass to avoid undoing LICM
|
|
|
|
// result too early.
|
|
|
|
OptimizePM.addPass(LoopSinkPass());
|
|
|
|
|
|
|
|
// And finally clean up LCSSA form before generating code.
|
2018-06-30 07:36:03 +08:00
|
|
|
OptimizePM.addPass(InstSimplifyPass());
|
2017-01-27 08:50:21 +08:00
|
|
|
|
2017-09-09 21:38:18 +08:00
|
|
|
// This hoists/decomposes div/rem ops. It should run after other sink/hoist
|
|
|
|
// passes to avoid re-sinking, but before SimplifyCFG because it can allow
|
|
|
|
// flattening of blocks.
|
|
|
|
OptimizePM.addPass(DivRemPairsPass());
|
|
|
|
|
2017-04-26 20:02:41 +08:00
|
|
|
// LoopSink (and other loop passes since the last simplifyCFG) might have
|
|
|
|
// resulted in single-entry-single-exit or empty blocks. Clean up the CFG.
|
|
|
|
OptimizePM.addPass(SimplifyCFGPass());
|
|
|
|
|
Add a new pass to speculate around PHI nodes with constant (integer) operands when profitable.
The core idea is to (re-)introduce some redundancies where their cost is
hidden by the cost of materializing immediates for constant operands of
PHI nodes. When the cost of the redundancies is covered by this,
avoiding materializing the immediate has numerous benefits:
1) Less register pressure
2) Potential for further folding / combining
3) Potential for more efficient instructions due to immediate operand
As a motivating example, consider the remarkably different cost on x86
of a SHL instruction with an immediate operand versus a register
operand.
This pattern turns up surprisingly frequently, but is somewhat rarely
obvious as a significant performance problem.
The pass is entirely target independent, but it does rely on the target
cost model in TTI to decide when to speculate things around the PHI
node. I've included x86-focused tests, but any target that sets up its
immediate cost model should benefit from this pass.
There is probably more that can be done in this space, but the pass
as-is is enough to get some important performance on our internal
benchmarks, and should be generally performance neutral, but help with
more extensive benchmarking is always welcome.
One awkward part is that this pass has to be scheduled after
*everything* that can eliminate these kinds of redundancies. This
includes SimplifyCFG, GVN, etc. I'm open to suggestions about better
places to put this. We could in theory make it part of the codegen pass
pipeline, but there doesn't really seem to be a good reason for that --
it isn't "lowering" in any sense and only relies on pretty standard cost
model based TTI queries, so it seems to fit well with the "optimization"
pipeline model. Still, further thoughts on the pipeline position are
welcome.
I've also only implemented this in the new pass manager. If folks are
very interested, I can try to add it to the old PM as well, but I didn't
really see much point (my use case is already switched over to the new
PM).
I've tested this pretty heavily without issue. A wide range of
benchmarks internally show no change outside the noise, and I don't see
any significant changes in SPEC either. However, the size class
computation in tcmalloc is substantially improved by this, which turns
into a 2% to 4% win on the hottest path through tcmalloc for us, so
there are definitely important cases where this is going to make
a substantial difference.
Differential revision: https://reviews.llvm.org/D37467
llvm-svn: 319164
2017-11-28 19:32:31 +08:00
|
|
|
// Optimize PHIs by speculating around them when profitable. Note that this
|
|
|
|
// pass needs to be run after any PRE or similar pass as it is essentially
|
|
|
|
// inserting redudnancies into the progrem. This even includes SimplifyCFG.
|
|
|
|
OptimizePM.addPass(SpeculateAroundPHIsPass());
|
|
|
|
|
2018-11-12 19:17:07 +08:00
|
|
|
for (auto &C : OptimizerLastEPCallbacks)
|
|
|
|
C(OptimizePM, Level);
|
|
|
|
|
2017-01-27 08:50:21 +08:00
|
|
|
// Add the core optimizing pipeline.
|
2016-12-22 14:59:15 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM)));
|
|
|
|
|
2018-07-16 08:28:24 +08:00
|
|
|
MPM.addPass(CGProfilePass());
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
// Now we need to do some global optimization transforms.
|
|
|
|
// FIXME: It would seem like these should come first in the optimization
|
|
|
|
// pipeline and maybe be the bottom of the canonicalization pipeline? Weird
|
|
|
|
// ordering here.
|
|
|
|
MPM.addPass(GlobalDCEPass());
|
|
|
|
MPM.addPass(ConstantMergePass());
|
|
|
|
|
|
|
|
return MPM;
|
2016-02-29 06:16:03 +08:00
|
|
|
}
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
ModulePassManager
|
|
|
|
PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
|
2019-02-16 02:46:44 +08:00
|
|
|
bool DebugLogging, bool LTOPreLink) {
|
2017-06-01 19:39:39 +08:00
|
|
|
assert(Level != O0 && "Must request optimizations for the default pipeline!");
|
|
|
|
|
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
|
|
|
// Force any function attributes we want the rest of the pipeline to observe.
|
|
|
|
MPM.addPass(ForceFunctionAttrsPass());
|
|
|
|
|
2018-01-23 09:25:20 +08:00
|
|
|
// Apply module pipeline start EP callback.
|
|
|
|
for (auto &C : PipelineStartEPCallbacks)
|
|
|
|
C(MPM);
|
|
|
|
|
2017-08-08 04:23:20 +08:00
|
|
|
if (PGOOpt && PGOOpt->SamplePGOSupport)
|
2017-07-29 12:10:24 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
// Add the core simplification pipeline.
|
2017-07-30 12:55:39 +08:00
|
|
|
MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::None,
|
|
|
|
DebugLogging));
|
2017-06-01 19:39:39 +08:00
|
|
|
|
|
|
|
// Now add the optimization pipeline.
|
2019-02-16 02:46:44 +08:00
|
|
|
MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging, LTOPreLink));
|
2017-06-01 19:39:39 +08:00
|
|
|
|
|
|
|
return MPM;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModulePassManager
|
|
|
|
PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level,
|
|
|
|
bool DebugLogging) {
|
|
|
|
assert(Level != O0 && "Must request optimizations for the default pipeline!");
|
|
|
|
|
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
|
|
|
// Force any function attributes we want the rest of the pipeline to observe.
|
|
|
|
MPM.addPass(ForceFunctionAttrsPass());
|
|
|
|
|
2017-08-08 04:23:20 +08:00
|
|
|
if (PGOOpt && PGOOpt->SamplePGOSupport)
|
2017-07-29 12:10:24 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass()));
|
|
|
|
|
2018-01-23 09:25:20 +08:00
|
|
|
// Apply module pipeline start EP callback.
|
|
|
|
for (auto &C : PipelineStartEPCallbacks)
|
|
|
|
C(MPM);
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
// If we are planning to perform ThinLTO later, we don't bloat the code with
|
|
|
|
// unrolling/vectorization/... now. Just simplify the module as much as we
|
|
|
|
// can.
|
2017-07-30 12:55:39 +08:00
|
|
|
MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::PreLink,
|
|
|
|
DebugLogging));
|
2017-06-01 19:39:39 +08:00
|
|
|
|
|
|
|
// Run partial inlining pass to partially inline functions that have
|
|
|
|
// large bodies.
|
|
|
|
// FIXME: It isn't clear whether this is really the right place to run this
|
|
|
|
// in ThinLTO. Because there is another canonicalization and simplification
|
|
|
|
// phase that will run after the thin link, running this here ends up with
|
|
|
|
// less information than will be available later and it may grow functions in
|
|
|
|
// ways that aren't beneficial.
|
|
|
|
if (RunPartialInlining)
|
|
|
|
MPM.addPass(PartialInlinerPass());
|
|
|
|
|
|
|
|
// Reduce the size of the IR as much as possible.
|
|
|
|
MPM.addPass(GlobalOptPass());
|
|
|
|
|
|
|
|
return MPM;
|
|
|
|
}
|
|
|
|
|
2018-07-19 22:51:32 +08:00
|
|
|
ModulePassManager PassBuilder::buildThinLTODefaultPipeline(
|
|
|
|
OptimizationLevel Level, bool DebugLogging,
|
|
|
|
const ModuleSummaryIndex *ImportSummary) {
|
2017-06-01 19:39:39 +08:00
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
2018-07-19 22:51:32 +08:00
|
|
|
if (ImportSummary) {
|
|
|
|
// These passes import type identifier resolutions for whole-program
|
|
|
|
// devirtualization and CFI. They must run early because other passes may
|
|
|
|
// disturb the specific instruction patterns that these passes look for,
|
|
|
|
// creating dependencies on resolutions that may not appear in the summary.
|
|
|
|
//
|
|
|
|
// For example, GVN may transform the pattern assume(type.test) appearing in
|
|
|
|
// two basic blocks into assume(phi(type.test, type.test)), which would
|
|
|
|
// transform a dependency on a WPD resolution into a dependency on a type
|
|
|
|
// identifier resolution for CFI.
|
|
|
|
//
|
|
|
|
// Also, WPD has access to more precise information than ICP and can
|
|
|
|
// devirtualize more effectively, so it should operate on the IR first.
|
|
|
|
MPM.addPass(WholeProgramDevirtPass(nullptr, ImportSummary));
|
|
|
|
MPM.addPass(LowerTypeTestsPass(nullptr, ImportSummary));
|
|
|
|
}
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
// Force any function attributes we want the rest of the pipeline to observe.
|
|
|
|
MPM.addPass(ForceFunctionAttrsPass());
|
|
|
|
|
|
|
|
// Add the core simplification pipeline.
|
2017-07-30 12:55:39 +08:00
|
|
|
MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::PostLink,
|
|
|
|
DebugLogging));
|
2017-06-01 19:39:39 +08:00
|
|
|
|
|
|
|
// Now add the optimization pipeline.
|
|
|
|
MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging));
|
|
|
|
|
|
|
|
return MPM;
|
|
|
|
}
|
|
|
|
|
2016-12-22 14:59:15 +08:00
|
|
|
ModulePassManager
|
|
|
|
PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level,
|
|
|
|
bool DebugLogging) {
|
|
|
|
assert(Level != O0 && "Must request optimizations for the default pipeline!");
|
2016-02-29 06:16:03 +08:00
|
|
|
// FIXME: We should use a customized pre-link pipeline!
|
2019-02-16 02:46:44 +08:00
|
|
|
return buildPerModuleDefaultPipeline(Level, DebugLogging,
|
2019-03-05 04:21:27 +08:00
|
|
|
/* LTOPreLink */true);
|
2016-02-29 06:16:03 +08:00
|
|
|
}
|
|
|
|
|
2018-07-19 22:51:32 +08:00
|
|
|
ModulePassManager
|
|
|
|
PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging,
|
|
|
|
ModuleSummaryIndex *ExportSummary) {
|
2016-12-22 14:59:15 +08:00
|
|
|
assert(Level != O0 && "Must request optimizations for the default pipeline!");
|
|
|
|
ModulePassManager MPM(DebugLogging);
|
|
|
|
|
2019-03-05 04:21:27 +08:00
|
|
|
if (PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) {
|
2018-11-16 02:06:42 +08:00
|
|
|
// Load sample profile before running the LTO optimization pipeline.
|
2019-03-05 04:21:27 +08:00
|
|
|
MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile,
|
2018-11-16 02:06:42 +08:00
|
|
|
PGOOpt->ProfileRemappingFile,
|
|
|
|
false /* ThinLTOPhase::PreLink */));
|
|
|
|
}
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Remove unused virtual tables to improve the quality of code generated by
|
|
|
|
// whole-program devirtualization and bitset lowering.
|
|
|
|
MPM.addPass(GlobalDCEPass());
|
|
|
|
|
|
|
|
// Force any function attributes we want the rest of the pipeline to observe.
|
|
|
|
MPM.addPass(ForceFunctionAttrsPass());
|
|
|
|
|
|
|
|
// Do basic inference of function attributes from known properties of system
|
|
|
|
// libraries and other oracles.
|
|
|
|
MPM.addPass(InferFunctionAttrsPass());
|
|
|
|
|
|
|
|
if (Level > 1) {
|
Recommit r317351 : Add CallSiteSplitting pass
This recommit r317351 after fixing a buildbot failure.
Original commit message:
Summary:
This change add a pass which tries to split a call-site to pass
more constrained arguments if its argument is predicated in the control flow
so that we can expose better context to the later passes (e.g, inliner, jump
threading, or IPA-CP based function cloning, etc.).
As of now we support two cases :
1) If a call site is dominated by an OR condition and if any of its arguments
are predicated on this OR condition, try to split the condition with more
constrained arguments. For example, in the code below, we try to split the
call site since we can predicate the argument (ptr) based on the OR condition.
Split from :
if (!ptr || c)
callee(ptr);
to :
if (!ptr)
callee(null ptr) // set the known constant value
else if (c)
callee(nonnull ptr) // set non-null attribute in the argument
2) We can also split a call-site based on constant incoming values of a PHI
For example,
from :
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2, label %BB1
BB1:
br label %BB2
BB2:
%p = phi i32 [ 0, %BB0 ], [ 1, %BB1 ]
call void @bar(i32 %p)
to
BB0:
%c = icmp eq i32 %i1, %i2
br i1 %c, label %BB2-split0, label %BB1
BB1:
br label %BB2-split1
BB2-split0:
call void @bar(i32 0)
br label %BB2
BB2-split1:
call void @bar(i32 1)
br label %BB2
BB2:
%p = phi i32 [ 0, %BB2-split0 ], [ 1, %BB2-split1 ]
llvm-svn: 317362
2017-11-04 04:41:16 +08:00
|
|
|
FunctionPassManager EarlyFPM(DebugLogging);
|
|
|
|
EarlyFPM.addPass(CallSiteSplittingPass());
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM)));
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Indirect call promotion. This should promote all the targets that are
|
|
|
|
// left by the earlier promotion pass that promotes intra-module targets.
|
|
|
|
// This two-step promotion is to save the compile time. For LTO, it should
|
|
|
|
// produce the same result as if we only do promotion here.
|
2017-06-30 07:33:05 +08:00
|
|
|
MPM.addPass(PGOIndirectCallPromotion(
|
2019-03-05 04:21:27 +08:00
|
|
|
true /* InLTO */, PGOOpt && PGOOpt->Action == PGOOptions::SampleUse));
|
2017-01-24 08:57:39 +08:00
|
|
|
// Propagate constants at call sites into the functions they call. This
|
|
|
|
// opens opportunities for globalopt (and inlining) by substituting function
|
|
|
|
// pointers passed as arguments to direct uses of functions.
|
|
|
|
MPM.addPass(IPSCCPPass());
|
2017-10-25 21:40:08 +08:00
|
|
|
|
|
|
|
// Attach metadata to indirect call sites indicating the set of functions
|
|
|
|
// they may target at run-time. This should follow IPSCCP.
|
|
|
|
MPM.addPass(CalledValuePropagationPass());
|
2017-01-24 08:57:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now deduce any function attributes based in the current code.
|
|
|
|
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
|
|
|
|
PostOrderFunctionAttrsPass()));
|
|
|
|
|
|
|
|
// Do RPO function attribute inference across the module to forward-propagate
|
|
|
|
// attributes where applicable.
|
|
|
|
// FIXME: Is this really an optimization rather than a canonicalization?
|
|
|
|
MPM.addPass(ReversePostOrderFunctionAttrsPass());
|
|
|
|
|
2019-02-27 04:33:22 +08:00
|
|
|
// Use in-range annotations on GEP indices to split globals where beneficial.
|
2017-01-24 08:57:39 +08:00
|
|
|
MPM.addPass(GlobalSplitPass());
|
2016-02-29 06:16:03 +08:00
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Run whole program optimization of virtual call when the list of callees
|
|
|
|
// is fixed.
|
2018-07-19 22:51:32 +08:00
|
|
|
MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr));
|
2017-01-24 08:57:39 +08:00
|
|
|
|
|
|
|
// Stop here at -O1.
|
2018-07-19 22:51:32 +08:00
|
|
|
if (Level == 1) {
|
|
|
|
// The LowerTypeTestsPass needs to run to lower type metadata and the
|
|
|
|
// type.test intrinsics. The pass does nothing if CFI is disabled.
|
|
|
|
MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr));
|
2017-01-24 08:57:39 +08:00
|
|
|
return MPM;
|
2018-07-19 22:51:32 +08:00
|
|
|
}
|
2017-01-24 08:57:39 +08:00
|
|
|
|
|
|
|
// Optimize globals to try and fold them into constants.
|
|
|
|
MPM.addPass(GlobalOptPass());
|
|
|
|
|
|
|
|
// Promote any localized globals to SSA registers.
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass()));
|
|
|
|
|
|
|
|
// Linking modules together can lead to duplicate global constant, only
|
|
|
|
// keep one copy of each constant.
|
|
|
|
MPM.addPass(ConstantMergePass());
|
|
|
|
|
|
|
|
// Remove unused arguments from functions.
|
|
|
|
MPM.addPass(DeadArgumentEliminationPass());
|
|
|
|
|
|
|
|
// Reduce the code after globalopt and ipsccp. Both can open up significant
|
|
|
|
// simplification opportunities, and both can propagate functions through
|
|
|
|
// function pointers. When this happens, we often have to resolve varargs
|
|
|
|
// calls, etc, so let instcombine do this.
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
FunctionPassManager PeepholeFPM(DebugLogging);
|
2018-01-25 20:06:32 +08:00
|
|
|
if (Level == O3)
|
|
|
|
PeepholeFPM.addPass(AggressiveInstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
PeepholeFPM.addPass(InstCombinePass());
|
|
|
|
invokePeepholeEPCallbacks(PeepholeFPM, Level);
|
|
|
|
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(PeepholeFPM)));
|
2017-01-24 08:57:39 +08:00
|
|
|
|
|
|
|
// Note: historically, the PruneEH pass was run first to deduce nounwind and
|
|
|
|
// generally clean up exception handling overhead. It isn't clear this is
|
|
|
|
// valuable as the inliner doesn't currently care whether it is inlining an
|
|
|
|
// invoke or a call.
|
|
|
|
// Run the inliner now.
|
2017-06-28 21:33:49 +08:00
|
|
|
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
|
|
|
|
InlinerPass(getInlineParamsFromOptLevel(Level))));
|
2017-01-24 08:57:39 +08:00
|
|
|
|
|
|
|
// Optimize globals again after we ran the inliner.
|
|
|
|
MPM.addPass(GlobalOptPass());
|
|
|
|
|
|
|
|
// Garbage collect dead functions.
|
|
|
|
// FIXME: Add ArgumentPromotion pass after once it's ported.
|
|
|
|
MPM.addPass(GlobalDCEPass());
|
|
|
|
|
|
|
|
FunctionPassManager FPM(DebugLogging);
|
|
|
|
// The IPO Passes may leave cruft around. Clean up after them.
|
|
|
|
FPM.addPass(InstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(FPM, Level);
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
FPM.addPass(JumpThreadingPass());
|
|
|
|
|
2019-03-05 04:21:27 +08:00
|
|
|
// Do a post inline PGO instrumentation and use pass. This is a context
|
|
|
|
// sensitive PGO pass.
|
|
|
|
if (PGOOpt) {
|
|
|
|
if (PGOOpt->CSAction == PGOOptions::CSIRInstr)
|
|
|
|
addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ true,
|
|
|
|
/* IsCS */ true, PGOOpt->CSProfileGenFile,
|
|
|
|
PGOOpt->ProfileRemappingFile);
|
|
|
|
else if (PGOOpt->CSAction == PGOOptions::CSIRUse)
|
|
|
|
addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ false,
|
|
|
|
/* IsCS */ true, PGOOpt->ProfileFile,
|
|
|
|
PGOOpt->ProfileRemappingFile);
|
|
|
|
}
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Break up allocas
|
|
|
|
FPM.addPass(SROA());
|
|
|
|
|
2019-03-21 03:08:18 +08:00
|
|
|
// LTO provides additional opportunities for tailcall elimination due to
|
|
|
|
// link-time inlining, and visibility of nocapture attribute.
|
|
|
|
FPM.addPass(TailCallElimPass());
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Run a few AA driver optimizations here and now to cleanup the code.
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
|
|
|
|
|
|
|
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
|
|
|
|
PostOrderFunctionAttrsPass()));
|
|
|
|
// FIXME: here we run IP alias analysis in the legacy PM.
|
|
|
|
|
|
|
|
FunctionPassManager MainFPM;
|
|
|
|
|
|
|
|
// FIXME: once we fix LoopPass Manager, add LICM here.
|
|
|
|
// FIXME: once we provide support for enabling MLSM, add it here.
|
|
|
|
// FIXME: once we provide support for enabling NewGVN, add it here.
|
2017-05-23 07:41:40 +08:00
|
|
|
if (RunNewGVN)
|
|
|
|
MainFPM.addPass(NewGVNPass());
|
|
|
|
else
|
|
|
|
MainFPM.addPass(GVN());
|
2017-01-24 08:57:39 +08:00
|
|
|
|
|
|
|
// Remove dead memcpy()'s.
|
|
|
|
MainFPM.addPass(MemCpyOptPass());
|
|
|
|
|
|
|
|
// Nuke dead stores.
|
|
|
|
MainFPM.addPass(DSEPass());
|
|
|
|
|
|
|
|
// FIXME: at this point, we run a bunch of loop passes:
|
|
|
|
// indVarSimplify, loopDeletion, loopInterchange, loopUnrool,
|
|
|
|
// loopVectorize. Enable them once the remaining issue with LPM
|
|
|
|
// are sorted out.
|
|
|
|
|
|
|
|
MainFPM.addPass(InstCombinePass());
|
|
|
|
MainFPM.addPass(SimplifyCFGPass());
|
|
|
|
MainFPM.addPass(SCCPPass());
|
|
|
|
MainFPM.addPass(InstCombinePass());
|
|
|
|
MainFPM.addPass(BDCEPass());
|
|
|
|
|
|
|
|
// FIXME: We may want to run SLPVectorizer here.
|
|
|
|
// After vectorization, assume intrinsics may tell us more
|
|
|
|
// about pointer alignments.
|
|
|
|
#if 0
|
|
|
|
MainFPM.add(AlignmentFromAssumptionsPass());
|
|
|
|
#endif
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// FIXME: Conditionally run LoadCombine here, after it's ported
|
|
|
|
// (in case we still have this pass, given its questionable usefulness).
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
MainFPM.addPass(InstCombinePass());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
invokePeepholeEPCallbacks(MainFPM, Level);
|
2017-01-24 08:57:39 +08:00
|
|
|
MainFPM.addPass(JumpThreadingPass());
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM)));
|
|
|
|
|
|
|
|
// Create a function that performs CFI checks for cross-DSO calls with
|
|
|
|
// targets in the current module.
|
|
|
|
MPM.addPass(CrossDSOCFIPass());
|
|
|
|
|
|
|
|
// Lower type metadata and the type.test intrinsic. This pass supports
|
|
|
|
// clang's control flow integrity mechanisms (-fsanitize=cfi*) and needs
|
|
|
|
// to be run at link time if CFI is enabled. This pass does nothing if
|
|
|
|
// CFI is disabled.
|
2018-07-19 22:51:32 +08:00
|
|
|
MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr));
|
2017-01-24 08:57:39 +08:00
|
|
|
|
2019-02-16 02:46:44 +08:00
|
|
|
// Enable splitting late in the FullLTO post-link pipeline. This is done in
|
|
|
|
// the same stage in the old pass manager (\ref addLateLTOOptimizationPasses).
|
|
|
|
if (EnableHotColdSplit)
|
|
|
|
MPM.addPass(HotColdSplittingPass());
|
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// Add late LTO optimization passes.
|
|
|
|
// Delete basic blocks, which optimization passes may have killed.
|
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass()));
|
|
|
|
|
|
|
|
// Drop bodies of available eternally objects to improve GlobalDCE.
|
|
|
|
MPM.addPass(EliminateAvailableExternallyPass());
|
|
|
|
|
|
|
|
// Now that we have optimized the program, discard unreachable functions.
|
|
|
|
MPM.addPass(GlobalDCEPass());
|
2016-12-22 14:59:15 +08:00
|
|
|
|
2017-01-24 08:57:39 +08:00
|
|
|
// FIXME: Enable MergeFuncs, conditionally, after ported, maybe.
|
2016-12-22 14:59:15 +08:00
|
|
|
return MPM;
|
2016-02-29 06:16:03 +08:00
|
|
|
}
|
|
|
|
|
2016-12-24 04:38:19 +08:00
|
|
|
AAManager PassBuilder::buildDefaultAAPipeline() {
|
|
|
|
AAManager AA;
|
|
|
|
|
|
|
|
// The order in which these are registered determines their priority when
|
|
|
|
// being queried.
|
|
|
|
|
|
|
|
// First we register the basic alias analysis that provides the majority of
|
|
|
|
// per-function local AA logic. This is a stateless, on-demand local set of
|
|
|
|
// AA techniques.
|
|
|
|
AA.registerFunctionAnalysis<BasicAA>();
|
|
|
|
|
|
|
|
// Next we query fast, specialized alias analyses that wrap IR-embedded
|
|
|
|
// information about aliasing.
|
|
|
|
AA.registerFunctionAnalysis<ScopedNoAliasAA>();
|
|
|
|
AA.registerFunctionAnalysis<TypeBasedAA>();
|
|
|
|
|
|
|
|
// Add support for querying global aliasing information when available.
|
2016-12-24 13:11:17 +08:00
|
|
|
// Because the `AAManager` is a function analysis and `GlobalsAA` is a module
|
|
|
|
// analysis, all that the `AAManager` can do is query for any *cached*
|
2017-02-12 13:34:04 +08:00
|
|
|
// results from `GlobalsAA` through a readonly proxy.
|
2016-12-24 04:38:19 +08:00
|
|
|
AA.registerModuleAnalysis<GlobalsAA>();
|
|
|
|
|
|
|
|
return AA;
|
|
|
|
}
|
|
|
|
|
2016-08-03 15:44:48 +08:00
|
|
|
static Optional<int> parseRepeatPassName(StringRef Name) {
|
|
|
|
if (!Name.consume_front("repeat<") || !Name.consume_back(">"))
|
|
|
|
return None;
|
|
|
|
int Count;
|
|
|
|
if (Name.getAsInteger(0, Count) || Count <= 0)
|
|
|
|
return None;
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2016-12-28 19:07:33 +08:00
|
|
|
static Optional<int> parseDevirtPassName(StringRef Name) {
|
|
|
|
if (!Name.consume_front("devirt<") || !Name.consume_back(">"))
|
|
|
|
return None;
|
|
|
|
int Count;
|
|
|
|
if (Name.getAsInteger(0, Count) || Count <= 0)
|
|
|
|
return None;
|
|
|
|
return Count;
|
|
|
|
}
|
|
|
|
|
2019-01-10 18:01:53 +08:00
|
|
|
static bool checkParametrizedPassName(StringRef Name, StringRef PassName) {
|
|
|
|
if (!Name.consume_front(PassName))
|
|
|
|
return false;
|
|
|
|
// normal pass name w/o parameters == default parameters
|
|
|
|
if (Name.empty())
|
|
|
|
return true;
|
|
|
|
return Name.startswith("<") && Name.endswith(">");
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// This performs customized parsing of pass name with parameters.
|
|
|
|
///
|
|
|
|
/// We do not need parametrization of passes in textual pipeline very often,
|
|
|
|
/// yet on a rare occasion ability to specify parameters right there can be
|
|
|
|
/// useful.
|
|
|
|
///
|
|
|
|
/// \p Name - parameterized specification of a pass from a textual pipeline
|
|
|
|
/// is a string in a form of :
|
|
|
|
/// PassName '<' parameter-list '>'
|
|
|
|
///
|
|
|
|
/// Parameter list is being parsed by the parser callable argument, \p Parser,
|
|
|
|
/// It takes a string-ref of parameters and returns either StringError or a
|
|
|
|
/// parameter list in a form of a custom parameters type, all wrapped into
|
|
|
|
/// Expected<> template class.
|
|
|
|
///
|
|
|
|
template <typename ParametersParseCallableT>
|
|
|
|
auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name,
|
|
|
|
StringRef PassName) -> decltype(Parser(StringRef{})) {
|
|
|
|
using ParametersT = typename decltype(Parser(StringRef{}))::value_type;
|
|
|
|
|
|
|
|
StringRef Params = Name;
|
|
|
|
if (!Params.consume_front(PassName)) {
|
|
|
|
assert(false &&
|
|
|
|
"unable to strip pass name from parametrized pass specification");
|
|
|
|
}
|
|
|
|
if (Params.empty())
|
|
|
|
return ParametersT{};
|
|
|
|
if (!Params.consume_front("<") || !Params.consume_back(">")) {
|
|
|
|
assert(false && "invalid format for parametrized pass name");
|
|
|
|
}
|
|
|
|
|
|
|
|
Expected<ParametersT> Result = Parser(Params);
|
|
|
|
assert((Result || Result.template errorIsA<StringError>()) &&
|
|
|
|
"Pass parameter parser can only return StringErrors.");
|
|
|
|
return std::move(Result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parser of parameters for LoopUnroll pass.
|
|
|
|
Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
|
|
|
|
LoopUnrollOptions UnrollOpts;
|
|
|
|
while (!Params.empty()) {
|
|
|
|
StringRef ParamName;
|
|
|
|
std::tie(ParamName, Params) = Params.split(';');
|
|
|
|
int OptLevel = StringSwitch<int>(ParamName)
|
|
|
|
.Case("O0", 0)
|
|
|
|
.Case("O1", 1)
|
|
|
|
.Case("O2", 2)
|
|
|
|
.Case("O3", 3)
|
|
|
|
.Default(-1);
|
|
|
|
if (OptLevel >= 0) {
|
|
|
|
UnrollOpts.setOptLevel(OptLevel);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Enable = !ParamName.consume_front("no-");
|
|
|
|
if (ParamName == "partial") {
|
|
|
|
UnrollOpts.setPartial(Enable);
|
|
|
|
} else if (ParamName == "peeling") {
|
|
|
|
UnrollOpts.setPeeling(Enable);
|
|
|
|
} else if (ParamName == "runtime") {
|
|
|
|
UnrollOpts.setRuntime(Enable);
|
|
|
|
} else if (ParamName == "upperbound") {
|
|
|
|
UnrollOpts.setUpperBound(Enable);
|
|
|
|
} else {
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return UnrollOpts;
|
|
|
|
}
|
|
|
|
|
2019-02-05 05:02:49 +08:00
|
|
|
Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
|
|
|
|
MemorySanitizerOptions Result;
|
|
|
|
while (!Params.empty()) {
|
|
|
|
StringRef ParamName;
|
|
|
|
std::tie(ParamName, Params) = Params.split(';');
|
|
|
|
|
|
|
|
if (ParamName == "recover") {
|
|
|
|
Result.Recover = true;
|
|
|
|
} else if (ParamName == "kernel") {
|
|
|
|
Result.Kernel = true;
|
|
|
|
} else if (ParamName.consume_front("track-origins=")) {
|
|
|
|
if (ParamName.getAsInteger(0, Result.TrackOrigins))
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid argument to MemorySanitizer pass track-origins "
|
|
|
|
"parameter: '{0}' ",
|
|
|
|
ParamName)
|
|
|
|
.str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
} else {
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName)
|
|
|
|
.str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2019-01-10 18:01:53 +08:00
|
|
|
} // namespace
|
|
|
|
|
2017-06-01 19:39:39 +08:00
|
|
|
/// Tests whether a pass name starts with a valid prefix for a default pipeline
|
|
|
|
/// alias.
|
|
|
|
static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
|
|
|
|
return Name.startswith("default") || Name.startswith("thinlto") ||
|
|
|
|
Name.startswith("lto");
|
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
/// Tests whether registered callbacks will accept a given pass name.
|
|
|
|
///
|
|
|
|
/// When parsing a pipeline text, the type of the outermost pipeline may be
|
|
|
|
/// omitted, in which case the type is automatically determined from the first
|
|
|
|
/// pass name in the text. This may be a name that is handled through one of the
|
|
|
|
/// callbacks. We check this through the oridinary parsing callbacks by setting
|
|
|
|
/// up a dummy PassManager in order to not force the client to also handle this
|
|
|
|
/// type of query.
|
|
|
|
template <typename PassManagerT, typename CallbacksT>
|
|
|
|
static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
|
|
|
|
if (!Callbacks.empty()) {
|
|
|
|
PassManagerT DummyPM;
|
|
|
|
for (auto &CB : Callbacks)
|
|
|
|
if (CB(Name, DummyPM, {}))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename CallbacksT>
|
|
|
|
static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
|
2016-02-29 06:16:03 +08:00
|
|
|
// Manually handle aliases for pre-configured pipeline fragments.
|
2017-06-01 19:39:39 +08:00
|
|
|
if (startsWithDefaultPipelineAliasPrefix(Name))
|
2016-02-29 06:16:03 +08:00
|
|
|
return DefaultAliasRegex.match(Name);
|
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Explicitly handle pass manager names.
|
|
|
|
if (Name == "module")
|
|
|
|
return true;
|
|
|
|
if (Name == "cgscc")
|
|
|
|
return true;
|
|
|
|
if (Name == "function")
|
|
|
|
return true;
|
|
|
|
|
2016-08-03 15:44:48 +08:00
|
|
|
// Explicitly handle custom-parsed pass names.
|
|
|
|
if (parseRepeatPassName(Name))
|
|
|
|
return true;
|
|
|
|
|
2016-06-17 15:15:29 +08:00
|
|
|
#define MODULE_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) \
|
|
|
|
return true;
|
2015-01-06 10:10:51 +08:00
|
|
|
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
2015-01-06 12:49:44 +08:00
|
|
|
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
2015-01-06 10:10:51 +08:00
|
|
|
return true;
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
template <typename CallbacksT>
|
|
|
|
static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {
|
2016-08-03 11:21:41 +08:00
|
|
|
// Explicitly handle pass manager names.
|
|
|
|
if (Name == "cgscc")
|
|
|
|
return true;
|
|
|
|
if (Name == "function")
|
|
|
|
return true;
|
|
|
|
|
2016-08-03 15:44:48 +08:00
|
|
|
// Explicitly handle custom-parsed pass names.
|
|
|
|
if (parseRepeatPassName(Name))
|
|
|
|
return true;
|
2016-12-28 19:07:33 +08:00
|
|
|
if (parseDevirtPassName(Name))
|
|
|
|
return true;
|
2016-08-03 15:44:48 +08:00
|
|
|
|
2016-06-17 15:15:29 +08:00
|
|
|
#define CGSCC_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) \
|
|
|
|
return true;
|
2015-01-06 10:10:51 +08:00
|
|
|
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
|
2015-01-06 12:49:44 +08:00
|
|
|
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
2015-01-06 10:10:51 +08:00
|
|
|
return true;
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);
|
2014-04-21 19:12:00 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
template <typename CallbacksT>
|
|
|
|
static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
|
2016-08-03 11:21:41 +08:00
|
|
|
// Explicitly handle pass manager names.
|
|
|
|
if (Name == "function")
|
|
|
|
return true;
|
|
|
|
if (Name == "loop")
|
|
|
|
return true;
|
|
|
|
|
2016-08-03 15:44:48 +08:00
|
|
|
// Explicitly handle custom-parsed pass names.
|
|
|
|
if (parseRepeatPassName(Name))
|
|
|
|
return true;
|
|
|
|
|
2016-06-17 15:15:29 +08:00
|
|
|
#define FUNCTION_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) \
|
|
|
|
return true;
|
2019-01-10 18:01:53 +08:00
|
|
|
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \
|
|
|
|
if (checkParametrizedPassName(Name, NAME)) \
|
|
|
|
return true;
|
2015-01-06 10:10:51 +08:00
|
|
|
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
2015-01-06 12:49:44 +08:00
|
|
|
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
2015-01-06 10:10:51 +08:00
|
|
|
return true;
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);
|
2014-01-12 17:34:22 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
template <typename CallbacksT>
|
|
|
|
static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks) {
|
2016-08-03 11:21:41 +08:00
|
|
|
// Explicitly handle pass manager names.
|
|
|
|
if (Name == "loop")
|
|
|
|
return true;
|
|
|
|
|
2016-08-03 15:44:48 +08:00
|
|
|
// Explicitly handle custom-parsed pass names.
|
|
|
|
if (parseRepeatPassName(Name))
|
|
|
|
return true;
|
|
|
|
|
2016-06-17 15:15:29 +08:00
|
|
|
#define LOOP_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) \
|
|
|
|
return true;
|
2016-02-25 15:23:08 +08:00
|
|
|
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
|
|
|
return true;
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
Optional<std::vector<PassBuilder::PipelineElement>>
|
|
|
|
PassBuilder::parsePipelineText(StringRef Text) {
|
|
|
|
std::vector<PipelineElement> ResultPipeline;
|
|
|
|
|
|
|
|
SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {
|
|
|
|
&ResultPipeline};
|
|
|
|
for (;;) {
|
|
|
|
std::vector<PipelineElement> &Pipeline = *PipelineStack.back();
|
|
|
|
size_t Pos = Text.find_first_of(",()");
|
|
|
|
Pipeline.push_back({Text.substr(0, Pos), {}});
|
|
|
|
|
|
|
|
// If we have a single terminating name, we're done.
|
|
|
|
if (Pos == Text.npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
char Sep = Text[Pos];
|
|
|
|
Text = Text.substr(Pos + 1);
|
|
|
|
if (Sep == ',')
|
|
|
|
// Just a name ending in a comma, continue.
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (Sep == '(') {
|
|
|
|
// Push the inner pipeline onto the stack to continue processing.
|
|
|
|
PipelineStack.push_back(&Pipeline.back().InnerPipeline);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(Sep == ')' && "Bogus separator!");
|
|
|
|
// When handling the close parenthesis, we greedily consume them to avoid
|
|
|
|
// empty strings in the pipeline.
|
|
|
|
do {
|
|
|
|
// If we try to pop the outer pipeline we have unbalanced parentheses.
|
|
|
|
if (PipelineStack.size() == 1)
|
|
|
|
return None;
|
|
|
|
|
|
|
|
PipelineStack.pop_back();
|
|
|
|
} while (Text.consume_front(")"));
|
|
|
|
|
|
|
|
// Check if we've finished parsing.
|
|
|
|
if (Text.empty())
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Otherwise, the end of an inner pipeline always has to be followed by
|
|
|
|
// a comma, and then we can continue.
|
|
|
|
if (!Text.consume_front(","))
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PipelineStack.size() > 1)
|
|
|
|
// Unbalanced paretheses.
|
|
|
|
return None;
|
|
|
|
|
|
|
|
assert(PipelineStack.back() == &ResultPipeline &&
|
|
|
|
"Wrong pipeline at the bottom of the stack!");
|
|
|
|
return {std::move(ResultPipeline)};
|
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseModulePass(ModulePassManager &MPM,
|
|
|
|
const PipelineElement &E,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
auto &Name = E.Name;
|
|
|
|
auto &InnerPipeline = E.InnerPipeline;
|
|
|
|
|
|
|
|
// First handle complex passes like the pass managers which carry pipelines.
|
|
|
|
if (!InnerPipeline.empty()) {
|
|
|
|
if (Name == "module") {
|
|
|
|
ModulePassManager NestedMPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
MPM.addPass(std::move(NestedMPM));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
if (Name == "cgscc") {
|
|
|
|
CGSCCPassManager CGPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass,
|
|
|
|
DebugLogging))
|
|
|
|
return Err;
|
2017-08-11 13:47:13 +08:00
|
|
|
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
if (Name == "function") {
|
|
|
|
FunctionPassManager FPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
2016-08-03 15:44:48 +08:00
|
|
|
if (auto Count = parseRepeatPassName(Name)) {
|
|
|
|
ModulePassManager NestedMPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-04 11:52:53 +08:00
|
|
|
MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 15:44:48 +08:00
|
|
|
}
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : ModulePipelineParsingCallbacks)
|
|
|
|
if (C(Name, MPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Normal passes can't have pipelines.
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid use of '{0}' pass as module pipeline", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
;
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
|
2016-02-29 06:16:03 +08:00
|
|
|
// Manually handle aliases for pre-configured pipeline fragments.
|
2017-06-01 19:39:39 +08:00
|
|
|
if (startsWithDefaultPipelineAliasPrefix(Name)) {
|
2016-02-29 06:16:03 +08:00
|
|
|
SmallVector<StringRef, 3> Matches;
|
|
|
|
if (!DefaultAliasRegex.match(Name, &Matches))
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown default pipeline alias '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
|
2016-02-29 06:16:03 +08:00
|
|
|
assert(Matches.size() == 3 && "Must capture two matched strings!");
|
|
|
|
|
2016-07-26 02:34:51 +08:00
|
|
|
OptimizationLevel L = StringSwitch<OptimizationLevel>(Matches[2])
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
.Case("O0", O0)
|
|
|
|
.Case("O1", O1)
|
|
|
|
.Case("O2", O2)
|
|
|
|
.Case("O3", O3)
|
|
|
|
.Case("Os", Os)
|
|
|
|
.Case("Oz", Oz);
|
2016-12-22 14:59:15 +08:00
|
|
|
if (L == O0)
|
|
|
|
// At O0 we do nothing at all!
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-02-29 06:16:03 +08:00
|
|
|
|
|
|
|
if (Matches[1] == "default") {
|
2016-12-22 14:59:15 +08:00
|
|
|
MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging));
|
2017-06-01 19:39:39 +08:00
|
|
|
} else if (Matches[1] == "thinlto-pre-link") {
|
|
|
|
MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L, DebugLogging));
|
|
|
|
} else if (Matches[1] == "thinlto") {
|
2018-07-19 22:51:32 +08:00
|
|
|
MPM.addPass(buildThinLTODefaultPipeline(L, DebugLogging, nullptr));
|
2016-02-29 06:16:03 +08:00
|
|
|
} else if (Matches[1] == "lto-pre-link") {
|
2016-12-22 14:59:15 +08:00
|
|
|
MPM.addPass(buildLTOPreLinkDefaultPipeline(L, DebugLogging));
|
2016-02-29 06:16:03 +08:00
|
|
|
} else {
|
|
|
|
assert(Matches[1] == "lto" && "Not one of the matched options!");
|
2018-07-19 22:51:32 +08:00
|
|
|
MPM.addPass(buildLTODefaultPipeline(L, DebugLogging, nullptr));
|
2016-02-29 06:16:03 +08:00
|
|
|
}
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-02-29 06:16:03 +08:00
|
|
|
}
|
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Finally expand the basic registered passes from the .inc file.
|
2014-04-21 16:08:50 +08:00
|
|
|
#define MODULE_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
|
|
|
MPM.addPass(CREATE_PASS); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2014-02-06 12:37:03 +08:00
|
|
|
}
|
2015-01-06 10:10:51 +08:00
|
|
|
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == "require<" NAME ">") { \
|
2016-08-20 02:36:06 +08:00
|
|
|
MPM.addPass( \
|
|
|
|
RequireAnalysisPass< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type, Module>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 12:49:44 +08:00
|
|
|
} \
|
|
|
|
if (Name == "invalidate<" NAME ">") { \
|
2016-02-26 20:30:18 +08:00
|
|
|
MPM.addPass(InvalidateAnalysisPass< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 10:10:51 +08:00
|
|
|
}
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : ModulePipelineParsingCallbacks)
|
|
|
|
if (C(Name, MPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown module pass '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,
|
|
|
|
const PipelineElement &E, bool VerifyEachPass,
|
|
|
|
bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
auto &Name = E.Name;
|
|
|
|
auto &InnerPipeline = E.InnerPipeline;
|
|
|
|
|
|
|
|
// First handle complex passes like the pass managers which carry pipelines.
|
|
|
|
if (!InnerPipeline.empty()) {
|
|
|
|
if (Name == "cgscc") {
|
|
|
|
CGSCCPassManager NestedCGPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// Add the nested pass manager with the appropriate adaptor.
|
|
|
|
CGPM.addPass(std::move(NestedCGPM));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
if (Name == "function") {
|
|
|
|
FunctionPassManager FPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// Add the nested pass manager with the appropriate adaptor.
|
2017-08-11 13:47:13 +08:00
|
|
|
CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
2016-08-03 15:44:48 +08:00
|
|
|
if (auto Count = parseRepeatPassName(Name)) {
|
|
|
|
CGSCCPassManager NestedCGPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-04 11:52:53 +08:00
|
|
|
CGPM.addPass(createRepeatedPass(*Count, std::move(NestedCGPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 15:44:48 +08:00
|
|
|
}
|
2016-12-28 19:07:33 +08:00
|
|
|
if (auto MaxRepetitions = parseDevirtPassName(Name)) {
|
|
|
|
CGSCCPassManager NestedCGPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2017-08-11 13:47:13 +08:00
|
|
|
CGPM.addPass(
|
|
|
|
createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-12-28 19:07:33 +08:00
|
|
|
}
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : CGSCCPipelineParsingCallbacks)
|
|
|
|
if (C(Name, CGPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Normal passes can't have pipelines.
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid use of '{0}' pass as cgscc pipeline", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// Now expand the basic registered passes from the .inc file.
|
2014-04-21 19:12:00 +08:00
|
|
|
#define CGSCC_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
|
|
|
CGPM.addPass(CREATE_PASS); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2014-04-21 19:12:00 +08:00
|
|
|
}
|
2015-01-06 10:10:51 +08:00
|
|
|
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == "require<" NAME ">") { \
|
2016-02-26 20:30:18 +08:00
|
|
|
CGPM.addPass(RequireAnalysisPass< \
|
2016-08-20 02:36:06 +08:00
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type, \
|
[PM] Introduce basic update capabilities to the new PM's CGSCC pass
manager, including both plumbing and logic to handle function pass
updates.
There are three fundamentally tied changes here:
1) Plumbing *some* mechanism for updating the CGSCC pass manager as the
CG changes while passes are running.
2) Changing the CGSCC pass manager infrastructure to have support for
the underlying graph to mutate mid-pass run.
3) Actually updating the CG after function passes run.
I can separate them if necessary, but I think its really useful to have
them together as the needs of #3 drove #2, and that in turn drove #1.
The plumbing technique is to extend the "run" method signature with
extra arguments. We provide the call graph that intrinsically is
available as it is the basis of the pass manager's IR units, and an
output parameter that records the results of updating the call graph
during an SCC passes's run. Note that "...UpdateResult" isn't a *great*
name here... suggestions very welcome.
I tried a pretty frustrating number of different data structures and such
for the innards of the update result. Every other one failed for one
reason or another. Sometimes I just couldn't keep the layers of
complexity right in my head. The thing that really worked was to just
directly provide access to the underlying structures used to walk the
call graph so that their updates could be informed by the *particular*
nature of the change to the graph.
The technique for how to make the pass management infrastructure cope
with mutating graphs was also something that took a really, really large
number of iterations to get to a place where I was happy. Here are some
of the considerations that drove the design:
- We operate at three levels within the infrastructure: RefSCC, SCC, and
Node. In each case, we are working bottom up and so we want to
continue to iterate on the "lowest" node as the graph changes. Look at
how we iterate over nodes in an SCC running function passes as those
function passes mutate the CG. We continue to iterate on the "lowest"
SCC, which is the one that continues to contain the function just
processed.
- The call graph structure re-uses SCCs (and RefSCCs) during mutation
events for the *highest* entry in the resulting new subgraph, not the
lowest. This means that it is necessary to continually update the
current SCC or RefSCC as it shifts. This is really surprising and
subtle, and took a long time for me to work out. I actually tried
changing the call graph to provide the opposite behavior, and it
breaks *EVERYTHING*. The graph update algorithms are really deeply
tied to this particualr pattern.
- When SCCs or RefSCCs are split apart and refined and we continually
re-pin our processing to the bottom one in the subgraph, we need to
enqueue the newly formed SCCs and RefSCCs for subsequent processing.
Queuing them presents a few challenges:
1) SCCs and RefSCCs use wildly different iteration strategies at
a high level. We end up needing to converge them on worklist
approaches that can be extended in order to be able to handle the
mutations.
2) The order of the enqueuing need to remain bottom-up post-order so
that we don't get surprising order of visitation for things like
the inliner.
3) We need the worklists to have set semantics so we don't duplicate
things endlessly. We don't need a *persistent* set though because
we always keep processing the bottom node!!!! This is super, super
surprising to me and took a long time to convince myself this is
correct, but I'm pretty sure it is... Once we sink down to the
bottom node, we can't re-split out the same node in any way, and
the postorder of the current queue is fixed and unchanging.
4) We need to make sure that the "current" SCC or RefSCC actually gets
enqueued here such that we re-visit it because we continue
processing a *new*, *bottom* SCC/RefSCC.
- We also need the ability to *skip* SCCs and RefSCCs that get merged
into a larger component. We even need the ability to skip *nodes* from
an SCC that are no longer part of that SCC.
This led to the design you see in the patch which uses SetVector-based
worklists. The RefSCC worklist is always empty until an update occurs
and is just used to handle those RefSCCs created by updates as the
others don't even exist yet and are formed on-demand during the
bottom-up walk. The SCC worklist is pre-populated from the RefSCC, and
we push new SCCs onto it and blacklist existing SCCs on it to get the
desired processing.
We then *directly* update these when updating the call graph as I was
never able to find a satisfactory abstraction around the update
strategy.
Finally, we need to compute the updates for function passes. This is
mostly used as an initial customer of all the update mechanisms to drive
their design to at least cover some real set of use cases. There are
a bunch of interesting things that came out of doing this:
- It is really nice to do this a function at a time because that
function is likely hot in the cache. This means we want even the
function pass adaptor to support online updates to the call graph!
- To update the call graph after arbitrary function pass mutations is
quite hard. We have to build a fairly comprehensive set of
data structures and then process them. Fortunately, some of this code
is related to the code for building the cal graph in the first place.
Unfortunately, very little of it makes any sense to share because the
nature of what we're doing is so very different. I've factored out the
one part that made sense at least.
- We need to transfer these updates into the various structures for the
CGSCC pass manager. Once those were more sanely worked out, this
became relatively easier. But some of those needs necessitated changes
to the LazyCallGraph interface to make it significantly easier to
extract the changed SCCs from an update operation.
- We also need to update the CGSCC analysis manager as the shape of the
graph changes. When an SCC is merged away we need to clear analyses
associated with it from the analysis manager which we didn't have
support for in the analysis manager infrsatructure. New SCCs are easy!
But then we have the case that the original SCC has its shape changed
but remains in the call graph. There we need to *invalidate* the
analyses associated with it.
- We also need to invalidate analyses after we *finish* processing an
SCC. But the analyses we need to invalidate here are *only those for
the newly updated SCC*!!! Because we only continue processing the
bottom SCC, if we split SCCs apart the original one gets invalidated
once when its shape changes and is not processed farther so its
analyses will be correct. It is the bottom SCC which continues being
processed and needs to have the "normal" invalidation done based on
the preserved analyses set.
All of this is mostly background and context for the changes here.
Many thanks to all the reviewers who helped here. Especially Sanjoy who
caught several interesting bugs in the graph algorithms, David, Sean,
and others who all helped with feedback.
Differential Revision: http://reviews.llvm.org/D21464
llvm-svn: 279618
2016-08-24 17:37:14 +08:00
|
|
|
LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \
|
|
|
|
CGSCCUpdateResult &>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 12:49:44 +08:00
|
|
|
} \
|
|
|
|
if (Name == "invalidate<" NAME ">") { \
|
2016-02-26 20:30:18 +08:00
|
|
|
CGPM.addPass(InvalidateAnalysisPass< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 10:10:51 +08:00
|
|
|
}
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : CGSCCPipelineParsingCallbacks)
|
|
|
|
if (C(Name, CGPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown cgscc pass '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2014-04-21 19:12:00 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
|
|
|
|
const PipelineElement &E,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
auto &Name = E.Name;
|
|
|
|
auto &InnerPipeline = E.InnerPipeline;
|
|
|
|
|
|
|
|
// First handle complex passes like the pass managers which carry pipelines.
|
|
|
|
if (!InnerPipeline.empty()) {
|
|
|
|
if (Name == "function") {
|
|
|
|
FunctionPassManager NestedFPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// Add the nested pass manager with the appropriate adaptor.
|
|
|
|
FPM.addPass(std::move(NestedFPM));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
if (Name == "loop") {
|
|
|
|
LoopPassManager LPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass,
|
|
|
|
DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// Add the nested pass manager with the appropriate adaptor.
|
2017-12-29 16:16:06 +08:00
|
|
|
FPM.addPass(
|
|
|
|
createFunctionToLoopPassAdaptor(std::move(LPM), DebugLogging));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
2016-08-03 15:44:48 +08:00
|
|
|
if (auto Count = parseRepeatPassName(Name)) {
|
|
|
|
FunctionPassManager NestedFPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-04 11:52:53 +08:00
|
|
|
FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 15:44:48 +08:00
|
|
|
}
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : FunctionPipelineParsingCallbacks)
|
|
|
|
if (C(Name, FPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Normal passes can't have pipelines.
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid use of '{0}' pass as function pipeline", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// Now expand the basic registered passes from the .inc file.
|
2014-04-21 16:08:50 +08:00
|
|
|
#define FUNCTION_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
|
|
|
FPM.addPass(CREATE_PASS); \
|
2019-01-10 18:01:53 +08:00
|
|
|
return Error::success(); \
|
|
|
|
}
|
|
|
|
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \
|
|
|
|
if (checkParametrizedPassName(Name, NAME)) { \
|
|
|
|
auto Params = parsePassParameters(PARSER, Name, NAME); \
|
|
|
|
if (!Params) \
|
|
|
|
return Params.takeError(); \
|
|
|
|
FPM.addPass(CREATE_PASS(Params.get())); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2014-01-12 20:15:39 +08:00
|
|
|
}
|
2015-01-06 10:10:51 +08:00
|
|
|
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == "require<" NAME ">") { \
|
2016-08-20 02:36:06 +08:00
|
|
|
FPM.addPass( \
|
|
|
|
RequireAnalysisPass< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type, Function>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 12:49:44 +08:00
|
|
|
} \
|
|
|
|
if (Name == "invalidate<" NAME ">") { \
|
2016-02-26 20:30:18 +08:00
|
|
|
FPM.addPass(InvalidateAnalysisPass< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2015-01-06 10:10:51 +08:00
|
|
|
}
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : FunctionPipelineParsingCallbacks)
|
|
|
|
if (C(Name, FPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown function pass '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2014-01-12 17:34:22 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
2016-08-03 15:44:48 +08:00
|
|
|
StringRef Name = E.Name;
|
2016-08-03 11:21:41 +08:00
|
|
|
auto &InnerPipeline = E.InnerPipeline;
|
|
|
|
|
|
|
|
// First handle complex passes like the pass managers which carry pipelines.
|
|
|
|
if (!InnerPipeline.empty()) {
|
|
|
|
if (Name == "loop") {
|
|
|
|
LoopPassManager NestedLPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// Add the nested pass manager with the appropriate adaptor.
|
2016-08-03 17:14:03 +08:00
|
|
|
LPM.addPass(std::move(NestedLPM));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
2016-08-03 15:44:48 +08:00
|
|
|
if (auto Count = parseRepeatPassName(Name)) {
|
|
|
|
LoopPassManager NestedLPM(DebugLogging);
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline,
|
|
|
|
VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-04 11:52:53 +08:00
|
|
|
LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM)));
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-08-03 15:44:48 +08:00
|
|
|
}
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
for (auto &C : LoopPipelineParsingCallbacks)
|
|
|
|
if (C(Name, LPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
2016-08-03 11:21:41 +08:00
|
|
|
// Normal passes can't have pipelines.
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid use of '{0}' pass as loop pipeline", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-08-03 11:21:41 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// Now expand the basic registered passes from the .inc file.
|
2016-02-25 15:23:08 +08:00
|
|
|
#define LOOP_PASS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
2016-08-03 17:14:03 +08:00
|
|
|
LPM.addPass(CREATE_PASS); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == "require<" NAME ">") { \
|
2016-08-03 17:14:03 +08:00
|
|
|
LPM.addPass(RequireAnalysisPass< \
|
2017-01-11 14:23:21 +08:00
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type, Loop, \
|
|
|
|
LoopAnalysisManager, LoopStandardAnalysisResults &, \
|
|
|
|
LPMUpdater &>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2016-02-25 15:23:08 +08:00
|
|
|
} \
|
|
|
|
if (Name == "invalidate<" NAME ">") { \
|
2016-08-03 17:14:03 +08:00
|
|
|
LPM.addPass(InvalidateAnalysisPass< \
|
2016-02-26 20:30:18 +08:00
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>()); \
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success(); \
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : LoopPipelineParsingCallbacks)
|
|
|
|
if (C(Name, LPM, InnerPipeline))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
|
|
|
return make_error<StringError>(formatv("unknown loop pass '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
|
2016-02-18 17:45:17 +08:00
|
|
|
bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
|
2016-03-11 17:15:11 +08:00
|
|
|
#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
|
|
|
AA.registerModuleAnalysis< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>(); \
|
|
|
|
return true; \
|
|
|
|
}
|
2016-02-18 17:45:17 +08:00
|
|
|
#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
|
|
|
|
if (Name == NAME) { \
|
2016-02-26 20:17:54 +08:00
|
|
|
AA.registerFunctionAnalysis< \
|
|
|
|
std::remove_reference<decltype(CREATE_PASS)>::type>(); \
|
2016-02-18 17:45:17 +08:00
|
|
|
return true; \
|
|
|
|
}
|
|
|
|
#include "PassRegistry.def"
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
for (auto &C : AAParsingCallbacks)
|
|
|
|
if (C(Name, AA))
|
|
|
|
return true;
|
2016-02-18 17:45:17 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
|
|
|
|
ArrayRef<PipelineElement> Pipeline,
|
|
|
|
bool VerifyEachPass,
|
|
|
|
bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
for (const auto &Element : Pipeline) {
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// FIXME: No verifier support for Loop passes!
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-02-25 15:23:08 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM,
|
|
|
|
ArrayRef<PipelineElement> Pipeline,
|
|
|
|
bool VerifyEachPass,
|
|
|
|
bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
for (const auto &Element : Pipeline) {
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err =
|
|
|
|
parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
if (VerifyEachPass)
|
|
|
|
FPM.addPass(VerifierPass());
|
2014-01-12 17:34:22 +08:00
|
|
|
}
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2014-01-12 17:34:22 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
|
|
|
|
ArrayRef<PipelineElement> Pipeline,
|
|
|
|
bool VerifyEachPass,
|
|
|
|
bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
for (const auto &Element : Pipeline) {
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
// FIXME: No verifier support for CGSCC passes!
|
2014-04-21 19:12:00 +08:00
|
|
|
}
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2014-04-21 19:12:00 +08:00
|
|
|
}
|
|
|
|
|
2016-05-16 18:13:37 +08:00
|
|
|
void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
|
|
|
|
FunctionAnalysisManager &FAM,
|
|
|
|
CGSCCAnalysisManager &CGAM,
|
|
|
|
ModuleAnalysisManager &MAM) {
|
|
|
|
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
|
|
|
|
MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
|
|
|
|
CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
|
|
|
|
FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
|
|
|
|
FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
|
|
|
|
FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });
|
|
|
|
LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });
|
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
|
|
|
|
ArrayRef<PipelineElement> Pipeline,
|
|
|
|
bool VerifyEachPass,
|
|
|
|
bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
for (const auto &Element : Pipeline) {
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err = parseModulePass(MPM, Element, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
2016-08-03 11:21:41 +08:00
|
|
|
if (VerifyEachPass)
|
|
|
|
MPM.addPass(VerifierPass());
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
}
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
}
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// Primary pass pipeline description parsing routine for a \c ModulePassManager
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
// FIXME: Should this routine accept a TargetMachine or require the caller to
|
|
|
|
// pre-populate the analysis managers with target-specific stuff?
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,
|
|
|
|
StringRef PipelineText,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
2016-08-03 11:21:41 +08:00
|
|
|
auto Pipeline = parsePipelineText(PipelineText);
|
|
|
|
if (!Pipeline || Pipeline->empty())
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid pipeline '{0}'", PipelineText).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-08-03 11:21:41 +08:00
|
|
|
|
|
|
|
// If the first name isn't at the module layer, wrap the pipeline up
|
|
|
|
// automatically.
|
|
|
|
StringRef FirstName = Pipeline->front().Name;
|
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {
|
|
|
|
if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {
|
2016-08-03 11:21:41 +08:00
|
|
|
Pipeline = {{"cgscc", std::move(*Pipeline)}};
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
} else if (isFunctionPassName(FirstName,
|
|
|
|
FunctionPipelineParsingCallbacks)) {
|
2016-08-03 11:21:41 +08:00
|
|
|
Pipeline = {{"function", std::move(*Pipeline)}};
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
} else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks)) {
|
2016-08-03 11:21:41 +08:00
|
|
|
Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}};
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
} else {
|
|
|
|
for (auto &C : TopLevelPipelineParsingCallbacks)
|
|
|
|
if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging))
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
|
|
|
|
|
|
|
// Unknown pass or pipeline name!
|
|
|
|
auto &InnerPipeline = Pipeline->front().InnerPipeline;
|
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown {0} name '{1}'",
|
|
|
|
(InnerPipeline.empty() ? "pass" : "pipeline"), FirstName)
|
|
|
|
.str(),
|
|
|
|
inconvertibleErrorCode());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
}
|
2014-01-12 17:34:22 +08:00
|
|
|
}
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err =
|
|
|
|
parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
|
|
|
return Error::success();
|
[PM] Add (very skeletal) support to opt for running the new pass
manager. I cannot emphasize enough that this is a WIP. =] I expect it
to change a great deal as things stabilize, but I think its really
important to get *some* functionality here so that the infrastructure
can be tested more traditionally from the commandline.
The current design is looking something like this:
./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'
So rather than custom-parsed flags, there is a single flag with a string
argument that is parsed into the pass pipeline structure. This makes it
really easy to have nice structural properties that are very explicit.
There is one obvious and important shortcut. You can start off the
pipeline with a pass, and the minimal context of pass managers will be
built around the entire specified pipeline. This makes the common case
for tests super easy:
./bin/opt -passes=instcombine,sroa,gvn
But this won't introduce any of the complexity of the fully inferred old
system -- we only ever do this for the *entire* argument, and we only
look at the first pass. If the other passes don't fit in the pass
manager selected it is a hard error.
The other interesting aspect here is that I'm not relying on any
registration facilities. Such facilities may be unavoidable for
supporting plugins, but I have alternative ideas for plugins that I'd
like to try first. My plan is essentially to build everything without
registration until we hit an absolute requirement.
Instead of registration of pass names, there will be a library dedicated
to parsing pass names and the pass pipeline strings described above.
Currently, this is directly embedded into opt for simplicity as it is
very early, but I plan to eventually pull this into a library that opt,
bugpoint, and even Clang can depend on. It should end up as a good home
for things like the existing PassManagerBuilder as well.
There are a bunch of FIXMEs in the code for the parts of this that are
just stubbed out to make the patch more incremental. A quick list of
what's coming up directly after this:
- Support for function passes and building the structured nesting.
- Support for printing the pass structure, and FileCheck tests of all of
this code.
- The .def-file based pass name parsing.
- IR priting passes and the corresponding tests.
Some obvious things that I'm not going to do right now, but am
definitely planning on as the pass manager work gets a bit further:
- Pull the parsing into library, including the builders.
- Thread the rest of the target stuff into the new pass manager.
- Wire support for the new pass manager up to llc.
- Plugin support.
Some things that I'd like to have, but are significantly lower on my
priority list. I'll get to these eventually, but they may also be places
where others want to contribute:
- Adding nice error reporting for broken pass pipeline descriptions.
- Typo-correction for pass names.
llvm-svn: 198998
2014-01-11 16:16:35 +08:00
|
|
|
}
|
2016-02-18 17:45:17 +08:00
|
|
|
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
// Primary pass pipeline description parsing routine for a \c CGSCCPassManager
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,
|
|
|
|
StringRef PipelineText,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
auto Pipeline = parsePipelineText(PipelineText);
|
|
|
|
if (!Pipeline || Pipeline->empty())
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid pipeline '{0}'", PipelineText).str(),
|
|
|
|
inconvertibleErrorCode());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
StringRef FirstName = Pipeline->front().Name;
|
|
|
|
if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown cgscc pass '{0}' in pipeline '{1}'", FirstName,
|
|
|
|
PipelineText)
|
|
|
|
.str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
|
|
|
|
if (auto Err =
|
|
|
|
parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Primary pass pipeline description parsing routine for a \c
|
|
|
|
// FunctionPassManager
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM,
|
|
|
|
StringRef PipelineText,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
auto Pipeline = parsePipelineText(PipelineText);
|
|
|
|
if (!Pipeline || Pipeline->empty())
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid pipeline '{0}'", PipelineText).str(),
|
|
|
|
inconvertibleErrorCode());
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
|
|
|
|
StringRef FirstName = Pipeline->front().Name;
|
|
|
|
if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown function pass '{0}' in pipeline '{1}'", FirstName,
|
|
|
|
PipelineText)
|
|
|
|
.str(),
|
|
|
|
inconvertibleErrorCode());
|
|
|
|
|
|
|
|
if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass,
|
|
|
|
DebugLogging))
|
|
|
|
return Err;
|
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Primary pass pipeline description parsing routine for a \c LoopPassManager
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
|
|
|
|
StringRef PipelineText,
|
|
|
|
bool VerifyEachPass, bool DebugLogging) {
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
auto Pipeline = parsePipelineText(PipelineText);
|
|
|
|
if (!Pipeline || Pipeline->empty())
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("invalid pipeline '{0}'", PipelineText).str(),
|
|
|
|
inconvertibleErrorCode());
|
2018-10-15 23:00:18 +08:00
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
if (auto Err =
|
|
|
|
parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging))
|
|
|
|
return Err;
|
|
|
|
|
|
|
|
return Error::success();
|
[PM] Enable registration of out-of-tree passes with PassBuilder
Summary:
This patch adds a callback registration API to the PassBuilder,
enabling registering out-of-tree passes with it.
Through the Callback API, callers may register callbacks with the
various stages at which passes are added into pass managers, including
parsing of a pass pipeline as well as at extension points within the
default -O pipelines.
Registering utilities like `require<>` and `invalidate<>` needs to be
handled manually by the caller, but a helper is provided.
Additionally, adding passes at pipeline extension points is exposed
through the opt tool. This patch adds a `-passes-ep-X` commandline
option for every extension point X, which opt parses into pipelines
inserted into that extension point.
Reviewers: chandlerc
Reviewed By: chandlerc
Subscribers: lksbhm, grosser, davide, mehdi_amini, llvm-commits, mgorny
Differential Revision: https://reviews.llvm.org/D33464
llvm-svn: 307532
2017-07-10 18:57:55 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
|
2016-12-24 04:38:19 +08:00
|
|
|
// If the pipeline just consists of the word 'default' just replace the AA
|
|
|
|
// manager with our default one.
|
|
|
|
if (PipelineText == "default") {
|
|
|
|
AA = buildDefaultAAPipeline();
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-12-24 04:38:19 +08:00
|
|
|
}
|
|
|
|
|
2016-02-18 17:45:17 +08:00
|
|
|
while (!PipelineText.empty()) {
|
|
|
|
StringRef Name;
|
|
|
|
std::tie(Name, PipelineText) = PipelineText.split(',');
|
|
|
|
if (!parseAAPassName(AA, Name))
|
2018-10-17 18:36:23 +08:00
|
|
|
return make_error<StringError>(
|
|
|
|
formatv("unknown alias analysis name '{0}'", Name).str(),
|
|
|
|
inconvertibleErrorCode());
|
2016-02-18 17:45:17 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 18:36:23 +08:00
|
|
|
return Error::success();
|
2016-02-18 17:45:17 +08:00
|
|
|
}
|