[llvm] r261197 - [PM/AA] Teach the new pass manager to use pass-by-lambda for registering

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 18 01:45:18 PST 2016


Author: chandlerc
Date: Thu Feb 18 03:45:17 2016
New Revision: 261197

URL: http://llvm.org/viewvc/llvm-project?rev=261197&view=rev
Log:
[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

Modified:
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/include/llvm/Passes/PassBuilder.h
    llvm/trunk/lib/Passes/PassBuilder.cpp
    llvm/trunk/lib/Passes/PassRegistry.def
    llvm/trunk/test/Other/new-pass-manager.ll
    llvm/trunk/tools/opt/NewPMDriver.cpp
    llvm/trunk/unittests/IR/PassManagerTest.cpp

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Thu Feb 18 03:45:17 2016
@@ -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.

Modified: llvm/trunk/include/llvm/Passes/PassBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Passes/PassBuilder.h?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Passes/PassBuilder.h (original)
+++ llvm/trunk/include/llvm/Passes/PassBuilder.h Thu Feb 18 03:45:17 2016
@@ -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);

Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
+++ llvm/trunk/lib/Passes/PassBuilder.cpp Thu Feb 18 03:45:17 2016
@@ -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(
   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(Modu
 
   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;
+}

Modified: llvm/trunk/lib/Passes/PassRegistry.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/PassRegistry.def (original)
+++ llvm/trunk/lib/Passes/PassRegistry.def Thu Feb 18 03:45:17 2016
@@ -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", Sc
 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

Modified: llvm/trunk/test/Other/new-pass-manager.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pass-manager.ll?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/test/Other/new-pass-manager.ll (original)
+++ llvm/trunk/test/Other/new-pass-manager.ll Thu Feb 18 03:45:17 2016
@@ -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
 }

Modified: llvm/trunk/tools/opt/NewPMDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/tools/opt/NewPMDriver.cpp (original)
+++ llvm/trunk/tools/opt/NewPMDriver.cpp Thu Feb 18 03:45:17 2016
@@ -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 Arg
                            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)

Modified: llvm/trunk/unittests/IR/PassManagerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=261197&r1=261196&r2=261197&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PassManagerTest.cpp (original)
+++ llvm/trunk/unittests/IR/PassManagerTest.cpp Thu Feb 18 03:45:17 2016
@@ -232,13 +232,13 @@ TEST_F(PassManagerTest, BasicPreservedAn
 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;
 




More information about the llvm-commits mailing list