summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/PassManager.h34
-rw-r--r--llvm/include/llvm/Passes/PassBuilder.h28
-rw-r--r--llvm/lib/Passes/PassBuilder.cpp28
-rw-r--r--llvm/lib/Passes/PassRegistry.def8
-rw-r--r--llvm/test/Other/new-pass-manager.ll17
-rw-r--r--llvm/tools/opt/NewPMDriver.cpp33
-rw-r--r--llvm/unittests/IR/PassManagerTest.cpp8
7 files changed, 124 insertions, 32 deletions
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
index 2ceb53d21b7..9b0301b4a66 100644
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -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.
diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h
index 1e605e37417..8b182e1955e 100644
--- a/llvm/include/llvm/Passes/PassBuilder.h
+++ b/llvm/include/llvm/Passes/PassBuilder.h
@@ -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);
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 68ce41aeaff..1a762dfd71b 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -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;
+}
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 1e48d6aa018..703032e31a9 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -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
diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll
index 5bc3940e6b1..da5cff5205d 100644
--- a/llvm/test/Other/new-pass-manager.ll
+++ b/llvm/test/Other/new-pass-manager.ll
@@ -299,14 +299,6 @@
; 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
; CHECK-BASIC-AA: Starting pass manager
@@ -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
}
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 3030d65743a..a95a4ed8a00 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -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)
diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp
index 41af0b0bd25..37939768aaf 100644
--- a/llvm/unittests/IR/PassManagerTest.cpp
+++ b/llvm/unittests/IR/PassManagerTest.cpp
@@ -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;
OpenPOWER on IntegriCloud