diff options
22 files changed, 720 insertions, 35 deletions
diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h index 5e83ea2..f150064 100644 --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -364,6 +364,10 @@ public: InvalidSCCSet, nullptr, nullptr, InlinedInternalEdges}; + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M); + PreservedAnalyses PA = PreservedAnalyses::all(); CG.buildRefSCCs(); for (auto RCI = CG.postorder_ref_scc_begin(), @@ -428,8 +432,17 @@ public: UR.UpdatedRC = nullptr; UR.UpdatedC = nullptr; + + // Check the PassInstrumentation's BeforePass callbacks before + // running the pass, skip its execution completely if asked to + // (callback returns false). + if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C)) + continue; + PreservedAnalyses PassPA = Pass.run(*C, CGAM, CG, UR); + PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C); + // Update the SCC and RefSCC if necessary. C = UR.UpdatedC ? UR.UpdatedC : C; RC = UR.UpdatedRC ? UR.UpdatedRC : RC; @@ -615,12 +628,20 @@ public: if (CG.lookupSCC(*N) != CurrentC) continue; - PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); + Function &F = N->getFunction(); + + PassInstrumentation PI = FAM.getResult<PassInstrumentationAnalysis>(F); + if (!PI.runBeforePass<Function>(Pass, F)) + continue; + + PreservedAnalyses PassPA = Pass.run(F, FAM); + + PI.runAfterPass<Function>(Pass, F); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. - FAM.invalidate(N->getFunction(), PassPA); + FAM.invalidate(F, PassPA); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -690,6 +711,8 @@ public: PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { PreservedAnalyses PA = PreservedAnalyses::all(); + PassInstrumentation PI = + AM.getResult<PassInstrumentationAnalysis>(InitialC, CG); // The SCC may be refined while we are running passes over it, so set up // a pointer that we can update. @@ -733,8 +756,14 @@ public: auto CallCounts = ScanSCC(*C, CallHandles); for (int Iteration = 0;; ++Iteration) { + + if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C)) + continue; + PreservedAnalyses PassPA = Pass.run(*C, AM, CG, UR); + PI.runAfterPass<LazyCallGraph::SCC>(Pass, *C); + // If the SCC structure has changed, bail immediately and let the outer // CGSCC layer handle any iteration to reflect the refined structure. if (UR.UpdatedC && UR.UpdatedC != C) { diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h new file mode 100644 index 0000000..3fdda6c --- /dev/null +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -0,0 +1,150 @@ +//===- llvm/IR/PassInstrumentation.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines the Pass Instrumentation classes that provide +/// instrumentation points into the pass execution by PassManager. +/// +/// There are two main classes: +/// - PassInstrumentation provides a set of instrumentation points for +/// pass managers to call on. +/// +/// - PassInstrumentationCallbacks registers callbacks and provides access +/// to them for PassInstrumentation. +/// +/// PassInstrumentation object is being used as a result of +/// PassInstrumentationAnalysis (so it is intended to be easily copyable). +/// +/// Intended scheme of use for Pass Instrumentation is as follows: +/// - register instrumentation callbacks in PassInstrumentationCallbacks +/// instance. PassBuilder provides helper for that. +/// +/// - register PassInstrumentationAnalysis with all the PassManagers. +/// PassBuilder handles that automatically when registering analyses. +/// +/// - Pass Manager requests PassInstrumentationAnalysis from analysis manager +/// and gets PassInstrumentation as its result. +/// +/// - Pass Manager invokes PassInstrumentation entry points appropriately, +/// passing StringRef identification ("name") of the pass currently being +/// executed and IRUnit it works on. There can be different schemes of +/// providing names in future, currently it is just a name() of the pass. +/// +/// - PassInstrumentation wraps address of IRUnit into llvm::Any and passes +/// control to all the registered callbacks. Note that we specifically wrap +/// 'const IRUnitT*' so as to avoid any accidental changes to IR in +/// instrumenting callbacks. +/// +/// - Some instrumentation points (BeforePass) allow to control execution +/// of a pass. For those callbacks returning false means pass will not be +/// executed. +/// +/// TODO: currently there is no way for a pass to opt-out of execution control +/// (e.g. become unskippable). PassManager is the only entity that determines +/// how pass instrumentation affects pass execution. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSINSTRUMENTATION_H +#define LLVM_IR_PASSINSTRUMENTATION_H + +#include "llvm/ADT/Any.h" +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/TypeName.h" +#include <type_traits> + +namespace llvm { + +class PreservedAnalyses; + +/// This class manages callbacks registration, as well as provides a way for +/// PassInstrumentation to pass control to the registered callbacks. +class PassInstrumentationCallbacks { +public: + // Before/After Pass callbacks accept IRUnits, so they need to take them + // as pointers, wrapped with llvm::Any + using BeforePassFunc = bool(StringRef, Any); + using AfterPassFunc = void(StringRef, Any); + using BeforeAnalysisFunc = void(StringRef, Any); + using AfterAnalysisFunc = void(StringRef, Any); + +public: + PassInstrumentationCallbacks() {} + + /// Copying PassInstrumentationCallbacks is not intended. + PassInstrumentationCallbacks(const PassInstrumentationCallbacks &) = delete; + void operator=(const PassInstrumentationCallbacks &) = delete; + + template <typename CallableT> void registerBeforePassCallback(CallableT C) { + BeforePassCallbacks.emplace_back(std::move(C)); + } + + template <typename CallableT> void registerAfterPassCallback(CallableT C) { + AfterPassCallbacks.emplace_back(std::move(C)); + } + +private: + friend class PassInstrumentation; + + SmallVector<llvm::unique_function<BeforePassFunc>, 4> BeforePassCallbacks; + SmallVector<llvm::unique_function<AfterPassFunc>, 4> AfterPassCallbacks; +}; + +/// This class provides instrumentation entry points for the Pass Manager, +/// doing calls to callbacks registered in PassInstrumentationCallbacks. +class PassInstrumentation { + PassInstrumentationCallbacks *Callbacks; + +public: + /// Callbacks object is not owned by PassInstrumentation, its life-time + /// should at least match the life-time of corresponding + /// PassInstrumentationAnalysis (which usually is till the end of current + /// compilation). + PassInstrumentation(PassInstrumentationCallbacks *CB = nullptr) + : Callbacks(CB) {} + + /// BeforePass instrumentation point - takes \p Pass instance to be executed + /// and constant reference to IR it operates on. \Returns true if pass is + /// allowed to be executed. + template <typename IRUnitT, typename PassT> + bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const { + if (!Callbacks) + return true; + + bool ShouldRun = true; + for (auto &C : Callbacks->BeforePassCallbacks) + ShouldRun &= C(Pass.name(), llvm::Any(&IR)); + return ShouldRun; + } + + /// AfterPass instrumentation point - takes \p Pass instance that has + /// just been executed and constant reference to IR it operates on. + template <typename IRUnitT, typename PassT> + void runAfterPass(const PassT &Pass, const IRUnitT &IR) const { + if (Callbacks) + for (auto &C : Callbacks->AfterPassCallbacks) + C(Pass.name(), llvm::Any(&IR)); + } + + /// Handle invalidation from the pass manager when PassInstrumentation + /// is used as the result of PassInstrumentationAnalysis. + /// + /// On attempt to invalidate just return false. There is nothing to become + /// invalid here. + template <typename IRUnitT, typename... ExtraArgsT> + bool invalidate(IRUnitT &, const class llvm::PreservedAnalyses &, + ExtraArgsT...) { + return false; + } +}; + +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 3c18bbd..f318237 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -44,6 +44,7 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassInstrumentation.h" #include "llvm/IR/PassManagerInternal.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TypeName.h" @@ -402,6 +403,43 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> { } }; +namespace detail { + +/// Actual unpacker of extra arguments in getAnalysisResult, +/// passes only those tuple arguments that are mentioned in index_sequence. +template <typename PassT, typename IRUnitT, typename AnalysisManagerT, + typename... ArgTs, size_t... Ns> +typename PassT::Result +getAnalysisResultUnpackTuple(AnalysisManagerT &AM, IRUnitT &IR, + std::tuple<ArgTs...> Args, + llvm::index_sequence<Ns...>) { + (void)Args; + return AM.template getResult<PassT>(IR, std::get<Ns>(Args)...); +} + +/// Helper for *partial* unpacking of extra arguments in getAnalysisResult. +/// +/// Arguments passed in tuple come from PassManager, so they might have extra +/// arguments after those AnalysisManager's ExtraArgTs ones that we need to +/// pass to getResult. +template <typename PassT, typename IRUnitT, typename... AnalysisArgTs, + typename... MainArgTs> +typename PassT::Result +getAnalysisResult(AnalysisManager<IRUnitT, AnalysisArgTs...> &AM, IRUnitT &IR, + std::tuple<MainArgTs...> Args) { + return (getAnalysisResultUnpackTuple< + PassT, IRUnitT>)(AM, IR, Args, + llvm::index_sequence_for<AnalysisArgTs...>{}); +} + +} // namespace detail + +// Forward declare the pass instrumentation analysis explicitly queried in +// generic PassManager code. +// FIXME: figure out a way to move PassInstrumentationAnalysis into its own +// header. +class PassInstrumentationAnalysis; + /// Manages a sequence of passes over a particular unit of IR. /// /// A pass manager contains a sequence of passes to run over a particular unit @@ -445,15 +483,34 @@ public: ExtraArgTs... ExtraArgs) { PreservedAnalyses PA = PreservedAnalyses::all(); + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + // Here we use std::tuple wrapper over getResult which helps to extract + // AnalysisManager's arguments out of the whole ExtraArgs set. + PassInstrumentation PI = + detail::getAnalysisResult<PassInstrumentationAnalysis>( + AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...)); + if (DebugLogging) dbgs() << "Starting " << getTypeName<IRUnitT>() << " pass manager run.\n"; for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + auto *P = Passes[Idx].get(); if (DebugLogging) - dbgs() << "Running pass: " << Passes[Idx]->name() << " on " - << IR.getName() << "\n"; + dbgs() << "Running pass: " << P->name() << " on " << IR.getName() + << "\n"; + + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns + // false). + if (!PI.runBeforePass<IRUnitT>(*P, IR)) + continue; + + PreservedAnalyses PassPA = P->run(IR, AM, ExtraArgs...); - PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM, ExtraArgs...); + // Call onto PassInstrumentation's AfterPass callbacks immediately after + // running the pass. + PI.runAfterPass<IRUnitT>(*P, IR); // Update the analysis manager as each pass runs and potentially // invalidates analyses. @@ -510,6 +567,32 @@ extern template class PassManager<Function>; /// Convenience typedef for a pass manager over functions. using FunctionPassManager = PassManager<Function>; +/// Pseudo-analysis pass that exposes the \c PassInstrumentation to pass +/// managers. Goes before AnalysisManager definition to provide its +/// internals (e.g PassInstrumentationAnalysis::ID) for use there if needed. +/// FIXME: figure out a way to move PassInstrumentationAnalysis into its own +/// header. +class PassInstrumentationAnalysis + : public AnalysisInfoMixin<PassInstrumentationAnalysis> { + friend AnalysisInfoMixin<PassInstrumentationAnalysis>; + static AnalysisKey Key; + + PassInstrumentationCallbacks *Callbacks; + +public: + /// PassInstrumentationCallbacks object is shared, owned by something else, + /// not this analysis. + PassInstrumentationAnalysis(PassInstrumentationCallbacks *Callbacks = nullptr) + : Callbacks(Callbacks) {} + + using Result = PassInstrumentation; + + template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> + Result run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) { + return PassInstrumentation(Callbacks); + } +}; + /// A container for analyses that lazily runs them and caches their /// results. /// @@ -1192,13 +1275,24 @@ public: FunctionAnalysisManager &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(M); + PreservedAnalyses PA = PreservedAnalyses::all(); for (Function &F : M) { if (F.isDeclaration()) continue; + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns + // false). + if (!PI.runBeforePass<Function>(Pass, F)) + continue; PreservedAnalyses PassPA = Pass.run(F, FAM); + PI.runAfterPass(Pass, F); + // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. @@ -1302,10 +1396,26 @@ public: RepeatedPass(int Count, PassT P) : Count(Count), P(std::move(P)) {} template <typename IRUnitT, typename AnalysisManagerT, typename... Ts> - PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, Ts &&... Args) { + PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, Ts &&... Args) { + + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + // Here we use std::tuple wrapper over getResult which helps to extract + // AnalysisManager's arguments out of the whole Args set. + PassInstrumentation PI = + detail::getAnalysisResult<PassInstrumentationAnalysis>( + AM, IR, std::tuple<Ts...>(Args...)); + auto PA = PreservedAnalyses::all(); - for (int i = 0; i < Count; ++i) - PA.intersect(P.run(Arg, AM, std::forward<Ts>(Args)...)); + for (int i = 0; i < Count; ++i) { + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns + // false). + if (!PI.runBeforePass<IRUnitT>(P, IR)) + continue; + PA.intersect(P.run(IR, AM, std::forward<Ts>(Args)...)); + PI.runAfterPass(P, IR); + } return PA; } diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 24a93bc..02d3dc3 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -58,6 +58,7 @@ struct PGOOptions { class PassBuilder { TargetMachine *TM; Optional<PGOOptions> PGOOpt; + PassInstrumentationCallbacks *PIC; public: /// A struct to capture parsed pass pipeline names. @@ -172,8 +173,9 @@ public: }; explicit PassBuilder(TargetMachine *TM = nullptr, - Optional<PGOOptions> PGOOpt = None) - : TM(TM), PGOOpt(PGOOpt) {} + Optional<PGOOptions> PGOOpt = None, + PassInstrumentationCallbacks *PIC = nullptr) + : TM(TM), PGOOpt(PGOOpt), PIC(PIC) {} /// Cross register the analysis managers through their proxies. /// diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h index 0d691f3..e54960d 100644 --- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -276,7 +276,15 @@ public: // pass pipeline to put loops into their canonical form. Note that we can // directly build up function analyses after this as the function pass // manager handles all the invalidation at that layer. - PreservedAnalyses PA = LoopCanonicalizationFPM.run(F, AM); + PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(F); + + PreservedAnalyses PA = PreservedAnalyses::all(); + // Check the PassInstrumentation's BeforePass callbacks before running the + // canonicalization pipeline. + if (PI.runBeforePass<Function>(LoopCanonicalizationFPM, F)) { + PA = LoopCanonicalizationFPM.run(F, AM); + PI.runAfterPass<Function>(LoopCanonicalizationFPM, F); + } // Get the loop structure for this function LoopInfo &LI = AM.getResult<LoopAnalysis>(F); @@ -337,8 +345,15 @@ public: assert(L->isRecursivelyLCSSAForm(LAR.DT, LI) && "Loops must remain in LCSSA form!"); #endif - + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns + // false). + if (!PI.runBeforePass<Loop>(Pass, *L)) + continue; PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater); + + PI.runAfterPass<Loop>(Pass, *L); + // FIXME: We should verify the set of analyses relevant to Loop passes // are preserved. diff --git a/llvm/lib/Analysis/CGSCCPassManager.cpp b/llvm/lib/Analysis/CGSCCPassManager.cpp index b325afb..6965235 100644 --- a/llvm/lib/Analysis/CGSCCPassManager.cpp +++ b/llvm/lib/Analysis/CGSCCPassManager.cpp @@ -54,6 +54,11 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, CGSCCUpdateResult &>::run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &G, CGSCCUpdateResult &UR) { + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = + AM.getResult<PassInstrumentationAnalysis>(InitialC, G); + PreservedAnalyses PA = PreservedAnalyses::all(); if (DebugLogging) @@ -67,8 +72,15 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, if (DebugLogging) dbgs() << "Running pass: " << Pass->name() << " on " << *C << "\n"; + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns false). + if (!PI.runBeforePass(*Pass, *C)) + continue; + PreservedAnalyses PassPA = Pass->run(*C, AM, G, UR); + PI.runAfterPass(*Pass, *C); + // Update the SCC if necessary. C = UR.UpdatedC ? UR.UpdatedC : C; diff --git a/llvm/lib/FuzzMutate/IRMutator.cpp b/llvm/lib/FuzzMutate/IRMutator.cpp index 2dc7dfb..40e402c 100644 --- a/llvm/lib/FuzzMutate/IRMutator.cpp +++ b/llvm/lib/FuzzMutate/IRMutator.cpp @@ -73,6 +73,7 @@ static void eliminateDeadCode(Function &F) { FPM.addPass(DCEPass()); FunctionAnalysisManager FAM; FAM.registerPass([&] { return TargetLibraryAnalysis(); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); FPM.run(F, FAM); } diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index a194b84..2586f98 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -42,6 +42,7 @@ add_llvm_library(LLVMCore Operator.cpp OptBisect.cpp Pass.cpp + PassInstrumentation.cpp PassManager.cpp PassRegistry.cpp PassTimingInfo.cpp diff --git a/llvm/lib/IR/PassInstrumentation.cpp b/llvm/lib/IR/PassInstrumentation.cpp new file mode 100644 index 0000000..5aa2bc6 --- /dev/null +++ b/llvm/lib/IR/PassInstrumentation.cpp @@ -0,0 +1,22 @@ +//===- PassInstrumentation.cpp - Pass Instrumentation interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides the implementation of PassInstrumentation class. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/PassInstrumentation.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +AnalysisKey PassInstrumentationAnalysis::Key; + +} // namespace llvm diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 5748c0d..b070b0e 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -26,6 +26,7 @@ MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis()) MODULE_ANALYSIS("profile-summary", ProfileSummaryAnalysis()) MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) MODULE_ANALYSIS("verify", VerifierAnalysis()) +MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) #ifndef MODULE_ALIAS_ANALYSIS #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ @@ -84,6 +85,7 @@ MODULE_PASS("verify", VerifierPass()) #endif CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) CGSCC_ANALYSIS("fam-proxy", FunctionAnalysisManagerCGSCCProxy()) +CGSCC_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) #undef CGSCC_ANALYSIS #ifndef CGSCC_PASS @@ -121,6 +123,7 @@ FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) FUNCTION_ANALYSIS("targetir", TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()) FUNCTION_ANALYSIS("verify", VerifierAnalysis()) +FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) #ifndef FUNCTION_ALIAS_ANALYSIS #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ @@ -226,6 +229,7 @@ FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass()) LOOP_ANALYSIS("no-op-loop", NoOpLoopAnalysis()) LOOP_ANALYSIS("access-info", LoopAccessAnalysis()) LOOP_ANALYSIS("ivusers", IVUsersAnalysis()) +LOOP_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis(PIC)) #undef LOOP_ANALYSIS #ifndef LOOP_PASS diff --git a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp index 10f6fcd..6759bd2 100644 --- a/llvm/lib/Transforms/Scalar/LoopPassManager.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPassManager.cpp @@ -30,12 +30,22 @@ PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, if (DebugLogging) dbgs() << "Starting Loop pass manager run.\n"; + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + PassInstrumentation PI = AM.getResult<PassInstrumentationAnalysis>(L, AR); for (auto &Pass : Passes) { if (DebugLogging) dbgs() << "Running pass: " << Pass->name() << " on " << L; + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns false). + if (!PI.runBeforePass<Loop>(*Pass, L)) + continue; + PreservedAnalyses PassPA = Pass->run(L, AM, AR, U); + PI.runAfterPass<Loop>(*Pass, L); + // If the loop was deleted, abort the run and return to the outer walk. if (U.skipCurrentLoop()) { PA.intersect(std::move(PassPA)); diff --git a/llvm/test/Other/loop-pm-invalidation.ll b/llvm/test/Other/loop-pm-invalidation.ll index a6f5302..20acb35 100644 --- a/llvm/test/Other/loop-pm-invalidation.ll +++ b/llvm/test/Other/loop-pm-invalidation.ll @@ -73,6 +73,7 @@ define void @one_loop(i1* %ptr) { ; CHECK-LOOP-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}LoopAnalysis @@ -90,6 +91,7 @@ define void @one_loop(i1* %ptr) { ; CHECK-LOOP-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -108,6 +110,7 @@ define void @one_loop(i1* %ptr) { ; CHECK-SCEV-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ScalarEvolutionAnalysis @@ -123,6 +126,7 @@ define void @one_loop(i1* %ptr) { ; CHECK-SCEV-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -153,9 +157,11 @@ define void @nested_loops(i1* %ptr) { ; CHECK-LOOP-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}LoopAnalysis @@ -174,9 +180,11 @@ define void @nested_loops(i1* %ptr) { ; CHECK-LOOP-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -195,9 +203,11 @@ define void @nested_loops(i1* %ptr) { ; CHECK-SCEV-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ScalarEvolutionAnalysis @@ -214,9 +224,11 @@ define void @nested_loops(i1* %ptr) { ; CHECK-SCEV-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -254,6 +266,7 @@ define void @dead_loop() { ; CHECK-LOOP-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}LoopAnalysis @@ -271,6 +284,7 @@ define void @dead_loop() { ; CHECK-LOOP-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-LOOP-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-LOOP-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-LOOP-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-LOOP-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-LOOP-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -289,6 +303,7 @@ define void @dead_loop() { ; CHECK-SCEV-INV-NEXT: Running analysis: TargetIRAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Running pass: InvalidateAnalysisPass<{{.*}}ScalarEvolutionAnalysis @@ -304,6 +319,7 @@ define void @dead_loop() { ; CHECK-SCEV-INV-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-SCEV-INV-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Loop pass manager run. ; CHECK-SCEV-INV-NEXT: Finished {{.*}}Function pass manager run. @@ -322,6 +338,7 @@ define void @dead_loop() { ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Running analysis: TargetIRAnalysis ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Loop ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Starting {{.*}}Loop pass manager run. +; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Running pass: NoOpLoopPass ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Running pass: LoopDeletionPass ; CHECK-SCEV-INV-AFTER-DELETE-NEXT: Clearing all analysis results for: diff --git a/llvm/test/Other/new-pass-manager.ll b/llvm/test/Other/new-pass-manager.ll index 320fd04..5f5ba19 100644 --- a/llvm/test/Other/new-pass-manager.ll +++ b/llvm/test/Other/new-pass-manager.ll @@ -24,6 +24,7 @@ ; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*(FunctionAnalysisManager|AnalysisManager<.*Function.*>).*}},{{.*}}Module> ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-CGSCC-PASS-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-CGSCC-PASS-NEXT: Starting CGSCC pass manager run ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass ; CHECK-CGSCC-PASS-NEXT: Finished CGSCC pass manager run @@ -38,6 +39,7 @@ ; CHECK-FUNCTION-PASS: Starting llvm::Module pass manager run ; CHECK-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor ; CHECK-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-FUNCTION-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass ; CHECK-FUNCTION-PASS-NEXT: Finished llvm::Function pass manager run @@ -408,6 +410,7 @@ ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*(FunctionAnalysisManager|AnalysisManager<.*Function.*>).*}},{{.*}}Module> ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-REPEAT-CGSCC-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run ; CHECK-REPEAT-CGSCC-PASS-NEXT: Running pass: RepeatedPass ; CHECK-REPEAT-CGSCC-PASS-NEXT: Starting CGSCC pass manager run @@ -428,6 +431,7 @@ ; CHECK-REPEAT-FUNCTION-PASS: Starting llvm::Module pass manager run ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Running pass: RepeatedPass ; CHECK-REPEAT-FUNCTION-PASS-NEXT: Starting llvm::Function pass manager run @@ -448,6 +452,7 @@ ; CHECK-REPEAT-LOOP-PASS: Starting llvm::Module pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Function pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: FunctionToLoopPassAdaptor ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting llvm::Function pass manager run @@ -464,6 +469,7 @@ ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: TargetIRAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}> ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run +; CHECK-REPEAT-LOOP-PASS-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: RepeatedPass ; CHECK-REPEAT-LOOP-PASS-NEXT: Starting Loop pass manager run ; CHECK-REPEAT-LOOP-PASS-NEXT: Running pass: NoOpLoopPass diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll index 10580e4..114514a 100644 --- a/llvm/test/Other/new-pm-defaults.ll +++ b/llvm/test/Other/new-pm-defaults.ll @@ -67,7 +67,8 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O3 \ ; RUN: --check-prefix=CHECK-EP-PIPELINE-START -; CHECK-O: Starting llvm::Module pass manager run. +; CHECK-O: Running analysis: PassInstrumentationAnalysis +; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}> ; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: ForceFunctionAttrsPass @@ -78,6 +79,7 @@ ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -110,6 +112,7 @@ ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> @@ -149,6 +152,7 @@ ; CHECK-O-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Starting Loop pass manager run. +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Running pass: LoopInstSimplifyPass ; CHECK-O-NEXT: Running pass: LoopSimplifyCFGPass ; CHECK-O-NEXT: Running pass: LoopRotatePass diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll index 741ed64..92b4153 100644 --- a/llvm/test/Other/new-pm-lto-defaults.ll +++ b/llvm/test/Other/new-pm-lto-defaults.ll @@ -23,7 +23,8 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-O --check-prefix=CHECK-O2 \ ; RUN: --check-prefix=CHECK-O3 --check-prefix=CHECK-EP-Peephole -; CHECK-O: Starting llvm::Module pass manager run. +; CHECK-O: Running analysis: PassInstrumentationAnalysis +; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module ; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: GlobalDCEPass @@ -32,6 +33,7 @@ ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-O2-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}Module +; CHECK-O2-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O2-NEXT: Starting llvm::Function pass manager run. ; CHECK-O2-NEXT: Running pass: CallSiteSplittingPass on foo ; CHECK-O2-NEXT: Running analysis: TargetLibraryAnalysis on foo diff --git a/llvm/test/Other/new-pm-thinlto-defaults.ll b/llvm/test/Other/new-pm-thinlto-defaults.ll index dae51eb..ece33c8 100644 --- a/llvm/test/Other/new-pm-thinlto-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-defaults.ll @@ -47,7 +47,8 @@ ; RUN: -passes='thinlto<O2>' -S %s 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=CHECK-O,CHECK-O2,CHECK-POSTLINK-O,CHECK-POSTLINK-O2 ; -; CHECK-O: Starting llvm::Module pass manager run. +; CHECK-O: Running analysis: PassInstrumentationAnalysis +; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: PassManager<{{.*}}Module{{.*}}> ; CHECK-O-NEXT: Starting llvm::Module pass manager run. ; CHECK-O-NEXT: Running pass: ForceFunctionAttrsPass @@ -64,6 +65,7 @@ ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis ; CHECK-O-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> ; CHECK-PRELINK-O-NODIS-NEXT: Running analysis: InnerAnalysisManagerProxy +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting llvm::Function pass manager run. ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -95,6 +97,7 @@ ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}> ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: LazyCallGraphAnalysis +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Starting CGSCC pass manager run. ; CHECK-O-NEXT: Running pass: InlinerPass ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy<{{.*}}LazyCallGraph{{.*}}> @@ -133,6 +136,7 @@ ; CHECK-O-NEXT: Running analysis: ScalarEvolutionAnalysis ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Starting Loop pass manager run. +; CHECK-O-NEXT: Running analysis: PassInstrumentationAnalysis ; CHECK-O-NEXT: Running pass: LoopInstSimplifyPass ; CHECK-O-NEXT: Running pass: LoopSimplifyCFGPass ; CHECK-O-NEXT: Running pass: LoopRotatePass diff --git a/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll b/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll index 164f7a6..ba9f087 100644 --- a/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll +++ b/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll @@ -33,7 +33,8 @@ ; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_g ; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_g ; CHECK-NEXT: Finished llvm::Function pass manager run. -; CHECK-NEXT: Starting llvm::Function pass manager run. +; CHECK-NOT: Invalidating analysis: +; CHECK: Starting llvm::Function pass manager run. ; CHECK-NEXT: Running pass: DominatorTreeVerifierPass on test1_h ; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h ; CHECK-NEXT: Finished llvm::Function pass manager run. diff --git a/llvm/test/Transforms/LoopRotate/pr35210.ll b/llvm/test/Transforms/LoopRotate/pr35210.ll index e92ae4b4..3033ca8 100644 --- a/llvm/test/Transforms/LoopRotate/pr35210.ll +++ b/llvm/test/Transforms/LoopRotate/pr35210.ll @@ -21,6 +21,7 @@ ; CHECK-NEXT: Running analysis: TargetIRAnalysis on f ; CHECK-NEXT: Running analysis: InnerAnalysisManagerProxy{{.*}} on f ; CHECK-NEXT: Starting Loop pass manager run. +; CHECK-NEXT: Running analysis: PassInstrumentationAnalysis on bb ; CHECK-NEXT: Running pass: LoopRotatePass on Loop at depth 1 containing: %bb<header><exiting>,%bb4<latch> ; CHECK-NEXT: Folding loop latch bb4 into bb ; CHECK-NEXT: Invalidating all non-preserved analyses for: bb diff --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp index aa0be73..60da2bb 100644 --- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp @@ -231,6 +231,13 @@ public: MAM.registerPass([&] { return TargetLibraryAnalysis(); }); MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); + + // Register required pass instrumentation analysis. + MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + CGAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + + // Cross-register proxies. MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); }); CGAM.registerPass([&] { return FunctionAnalysisManagerCGSCCProxy(); }); CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); }); diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp index e46fc17..024e7d6 100644 --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -7,14 +7,18 @@ // //===----------------------------------------------------------------------===// +#include <functional> #include <gmock/gmock.h> #include <gtest/gtest.h> +#include <llvm/ADT/Any.h> #include <llvm/Analysis/CGSCCPassManager.h> #include <llvm/Analysis/LoopAnalysisManager.h> #include <llvm/AsmParser/Parser.h> #include <llvm/IR/LLVMContext.h> +#include <llvm/IR/PassInstrumentation.h> #include <llvm/IR/PassManager.h> #include <llvm/Passes/PassBuilder.h> +#include <llvm/Support/Regex.h> #include <llvm/Support/SourceMgr.h> #include <llvm/Transforms/Scalar/LoopPassManager.h> @@ -32,7 +36,10 @@ static std::ostream &operator<<(std::ostream &O, StringRef S) { } namespace { +using testing::AnyNumber; +using testing::AtLeast; using testing::DoDefault; +using testing::Not; using testing::Return; using testing::Expectation; using testing::Invoke; @@ -87,6 +94,7 @@ public: typename Analysis::Result getResult() { return typename Analysis::Result(static_cast<DerivedT &>(*this)); } + static StringRef getName() { return llvm::getTypeName<DerivedT>(); } protected: // FIXME: MSVC seems unable to handle a lambda argument to Invoke from within @@ -143,6 +151,8 @@ public: } }; + static StringRef getName() { return llvm::getTypeName<DerivedT>(); } + Pass getPass() { return Pass(static_cast<DerivedT &>(*this)); } protected: @@ -258,6 +268,81 @@ static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { return parseAssemblyString(IR, Err, C); } +/// Helper for HasName matcher that returns getName both for IRUnit and +/// for IRUnit pointer wrapper into llvm::Any (wrapped by PassInstrumentation). +template <typename IRUnitT> std::string getName(const IRUnitT &IR) { + return IR.getName(); +} + +template <> std::string getName(const StringRef &name) { return name; } + +template <> std::string getName(const llvm::Any &WrappedIR) { + if (any_isa<const Module *>(WrappedIR)) + return any_cast<const Module *>(WrappedIR)->getName().str(); + if (any_isa<const Function *>(WrappedIR)) + return any_cast<const Function *>(WrappedIR)->getName().str(); + if (any_isa<const Loop *>(WrappedIR)) + return any_cast<const Loop *>(WrappedIR)->getName().str(); + if (any_isa<const LazyCallGraph::SCC *>(WrappedIR)) + return any_cast<const LazyCallGraph::SCC *>(WrappedIR)->getName(); + return "<UNKNOWN>"; +} +/// Define a custom matcher for objects which support a 'getName' method. +/// +/// LLVM often has IR objects or analysis objects which expose a name +/// and in tests it is convenient to match these by name for readability. +/// Usually, this name is either a StringRef or a plain std::string. This +/// matcher supports any type exposing a getName() method of this form whose +/// return value is compatible with an std::ostream. For StringRef, this uses +/// the shift operator defined above. +/// +/// It should be used as: +/// +/// HasName("my_function") +/// +/// No namespace or other qualification is required. +MATCHER_P(HasName, Name, "") { + *result_listener << "has name '" << getName(arg) << "'"; + return Name == getName(arg); +} + +MATCHER_P(HasNameRegex, Name, "") { + *result_listener << "has name '" << getName(arg) << "'"; + llvm::Regex r(Name); + return r.match(getName(arg)); +} + +struct MockPassInstrumentationCallbacks { + PassInstrumentationCallbacks Callbacks; + + MockPassInstrumentationCallbacks() { + ON_CALL(*this, runBeforePass(_, _)).WillByDefault(Return(true)); + } + MOCK_METHOD2(runBeforePass, bool(StringRef PassID, llvm::Any)); + MOCK_METHOD2(runAfterPass, void(StringRef PassID, llvm::Any)); + + void registerPassInstrumentation() { + Callbacks.registerBeforePassCallback([this](StringRef P, llvm::Any IR) { + return this->runBeforePass(P, IR); + }); + Callbacks.registerAfterPassCallback( + [this](StringRef P, llvm::Any IR) { this->runAfterPass(P, IR); }); + } + + void ignoreNonMockPassInstrumentation(StringRef IRName) { + // Generic EXPECT_CALLs are needed to match instrumentation on unimportant + // parts of a pipeline that we do not care about (e.g. various passes added + // by default by PassBuilder - Verifier pass etc). + // Make sure to avoid ignoring Mock passes/analysis, we definitely want + // to check these explicitly. + EXPECT_CALL(*this, + runBeforePass(Not(HasNameRegex("Mock")), HasName(IRName))) + .Times(AnyNumber()); + EXPECT_CALL(*this, runAfterPass(Not(HasNameRegex("Mock")), HasName(IRName))) + .Times(AnyNumber()); + } +}; + template <typename PassManagerT> class PassBuilderCallbacksTest; /// This test fixture is shared between all the actual tests below and @@ -280,6 +365,8 @@ protected: LLVMContext Context; std::unique_ptr<Module> M; + MockPassInstrumentationCallbacks CallbacksHandle; + PassBuilder PB; ModulePassManager PM; LoopAnalysisManager LAM; @@ -312,6 +399,7 @@ protected: "exit:\n" " ret void\n" "}\n")), + CallbacksHandle(), PB(nullptr, None, &CallbacksHandle.Callbacks), PM(true), LAM(true), FAM(true), CGAM(true), AM(true) { /// Register a callback for analysis registration. @@ -356,25 +444,6 @@ protected: } }; -/// Define a custom matcher for objects which support a 'getName' method. -/// -/// LLVM often has IR objects or analysis objects which expose a name -/// and in tests it is convenient to match these by name for readability. -/// Usually, this name is either a StringRef or a plain std::string. This -/// matcher supports any type exposing a getName() method of this form whose -/// return value is compatible with an std::ostream. For StringRef, this uses -/// the shift operator defined above. -/// -/// It should be used as: -/// -/// HasName("my_function") -/// -/// No namespace or other qualification is required. -MATCHER_P(HasName, Name, "") { - *result_listener << "has name '" << arg.getName() << "'"; - return Name == arg.getName(); -} - using ModuleCallbacksTest = PassBuilderCallbacksTest<ModulePassManager>; using CGSCCCallbacksTest = PassBuilderCallbacksTest<CGSCCPassManager>; using FunctionCallbacksTest = PassBuilderCallbacksTest<FunctionPassManager>; @@ -391,6 +460,57 @@ TEST_F(ModuleCallbacksTest, Passes) { StringRef PipelineText = "test-transform"; ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) << "Pipeline was: " << PipelineText; + + PM.run(*M, AM); +} + +TEST_F(ModuleCallbacksTest, InstrumentedPasses) { + EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)); + EXPECT_CALL(PassHandle, run(HasName("<string>"), _)) + .WillOnce(Invoke(getAnalysisResult)); + + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation not specifically mentioned below can be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + + // PassInstrumentation calls should happen in-sequence, in the same order + // as passes/analyses are scheduled. + ::testing::Sequence PISequence; + EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), + HasName("<string>"))) + .InSequence(PISequence); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), HasName("<string>"))) + .InSequence(PISequence); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + + PM.run(*M, AM); +} + +TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation run here can safely be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + + // Skip the pass by returning false. + EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), + HasName("<string>"))) + .WillOnce(Return(false)); + + EXPECT_CALL(AnalysisHandle, run(HasName("<string>"), _)).Times(0); + EXPECT_CALL(PassHandle, run(HasName("<string>"), _)).Times(0); + + // As the pass is skipped there is no afterPass as well. + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + .Times(0); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); } @@ -405,6 +525,56 @@ TEST_F(FunctionCallbacksTest, Passes) { PM.run(*M, AM); } +TEST_F(FunctionCallbacksTest, InstrumentedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation not specifically mentioned below can be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); + + EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)); + EXPECT_CALL(PassHandle, run(HasName("foo"), _)) + .WillOnce(Invoke(getAnalysisResult)); + + // PassInstrumentation calls should happen in-sequence, in the same order + // as passes/analyses are scheduled. + ::testing::Sequence PISequence; + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"))) + .InSequence(PISequence); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), HasName("foo"))) + .InSequence(PISequence); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + +TEST_F(FunctionCallbacksTest, InstrumentedSkippedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation run here can safely be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); + + // Skip the pass by returning false. + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("foo"))) + .WillOnce(Return(false)); + + EXPECT_CALL(AnalysisHandle, run(HasName("foo"), _)).Times(0); + EXPECT_CALL(PassHandle, run(HasName("foo"), _)).Times(0); + + // As the pass is skipped there is no afterPass as well. + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + .Times(0); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + TEST_F(LoopCallbacksTest, Passes) { EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) @@ -416,6 +586,58 @@ TEST_F(LoopCallbacksTest, Passes) { PM.run(*M, AM); } +TEST_F(LoopCallbacksTest, InstrumentedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation not specifically mentioned below can be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); + CallbacksHandle.ignoreNonMockPassInstrumentation("loop"); + + EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)); + EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)) + .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); + + // PassInstrumentation calls should happen in-sequence, in the same order + // as passes/analyses are scheduled. + ::testing::Sequence PISequence; + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) + .InSequence(PISequence); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), HasName("loop"))) + .InSequence(PISequence); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + +TEST_F(LoopCallbacksTest, InstrumentedSkippedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation run here can safely be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("foo"); + CallbacksHandle.ignoreNonMockPassInstrumentation("loop"); + + // Skip the pass by returning false. + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("loop"))) + .WillOnce(Return(false)); + + EXPECT_CALL(AnalysisHandle, run(HasName("loop"), _, _)).Times(0); + EXPECT_CALL(PassHandle, run(HasName("loop"), _, _, _)).Times(0); + + // As the pass is skipped there is no afterPass as well. + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + .Times(0); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + TEST_F(CGSCCCallbacksTest, Passes) { EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) @@ -427,6 +649,57 @@ TEST_F(CGSCCCallbacksTest, Passes) { PM.run(*M, AM); } +TEST_F(CGSCCCallbacksTest, InstrumentedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation not specifically mentioned below can be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)"); + + EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)); + EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)) + .WillOnce(WithArgs<0, 1, 2>(Invoke(getAnalysisResult))); + + // PassInstrumentation calls should happen in-sequence, in the same order + // as passes/analyses are scheduled. + ::testing::Sequence PISequence; + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) + .InSequence(PISequence); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) + .InSequence(PISequence); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + +TEST_F(CGSCCCallbacksTest, InstrumentedSkippedPasses) { + CallbacksHandle.registerPassInstrumentation(); + // Non-mock instrumentation run here can safely be ignored. + CallbacksHandle.ignoreNonMockPassInstrumentation("<string>"); + CallbacksHandle.ignoreNonMockPassInstrumentation("(foo)"); + + // Skip the pass by returning false. + EXPECT_CALL(CallbacksHandle, + runBeforePass(HasNameRegex("MockPassHandle"), HasName("(foo)"))) + .WillOnce(Return(false)); + + // neither Analysis nor Pass are called. + EXPECT_CALL(AnalysisHandle, run(HasName("(foo)"), _, _)).Times(0); + EXPECT_CALL(PassHandle, run(HasName("(foo)"), _, _, _)).Times(0); + + // As the pass is skipped there is no afterPass as well. + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("MockPassHandle"), _)) + .Times(0); + + StringRef PipelineText = "test-transform"; + ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true)) + << "Pipeline was: " << PipelineText; + PM.run(*M, AM); +} + /// Test parsing of the names of analysis utilities for our mock analysis /// for all IRUnits. /// diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp index 7709453..13b87f1 100644 --- a/llvm/unittests/IR/PassManagerTest.cpp +++ b/llvm/unittests/IR/PassManagerTest.cpp @@ -406,6 +406,9 @@ TEST_F(PassManagerTest, Basic) { MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + ModulePassManager MPM; // Count the runs over a Function. @@ -556,6 +559,8 @@ struct CustomizedPass : PassInfoMixin<CustomizedPass> { TEST_F(PassManagerTest, CustomizedPassManagerArgs) { CustomizedAnalysisManager AM; AM.registerPass([&] { return CustomizedAnalysis(); }); + PassInstrumentationCallbacks PIC; + AM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); CustomizedPassManager PM; @@ -688,6 +693,10 @@ TEST_F(PassManagerTest, IndirectAnalysisInvalidation) { MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + PassInstrumentationCallbacks PIC; + MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); }); + int InstrCount = 0, FunctionCount = 0; ModulePassManager MPM(/*DebugLogging*/ true); FunctionPassManager FPM(/*DebugLogging*/ true); diff --git a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp index 57fb57e..9f0b6f0 100644 --- a/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp +++ b/llvm/unittests/Transforms/Scalar/LoopPassManagerTest.cpp @@ -308,6 +308,11 @@ public: FAM.registerPass([&] { return TargetLibraryAnalysis(); }); FAM.registerPass([&] { return TargetIRAnalysis(); }); + // Register required pass instrumentation analysis. + LAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + // Cross-register proxies. LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); }); FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); }); |