[llvm] r342597 - [New PM] Introducing PassInstrumentation framework

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 19 22:08:44 PDT 2018


So it looks like this is causing issues in the asan buildbot:

http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/23878/steps/check-llvm%20asan/logs/stdio

(hack wasn't quite enough I'm guessing :)

I'm going to go ahead and revert and will reply with the reverted revision.
Sorry for the inconvenience!

Thanks!

-eric

On Wed, Sep 19, 2018 at 3:44 PM Fedor Sergeev via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: fedor.sergeev
> Date: Wed Sep 19 15:42:57 2018
> New Revision: 342597
>
> URL: http://llvm.org/viewvc/llvm-project?rev=342597&view=rev
> Log:
> [New PM] Introducing PassInstrumentation framework
>
> Pass Execution Instrumentation interface enables customizable
> instrumentation
> of pass execution, as per "RFC: Pass Execution Instrumentation interface"
> posted 06/07/2018 on llvm-dev@
>
> The intent is to provide a common machinery to implement all
> the pass-execution-debugging features like print-before/after,
> opt-bisect, time-passes etc.
>
> Here we get a basic implementation consisting of:
> * PassInstrumentationCallbacks class that handles registration of callbacks
>   and access to them.
>
> * PassInstrumentation class that handles instrumentation-point interfaces
>   that call into PassInstrumentationCallbacks.
>
> * Callbacks accept StringRef which is just a name of the Pass right now.
>   There were some ideas to pass an opaque wrapper for the pointer to pass
> instance,
>   however it appears that pointer does not actually identify the instance
>   (adaptors and managers might have the same address with the pass they
> govern).
>   Hence it was decided to go simple for now and then later decide on what
> the proper
>   mental model of identifying a "pass in a phase of pipeline" is.
>
> * Callbacks accept llvm::Any serving as a wrapper for const IRUnit*, to
> remove direct dependencies
>   on different IRUnits (e.g. Analyses).
>
> * PassInstrumentationAnalysis analysis is explicitly requested from
> PassManager through
>   usual AnalysisManager::getResult. All pass managers were updated to run
> that
>   to get PassInstrumentation object for instrumentation calls.
>
> * Using tuples/index_sequence getAnalysisResult helper to extract generic
> AnalysisManager's extra
>   args out of a generic PassManager's extra args. This is the only way I
> was able to explicitly
>   run getResult for PassInstrumentationAnalysis out of a generic code like
> PassManager::run or
>   RepeatedPass::run.
>   TODO: Upon lengthy discussions we agreed to accept this as an initial
> implementation
>   and then get rid of getAnalysisResult by improving RepeatedPass
> implementation.
>
> * PassBuilder takes PassInstrumentationCallbacks object to pass it further
> into
>   PassInstrumentationAnalysis. Callbacks registration should be performed
> directly
>   through PassInstrumentationCallbacks.
>
> * new-pm tests updated to account for PassInstrumentationAnalysis being run
>
> * Added PassInstrumentation tests to PassBuilderCallbacks unit tests.
>   Other unit tests updated with registration of the now-required
> PassInstrumentationAnalysis.
>
> Reviewers: chandlerc, philip.pfaffe
> Differential Revision: https://reviews.llvm.org/D47858
>
> Added:
>     llvm/trunk/include/llvm/IR/PassInstrumentation.h
>     llvm/trunk/lib/IR/PassInstrumentation.cpp
> Modified:
>     llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
>     llvm/trunk/include/llvm/IR/PassManager.h
>     llvm/trunk/include/llvm/Passes/PassBuilder.h
>     llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h
>     llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
>     llvm/trunk/lib/FuzzMutate/IRMutator.cpp
>     llvm/trunk/lib/IR/CMakeLists.txt
>     llvm/trunk/lib/Passes/PassRegistry.def
>     llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp
>     llvm/trunk/test/Other/loop-pm-invalidation.ll
>     llvm/trunk/test/Other/new-pass-manager.ll
>     llvm/trunk/test/Other/new-pm-defaults.ll
>     llvm/trunk/test/Other/new-pm-lto-defaults.ll
>     llvm/trunk/test/Other/new-pm-thinlto-defaults.ll
>     llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll
>     llvm/trunk/test/Transforms/LoopRotate/pr35210.ll
>     llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp
>     llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
>     llvm/trunk/unittests/IR/PassManagerTest.cpp
>     llvm/trunk/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
>
> Modified: llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h (original)
> +++ llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h Wed Sep 19
> 15:42:57 2018
> @@ -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) {
>
> Added: llvm/trunk/include/llvm/IR/PassInstrumentation.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassInstrumentation.h?rev=342597&view=auto
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/PassInstrumentation.h (added)
> +++ llvm/trunk/include/llvm/IR/PassInstrumentation.h Wed Sep 19 15:42:57
> 2018
> @@ -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
>
> Modified: llvm/trunk/include/llvm/IR/PassManager.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/PassManager.h (original)
> +++ llvm/trunk/include/llvm/IR/PassManager.h Wed Sep 19 15:42:57 2018
> @@ -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
>    }
>  };
>
> +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 = Passes[Idx]->run(IR, AM, ExtraArgs...);
> +      PreservedAnalyses PassPA = P->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<Functi
>  /// 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;
>    }
>
>
> Modified: llvm/trunk/include/llvm/Passes/PassBuilder.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Passes/PassBuilder.h?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Passes/PassBuilder.h (original)
> +++ llvm/trunk/include/llvm/Passes/PassBuilder.h Wed Sep 19 15:42:57 2018
> @@ -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.
>    ///
>
> Modified: llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Scalar/LoopPassManager.h Wed Sep 19
> 15:42:57 2018
> @@ -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.
>
>
> Modified: llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CGSCCPassManager.cpp (original)
> +++ llvm/trunk/lib/Analysis/CGSCCPassManager.cpp Wed Sep 19 15:42:57 2018
> @@ -54,6 +54,11 @@ PassManager<LazyCallGraph::SCC, CGSCCAna
>              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, CGSCCAna
>      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;
>
>
> Modified: llvm/trunk/lib/FuzzMutate/IRMutator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/FuzzMutate/IRMutator.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/FuzzMutate/IRMutator.cpp (original)
> +++ llvm/trunk/lib/FuzzMutate/IRMutator.cpp Wed Sep 19 15:42:57 2018
> @@ -73,6 +73,7 @@ static void eliminateDeadCode(Function &
>    FPM.addPass(DCEPass());
>    FunctionAnalysisManager FAM;
>    FAM.registerPass([&] { return TargetLibraryAnalysis(); });
> +  FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
>    FPM.run(F, FAM);
>  }
>
>
> Modified: llvm/trunk/lib/IR/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/CMakeLists.txt (original)
> +++ llvm/trunk/lib/IR/CMakeLists.txt Wed Sep 19 15:42:57 2018
> @@ -42,6 +42,7 @@ add_llvm_library(LLVMCore
>    Operator.cpp
>    OptBisect.cpp
>    Pass.cpp
> +  PassInstrumentation.cpp
>    PassManager.cpp
>    PassRegistry.cpp
>    PassTimingInfo.cpp
>
> Added: llvm/trunk/lib/IR/PassInstrumentation.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassInstrumentation.cpp?rev=342597&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/IR/PassInstrumentation.cpp (added)
> +++ llvm/trunk/lib/IR/PassInstrumentation.cpp Wed Sep 19 15:42:57 2018
> @@ -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
>
> Modified: llvm/trunk/lib/Passes/PassRegistry.def
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
> +++ llvm/trunk/lib/Passes/PassRegistry.def Wed Sep 19 15:42:57 2018
> @@ -26,6 +26,7 @@ MODULE_ANALYSIS("no-op-module", NoOpModu
>  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", Targe
>  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", CFGOnlyVi
>  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
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopPassManager.cpp Wed Sep 19
> 15:42:57 2018
> @@ -30,12 +30,22 @@ PassManager<Loop, LoopAnalysisManager, L
>    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));
>
> Modified: llvm/trunk/test/Other/loop-pm-invalidation.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/loop-pm-invalidation.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/loop-pm-invalidation.ll (original)
> +++ llvm/trunk/test/Other/loop-pm-invalidation.ll Wed Sep 19 15:42:57 2018
> @@ -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:
>
> 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=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/new-pass-manager.ll (original)
> +++ llvm/trunk/test/Other/new-pass-manager.ll Wed Sep 19 15:42:57 2018
> @@ -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
>
> Modified: llvm/trunk/test/Other/new-pm-defaults.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-defaults.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/new-pm-defaults.ll (original)
> +++ llvm/trunk/test/Other/new-pm-defaults.ll Wed Sep 19 15:42:57 2018
> @@ -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
>
> Modified: llvm/trunk/test/Other/new-pm-lto-defaults.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-lto-defaults.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/new-pm-lto-defaults.ll (original)
> +++ llvm/trunk/test/Other/new-pm-lto-defaults.ll Wed Sep 19 15:42:57 2018
> @@ -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
>
> Modified: llvm/trunk/test/Other/new-pm-thinlto-defaults.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-thinlto-defaults.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Other/new-pm-thinlto-defaults.ll (original)
> +++ llvm/trunk/test/Other/new-pm-thinlto-defaults.ll Wed Sep 19 15:42:57
> 2018
> @@ -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
>
> Modified: llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll
> (original)
> +++ llvm/trunk/test/Transforms/Inline/cgscc-incremental-invalidate.ll Wed
> Sep 19 15:42:57 2018
> @@ -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.
>
> Modified: llvm/trunk/test/Transforms/LoopRotate/pr35210.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopRotate/pr35210.ll?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/LoopRotate/pr35210.ll (original)
> +++ llvm/trunk/test/Transforms/LoopRotate/pr35210.ll Wed Sep 19 15:42:57
> 2018
> @@ -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
>
> Modified: llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp (original)
> +++ llvm/trunk/unittests/Analysis/CGSCCPassManagerTest.cpp Wed Sep 19
> 15:42:57 2018
> @@ -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);
> });
>
> Modified: llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp (original)
> +++ llvm/trunk/unittests/IR/PassBuilderCallbacksTest.cpp Wed Sep 19
> 15:42:57 2018
> @@ -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::ost
>  }
>
>  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(L
>    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> StringRef getName(const IRUnitT &IR) {
> +  return IR.getName();
> +}
> +
> +template <> StringRef getName(const StringRef &name) { return name; }
> +
> +template <> StringRef getName(const llvm::Any &WrappedIR) {
> +  if (any_isa<const Module *>(WrappedIR))
> +    return any_cast<const Module *>(WrappedIR)->getName();
> +  if (any_isa<const Function *>(WrappedIR))
> +    return any_cast<const Function *>(WrappedIR)->getName();
> +  if (any_isa<const Loop *>(WrappedIR))
> +    return any_cast<const Loop *>(WrappedIR)->getName();
> +  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)"), _, _, _))
> @@ -423,6 +645,57 @@ TEST_F(CGSCCCallbacksTest, Passes) {
>
>    StringRef PipelineText = "test-transform";
>    ASSERT_TRUE(PB.parsePassPipeline(PM, PipelineText, true))
> +      << "Pipeline was: " << PipelineText;
> +  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);
>  }
>
> Modified: llvm/trunk/unittests/IR/PassManagerTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/IR/PassManagerTest.cpp (original)
> +++ llvm/trunk/unittests/IR/PassManagerTest.cpp Wed Sep 19 15:42:57 2018
> @@ -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<Cu
>  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, IndirectAnalysis
>    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);
>
> Modified: llvm/trunk/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Transforms/Scalar/LoopPassManagerTest.cpp?rev=342597&r1=342596&r2=342597&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
> (original)
> +++ llvm/trunk/unittests/Transforms/Scalar/LoopPassManagerTest.cpp Wed Sep
> 19 15:42:57 2018
> @@ -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);
> });
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180919/984bce38/attachment-0001.html>


More information about the llvm-commits mailing list