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

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


Reverted thusly:

echristo at athyra ~/s/llvm> git svn dcommit
Committing to https://llvm.org/svn/llvm-project/llvm/trunk ...
D include/llvm/IR/PassInstrumentation.h
D lib/IR/PassInstrumentation.cpp
M include/llvm/Analysis/CGSCCPassManager.h
M include/llvm/IR/PassManager.h
M include/llvm/Passes/PassBuilder.h
M include/llvm/Transforms/Scalar/LoopPassManager.h
M lib/Analysis/CGSCCPassManager.cpp
M lib/FuzzMutate/IRMutator.cpp
M lib/IR/CMakeLists.txt
M lib/Passes/PassRegistry.def
M lib/Transforms/Scalar/LoopPassManager.cpp
M test/Other/loop-pm-invalidation.ll
M test/Other/new-pass-manager.ll
M test/Other/new-pm-defaults.ll
M test/Other/new-pm-lto-defaults.ll
M test/Other/new-pm-thinlto-defaults.ll
M test/Transforms/Inline/cgscc-incremental-invalidate.ll
M test/Transforms/LoopRotate/pr35210.ll
M unittests/Analysis/CGSCCPassManagerTest.cpp
M unittests/IR/PassBuilderCallbacksTest.cpp
M unittests/IR/PassManagerTest.cpp
M unittests/Transforms/Scalar/LoopPassManagerTest.cpp
Committed r342616

On Wed, Sep 19, 2018 at 10:08 PM Eric Christopher <echristo at gmail.com>
wrote:

> 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/3d5c9b7d/attachment-0001.html>


More information about the llvm-commits mailing list