mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 15:39:06 +00:00
[PM/AA] Teach the new pass manager to use pass-by-lambda for registering
analysis passes, support pre-registering analyses, and use that to implement parsing and pre-registering a custom alias analysis pipeline. With this its possible to configure the particular alias analysis pipeline used by the AAManager from the commandline of opt. I've updated the test to show this effectively in use to build a pipeline including basic-aa as part of it. My big question for reviewers are around the APIs that are used to expose this functionality. Are folks happy with pass-by-lambda to do pass registration? Are folks happy with pre-registering analyses as a way to inject customized instances of an analysis while still using the registry for the general case? Other thoughts of course welcome. The next round of patches will be to add the rest of the alias analyses into the new pass manager and wire them up here so that they can be used from opt. This will require extending the (somewhate limited) functionality of AAManager w.r.t. module passes. Differential Revision: http://reviews.llvm.org/D17259 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261197 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20dee1f1c0
commit
67a41f0919
@ -342,14 +342,34 @@ public:
|
||||
|
||||
/// \brief Register an analysis pass with the manager.
|
||||
///
|
||||
/// This provides an initialized and set-up analysis pass to the analysis
|
||||
/// manager. Whomever is setting up analysis passes must use this to populate
|
||||
/// the manager with all of the analysis passes available.
|
||||
template <typename PassT> void registerPass(PassT Pass) {
|
||||
assert(!AnalysisPasses.count(PassT::ID()) &&
|
||||
"Registered the same analysis pass twice!");
|
||||
/// The argument is a callable whose result is a pass. This allows passing in
|
||||
/// a lambda to construct the pass.
|
||||
///
|
||||
/// The pass type registered is the result type of calling the argument. If
|
||||
/// that pass has already been registered, then the argument will not be
|
||||
/// called and this function will return false. Otherwise, the pass type
|
||||
/// becomes registered, with the instance provided by calling the argument
|
||||
/// once, and this function returns true.
|
||||
///
|
||||
/// While this returns whether or not the pass type was already registered,
|
||||
/// there in't an independent way to query that as that would be prone to
|
||||
/// risky use when *querying* the analysis manager. Instead, the only
|
||||
/// supported use case is avoiding duplicate registry of an analysis. This
|
||||
/// interface also lends itself to minimizing the number of times we have to
|
||||
/// do lookups for analyses or construct complex passes only to throw them
|
||||
/// away.
|
||||
template <typename PassBuilderT> bool registerPass(PassBuilderT PassBuilder) {
|
||||
typedef decltype(PassBuilder()) PassT;
|
||||
typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT;
|
||||
AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass)));
|
||||
|
||||
auto &PassPtr = AnalysisPasses[PassT::ID()];
|
||||
if (PassPtr)
|
||||
// Already registered this pass type!
|
||||
return false;
|
||||
|
||||
// Construct a new model around the instance returned by the builder.
|
||||
PassPtr.reset(new PassModelT(PassBuilder()));
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Invalidate a specific analysis pass for an IR module.
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/IR/PassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
class AAManager;
|
||||
class TargetMachine;
|
||||
|
||||
/// \brief This class provides access to building LLVM's passes.
|
||||
@ -39,21 +40,24 @@ public:
|
||||
///
|
||||
/// This is an interface that can be used to populate a \c
|
||||
/// ModuleAnalysisManager with all registered module analyses. Callers can
|
||||
/// still manually register any additional analyses.
|
||||
/// still manually register any additional analyses. Callers can also
|
||||
/// pre-register analyses and this will not override those.
|
||||
void registerModuleAnalyses(ModuleAnalysisManager &MAM);
|
||||
|
||||
/// \brief Registers all available CGSCC analysis passes.
|
||||
///
|
||||
/// This is an interface that can be used to populate a \c CGSCCAnalysisManager
|
||||
/// with all registered CGSCC analyses. Callers can still manually register any
|
||||
/// additional analyses.
|
||||
/// additional analyses. Callers can also pre-register analyses and this will
|
||||
/// not override those.
|
||||
void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM);
|
||||
|
||||
/// \brief Registers all available function analysis passes.
|
||||
///
|
||||
/// This is an interface that can be used to populate a \c
|
||||
/// FunctionAnalysisManager with all registered function analyses. Callers can
|
||||
/// still manually register any additional analyses.
|
||||
/// still manually register any additional analyses. Callers can also
|
||||
/// pre-register analyses and this will not override those.
|
||||
void registerFunctionAnalyses(FunctionAnalysisManager &FAM);
|
||||
|
||||
/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
|
||||
@ -87,10 +91,28 @@ public:
|
||||
bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
|
||||
bool VerifyEachPass = true, bool DebugLogging = false);
|
||||
|
||||
/// Parse a textual alias analysis pipeline into the provided AA manager.
|
||||
///
|
||||
/// The format of the textual AA pipeline is a comma separated list of AA
|
||||
/// pass names:
|
||||
///
|
||||
/// basic-aa,globals-aa,...
|
||||
///
|
||||
/// The AA manager is set up such that the provided alias analyses are tried
|
||||
/// in the order specified. See the \c AAManaager documentation for details
|
||||
/// about the logic used. This routine just provides the textual mapping
|
||||
/// between AA names and the analyses to register with the manager.
|
||||
///
|
||||
/// Returns false if the text cannot be parsed cleanly. The specific state of
|
||||
/// the \p AA manager is unspecified if such an error is encountered and this
|
||||
/// returns false.
|
||||
bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
|
||||
|
||||
private:
|
||||
bool parseModulePassName(ModulePassManager &MPM, StringRef Name);
|
||||
bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name);
|
||||
bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name);
|
||||
bool parseAAPassName(AAManager &AA, StringRef Name);
|
||||
bool parseFunctionPassPipeline(FunctionPassManager &FPM,
|
||||
StringRef &PipelineText, bool VerifyEachPass,
|
||||
bool DebugLogging);
|
||||
|
@ -105,19 +105,19 @@ char NoOpFunctionAnalysis::PassID;
|
||||
|
||||
void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
|
||||
#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
|
||||
MAM.registerPass(CREATE_PASS);
|
||||
MAM.registerPass([&] { return CREATE_PASS; });
|
||||
#include "PassRegistry.def"
|
||||
}
|
||||
|
||||
void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
|
||||
#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
|
||||
CGAM.registerPass(CREATE_PASS);
|
||||
CGAM.registerPass([&] { return CREATE_PASS; });
|
||||
#include "PassRegistry.def"
|
||||
}
|
||||
|
||||
void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
|
||||
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
||||
FAM.registerPass(CREATE_PASS);
|
||||
FAM.registerPass([&] { return CREATE_PASS; });
|
||||
#include "PassRegistry.def"
|
||||
}
|
||||
|
||||
@ -214,6 +214,17 @@ bool PassBuilder::parseFunctionPassName(FunctionPassManager &FPM,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
|
||||
#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) { \
|
||||
AA.registerFunctionAnalysis<decltype(CREATE_PASS)>(); \
|
||||
return true; \
|
||||
}
|
||||
#include "PassRegistry.def"
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM,
|
||||
StringRef &PipelineText,
|
||||
bool VerifyEachPass,
|
||||
@ -418,3 +429,14 @@ bool PassBuilder::parsePassPipeline(ModulePassManager &MPM,
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
|
||||
while (!PipelineText.empty()) {
|
||||
StringRef Name;
|
||||
std::tie(Name, PipelineText) = PipelineText.split(',');
|
||||
if (!parseAAPassName(AA, Name))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass())
|
||||
#endif
|
||||
FUNCTION_ANALYSIS("aa", AAManager())
|
||||
FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis())
|
||||
FUNCTION_ANALYSIS("basic-aa", BasicAA())
|
||||
FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
|
||||
FUNCTION_ANALYSIS("loops", LoopAnalysis())
|
||||
FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis())
|
||||
@ -63,6 +62,13 @@ FUNCTION_ANALYSIS("scalar-evolution", ScalarEvolutionAnalysis())
|
||||
FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis())
|
||||
FUNCTION_ANALYSIS("targetir",
|
||||
TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())
|
||||
|
||||
#ifndef FUNCTION_ALIAS_ANALYSIS
|
||||
#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
|
||||
FUNCTION_ANALYSIS(NAME, CREATE_PASS)
|
||||
#endif
|
||||
FUNCTION_ALIAS_ANALYSIS("basic-aa", BasicAA())
|
||||
#undef FUNCTION_ALIAS_ANALYSIS
|
||||
#undef FUNCTION_ANALYSIS
|
||||
|
||||
#ifndef FUNCTION_PASS
|
||||
|
@ -298,14 +298,6 @@
|
||||
; CHECK-DT: Running analysis: DominatorTreeAnalysis
|
||||
; CHECK-DT: Finished pass manager
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
|
||||
; RUN: -passes='require<aa>' \
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-AA
|
||||
; CHECK-AA: Starting pass manager
|
||||
; CHECK-AA: Running pass: RequireAnalysisPass
|
||||
; CHECK-AA: Running analysis: AAManager
|
||||
; CHECK-AA: Finished pass manager
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
|
||||
; RUN: -passes='require<basic-aa>' \
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-BASIC-AA
|
||||
@ -314,6 +306,15 @@
|
||||
; CHECK-BASIC-AA: Running analysis: BasicAA
|
||||
; CHECK-BASIC-AA: Finished pass manager
|
||||
|
||||
; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
|
||||
; RUN: -passes='require<aa>' -aa-pipeline='basic-aa' \
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-AA
|
||||
; CHECK-AA: Starting pass manager
|
||||
; CHECK-AA: Running pass: RequireAnalysisPass
|
||||
; CHECK-AA: Running analysis: AAManager
|
||||
; CHECK-AA: Running analysis: BasicAA
|
||||
; CHECK-AA: Finished pass manager
|
||||
|
||||
define void @foo() {
|
||||
ret void
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "NewPMDriver.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/CGSCCPassManager.h"
|
||||
#include "llvm/Bitcode/BitcodeWriterPass.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
@ -36,6 +37,15 @@ static cl::opt<bool>
|
||||
DebugPM("debug-pass-manager", cl::Hidden,
|
||||
cl::desc("Print pass management debugging information"));
|
||||
|
||||
// This flag specifies a textual description of the alias analysis pipeline to
|
||||
// use when querying for aliasing information. It only works in concert with
|
||||
// the "passes" flag above.
|
||||
static cl::opt<std::string>
|
||||
AAPipeline("aa-pipeline",
|
||||
cl::desc("A textual description of the alias analysis "
|
||||
"pipeline for handling managed aliasing queries"),
|
||||
cl::Hidden);
|
||||
|
||||
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
|
||||
TargetMachine *TM, tool_output_file *Out,
|
||||
StringRef PassPipeline, OutputKind OK,
|
||||
@ -44,22 +54,33 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
|
||||
bool ShouldPreserveBitcodeUseListOrder) {
|
||||
PassBuilder PB(TM);
|
||||
|
||||
// Specially handle the alias analysis manager so that we can register
|
||||
// a custom pipeline of AA passes with it.
|
||||
AAManager AA;
|
||||
if (!PB.parseAAPipeline(AA, AAPipeline)) {
|
||||
errs() << Arg0 << ": unable to parse AA pipeline description.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionAnalysisManager FAM(DebugPM);
|
||||
CGSCCAnalysisManager CGAM(DebugPM);
|
||||
ModuleAnalysisManager MAM(DebugPM);
|
||||
|
||||
// Register the AA manager first so that our version is the one used.
|
||||
FAM.registerPass([&] { return std::move(AA); });
|
||||
|
||||
// Register all the basic analyses with the managers.
|
||||
PB.registerModuleAnalyses(MAM);
|
||||
PB.registerCGSCCAnalyses(CGAM);
|
||||
PB.registerFunctionAnalyses(FAM);
|
||||
|
||||
// Cross register the analysis managers through their proxies.
|
||||
MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
|
||||
MAM.registerPass(CGSCCAnalysisManagerModuleProxy(CGAM));
|
||||
CGAM.registerPass(FunctionAnalysisManagerCGSCCProxy(FAM));
|
||||
CGAM.registerPass(ModuleAnalysisManagerCGSCCProxy(MAM));
|
||||
FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM));
|
||||
FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
|
||||
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
|
||||
MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
|
||||
CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(FAM); });
|
||||
CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
|
||||
FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
|
||||
FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
|
||||
|
||||
ModulePassManager MPM(DebugPM);
|
||||
if (VK > VK_NoVerifier)
|
||||
|
@ -232,13 +232,13 @@ TEST_F(PassManagerTest, BasicPreservedAnalyses) {
|
||||
TEST_F(PassManagerTest, Basic) {
|
||||
FunctionAnalysisManager FAM;
|
||||
int FunctionAnalysisRuns = 0;
|
||||
FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns));
|
||||
FAM.registerPass([&] { return TestFunctionAnalysis(FunctionAnalysisRuns); });
|
||||
|
||||
ModuleAnalysisManager MAM;
|
||||
int ModuleAnalysisRuns = 0;
|
||||
MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns));
|
||||
MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
|
||||
FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
|
||||
MAM.registerPass([&] { return TestModuleAnalysis(ModuleAnalysisRuns); });
|
||||
MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
|
||||
FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
|
||||
|
||||
ModulePassManager MPM;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user