Skip to content
PassManager.cpp 62.9 KiB
Newer Older
//===- PassManager.cpp - LLVM Pass Infrastructure Implementation ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
Dan Gohman's avatar
Dan Gohman committed
// This file implements the LLVM Pass Manager infrastructure.
//
//===----------------------------------------------------------------------===//


#include "llvm/PassManagers.h"
David Greene's avatar
 
David Greene committed
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CommandLine.h"
David Greene's avatar
David Greene committed
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
Devang Patel's avatar
Devang Patel committed
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
David Greene's avatar
 
David Greene committed
#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
Jeff Cohen's avatar
Jeff Cohen committed
#include <algorithm>
#include <map>
using namespace llvm;
// See PassManagers.h for Pass Manager infrastructure overview.
namespace llvm {

//===----------------------------------------------------------------------===//
// Pass debugging information.  Often it is useful to find out what pass is
// running when a crash occurs in a utility.  When this library is compiled with
// debugging on, a command line option (--debug-pass) is enabled that causes the
// pass name to be printed before it executes.
//

// Different debug levels that can be enabled...
enum PassDebugLevel {
  Disabled, Arguments, Structure, Executions, Details
bool TimePassesIsEnabled = false;

/// Encapsulate PassManager debug options. These are convenient options that
/// should be available to any LLVM-based tool. They exist purely as
/// command-line debug options, therefore don't need to be local to an LLVM
/// context or captured by a formal API. In all respects they are handled like
/// global variables, but being defined in the LLVMCore library cannot have
/// static initializers and must be destroyed only at llvm_shutdown.
struct PassDebugOpts {
  cl::opt<enum PassDebugLevel> PassDebugging;

  typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser>
  PassOptionList;

  // Print IR out before/after specified passes.
  PassOptionList PrintBefore;

  PassOptionList PrintAfter;

  cl::opt<bool> PrintBeforeAll;
  cl::opt<bool> PrintAfterAll;

  cl::opt<bool,true> EnableTiming;

  PassDebugOpts():
    PassDebugging("debug-pass", cl::Hidden,
                  cl::desc("Print PassManager debugging information"),
                  cl::values(
                    clEnumVal(Disabled , "disable debug output"),
                    clEnumVal(Arguments,
                              "print pass arguments to pass to 'opt'"),
                    clEnumVal(Structure, "print pass structure before run()"),
                    clEnumVal(Executions,
                              "print pass name before it is executed"),
                    clEnumVal(Details,
                              "print pass details when it is executed"),
                    clEnumValEnd)),
    PrintBefore("print-before",
                llvm::cl::desc("Print IR before specified passes"),
                cl::Hidden),
    PrintAfter("print-after",
               llvm::cl::desc("Print IR after specified passes"),
               cl::Hidden),
    PrintBeforeAll("print-before-all",
                   llvm::cl::desc("Print IR before each pass"),
                   cl::init(false)),
    PrintAfterAll("print-after-all",
                  llvm::cl::desc("Print IR after each pass"),
                  cl::init(false)),
    EnableTiming("time-passes", cl::location(TimePassesIsEnabled),
                 cl::desc(
                   "Time each pass, printing elapsed time for each on exit"))
  {}

  /// This is a helper to determine whether to print IR before or
  /// after a pass.
  bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI,
                                    PassOptionList &PassesToPrint) {
    for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) {
      const llvm::PassInfo *PassInf = PassesToPrint[i];
      if (PassInf)
        if (PassInf->getPassArgument() == PI->getPassArgument()) {
          return true;
        }
    }
    return false;
David Greene's avatar
 
David Greene committed
  }
Dan Gohman's avatar
Dan Gohman committed

  /// This is a utility to check whether a pass should have IR dumped
  /// before it.
  bool ShouldPrintBeforePass(const PassInfo *PI) {
    return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore);
  }

  /// This is a utility to check whether a pass should have IR dumped
  /// after it.
  bool ShouldPrintAfterPass(const PassInfo *PI) {
    return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
  }
};
David Greene's avatar
 
David Greene committed

static ManagedStatic<PassDebugOpts> GlobalPassDebugOpts;

/// This is called by tools to force registration of debugging options and
/// ensure they appear in the tool's -help usage.
void initializePassManager() {
  // Force instantiation of PassDebugOpts.
  *GlobalPassDebugOpts;
David Greene's avatar
 
David Greene committed
}

/// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions
/// or higher is specified.
bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
  return GlobalPassDebugOpts->PassDebugging >= Executions;
void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
  if (V == 0 && M == 0)
    OS << "Releasing pass '";
  else
    OS << "Running pass '";
Dan Gohman's avatar
Dan Gohman committed

Dan Gohman's avatar
Dan Gohman committed

  if (M) {
    OS << " on module '" << M->getModuleIdentifier() << "'.\n";
    return;
  }
  if (V == 0) {
    OS << '\n';
    return;
  }

    OS << "value";

  OS << " '";
  WriteAsOperand(OS, V, /*PrintTy=*/false, M);
  OS << "'\n";
Devang Patel's avatar
Devang Patel committed
//===----------------------------------------------------------------------===//
// BBPassManager
Devang Patel's avatar
Devang Patel committed
//
/// BBPassManager manages BasicBlockPass. It batches all the
/// pass together and sequence them to process one basic block before
/// processing next basic block.
class BBPassManager : public PMDataManager, public FunctionPass {
Devang Patel's avatar
Devang Patel committed
  static char ID;
  explicit BBPassManager()
    : PMDataManager(), FunctionPass(ID) {}

  /// Execute all of the passes scheduled for execution.  Keep track of
  /// whether any of the passes modifies the function, and if so, return true.
  bool runOnFunction(Function &F);

  /// Pass Manager itself does not invalidate any analysis info.
  void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.setPreservesAll();
  }

  bool doInitialization(Module &M);
  bool doInitialization(Function &F);
  bool doFinalization(Module &M);
  bool doFinalization(Function &F);

  virtual PMDataManager *getAsPMDataManager() { return this; }
  virtual Pass *getAsPass() { return this; }

Devang Patel's avatar
Devang Patel committed
  virtual const char *getPassName() const {
Dan Gohman's avatar
Dan Gohman committed
    return "BasicBlock Pass Manager";
Devang Patel's avatar
Devang Patel committed
  }

  // Print passes managed by this manager
  void dumpPassStructure(unsigned Offset) {
    llvm::dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
    for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
      BasicBlockPass *BP = getContainedPass(Index);
      BP->dumpPassStructure(Offset + 1);

  BasicBlockPass *getContainedPass(unsigned N) {
    assert(N < PassVector.size() && "Pass number out of range!");
    BasicBlockPass *BP = static_cast<BasicBlockPass *>(PassVector[N]);
    return BP;
  }
Dan Gohman's avatar
Dan Gohman committed
  virtual PassManagerType getPassManagerType() const {
    return PMT_BasicBlockPassManager;
Devang Patel's avatar
Devang Patel committed
char BBPassManager::ID = 0;

//===----------------------------------------------------------------------===//
// FunctionPassManagerImpl
//
/// FunctionPassManagerImpl manages FPPassManagers
class FunctionPassManagerImpl : public Pass,
                                public PMDataManager,
                                public PMTopLevelManager {
Devang Patel's avatar
Devang Patel committed
  static char ID;
  explicit FunctionPassManagerImpl() :
    Pass(PT_PassManager, ID), PMDataManager(),
    PMTopLevelManager(new FPPassManager()), wasRun(false) {}

  /// add - Add a pass to the queue of passes to run.  This passes ownership of
  /// the Pass to the PassManager.  When the PassManager is destroyed, the pass
  /// will be destroyed as well, so there is no need to delete the pass.  This
  /// implies that all passes MUST be allocated with 'new'.
  void add(Pass *P) {
    schedulePass(P);
  }
Dan Gohman's avatar
Dan Gohman committed

  /// createPrinterPass - Get a function printer pass.
David Greene's avatar
 
David Greene committed
  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
    return createPrintFunctionPass(Banner, &O);
  }

  // Prepare for running an on the fly pass, freeing memory if needed
  // from a previous run.
  void releaseMemoryOnTheFly();

  /// run - Execute all of the passes scheduled for execution.  Keep track of
  /// whether any of the passes modifies the module, and if so, return true.
  bool run(Function &F);

  /// doInitialization - Run all of the initializers for the function passes.
  ///
  bool doInitialization(Module &M);
Dan Gohman's avatar
Dan Gohman committed

  /// doFinalization - Run all of the finalizers for the function passes.
  ///
  bool doFinalization(Module &M);

Dan Gohman's avatar
Dan Gohman committed

  virtual PMDataManager *getAsPMDataManager() { return this; }
  virtual Pass *getAsPass() { return this; }
  virtual PassManagerType getTopLevelPassManagerType() {
    return PMT_FunctionPassManager;
  }
  /// Pass Manager itself does not invalidate any analysis info.
  void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.setPreservesAll();
  }

  FPPassManager *getContainedManager(unsigned N) {
    assert(N < PassManagers.size() && "Pass number out of range!");
    FPPassManager *FP = static_cast<FPPassManager *>(PassManagers[N]);
    return FP;
  }
Devang Patel's avatar
Devang Patel committed
char FunctionPassManagerImpl::ID = 0;
Dan Gohman's avatar
Dan Gohman committed

Devang Patel's avatar
Devang Patel committed
//===----------------------------------------------------------------------===//
// MPPassManager
Devang Patel's avatar
Devang Patel committed
//
/// MPPassManager manages ModulePasses and function pass managers.
Dan Gohman's avatar
Dan Gohman committed
/// It batches all Module passes and function pass managers together and
/// sequences them to process one module.
class MPPassManager : public Pass, public PMDataManager {
Devang Patel's avatar
Devang Patel committed
  static char ID;
  explicit MPPassManager() :
    Pass(PT_PassManager, ID), PMDataManager() { }

  // Delete on the fly managers.
  virtual ~MPPassManager() {
Dan Gohman's avatar
Dan Gohman committed
    for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
           I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
         I != E; ++I) {
      FunctionPassManagerImpl *FPP = I->second;
Dan Gohman's avatar
Dan Gohman committed
  /// createPrinterPass - Get a module printer pass.
David Greene's avatar
 
David Greene committed
  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
    return createPrintModulePass(&O, false, Banner);
  }

  /// run - Execute all of the passes scheduled for execution.  Keep track of
  /// whether any of the passes modifies the module, and if so, return true.
  bool runOnModule(Module &M);
  using llvm::Pass::doInitialization;
  using llvm::Pass::doFinalization;

  /// doInitialization - Run all of the initializers for the module passes.
  ///

  /// doFinalization - Run all of the finalizers for the module passes.
  ///
  /// Pass Manager itself does not invalidate any analysis info.
  void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.setPreservesAll();
  }

  /// Add RequiredPass into list of lower level passes required by pass P.
  /// RequiredPass is run on the fly by Pass Manager when P requests it
  /// through getAnalysis interface.
  virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass);

Dan Gohman's avatar
Dan Gohman committed
  /// Return function pass corresponding to PassInfo PI, that is
  /// required by module pass MP. Instantiate analysis pass, by using
  /// its runOnFunction() for function F.
  virtual Pass* getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F);
Devang Patel's avatar
Devang Patel committed
  virtual const char *getPassName() const {
    return "Module Pass Manager";
  }

  virtual PMDataManager *getAsPMDataManager() { return this; }
  virtual Pass *getAsPass() { return this; }

  // Print passes managed by this manager
  void dumpPassStructure(unsigned Offset) {
    llvm::dbgs().indent(Offset*2) << "ModulePass Manager\n";
    for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
      ModulePass *MP = getContainedPass(Index);
      MP->dumpPassStructure(Offset + 1);
      std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
        OnTheFlyManagers.find(MP);
      if (I != OnTheFlyManagers.end())
        I->second->dumpPassStructure(Offset + 2);
  ModulePass *getContainedPass(unsigned N) {
    assert(N < PassVector.size() && "Pass number out of range!");
    return static_cast<ModulePass *>(PassVector[N]);
Dan Gohman's avatar
Dan Gohman committed
  virtual PassManagerType getPassManagerType() const {
    return PMT_ModulePassManager;

 private:
  /// Collection of on the fly FPPassManagers. These managers manage
  /// function passes that are required by module passes.
  std::map<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
Devang Patel's avatar
Devang Patel committed
char MPPassManager::ID = 0;
Devang Patel's avatar
Devang Patel committed
//===----------------------------------------------------------------------===//
// PassManagerImpl
Devang Patel's avatar
Devang Patel committed
//
/// PassManagerImpl manages MPPassManagers
class PassManagerImpl : public Pass,
                        public PMDataManager,
                        public PMTopLevelManager {
Devang Patel's avatar
Devang Patel committed
  static char ID;
  explicit PassManagerImpl() :
    Pass(PT_PassManager, ID), PMDataManager(),
                              PMTopLevelManager(new MPPassManager()) {}
  /// add - Add a pass to the queue of passes to run.  This passes ownership of
  /// the Pass to the PassManager.  When the PassManager is destroyed, the pass
  /// will be destroyed as well, so there is no need to delete the pass.  This
  /// implies that all passes MUST be allocated with 'new'.
    schedulePass(P);
Dan Gohman's avatar
Dan Gohman committed

  /// createPrinterPass - Get a module printer pass.
David Greene's avatar
 
David Greene committed
  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
    return createPrintModulePass(&O, false, Banner);
  }

  /// run - Execute all of the passes scheduled for execution.  Keep track of
  /// whether any of the passes modifies the module, and if so, return true.
  bool run(Module &M);

  using llvm::Pass::doInitialization;
  using llvm::Pass::doFinalization;

  /// doInitialization - Run all of the initializers for the module passes.
  ///

  /// doFinalization - Run all of the finalizers for the module passes.
  ///
  /// Pass Manager itself does not invalidate any analysis info.
  void getAnalysisUsage(AnalysisUsage &Info) const {
    Info.setPreservesAll();
  }

  virtual PMDataManager *getAsPMDataManager() { return this; }
  virtual Pass *getAsPass() { return this; }
  virtual PassManagerType getTopLevelPassManagerType() {
    return PMT_ModulePassManager;
  }
  MPPassManager *getContainedManager(unsigned N) {
    assert(N < PassManagers.size() && "Pass number out of range!");
    MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]);
    return MP;
  }
Devang Patel's avatar
Devang Patel committed
char PassManagerImpl::ID = 0;
//===----------------------------------------------------------------------===//
/// TimingInfo Class - This class is used to calculate information about the
/// amount of time each pass takes to execute.  This only happens when
/// -time-passes is enabled on the command line.
///
static ManagedStatic<sys::SmartMutex<true> > TimingInfoMutex;
  TimerGroup TG;
public:
  // Use 'create' member to get this.
  TimingInfo() : TG("... Pass execution timing report ...") {}
Dan Gohman's avatar
Dan Gohman committed

  // TimingDtor - Print out information about timing information
  ~TimingInfo() {
    // Delete all of the timers, which accumulate their info into the
    // TimerGroup.
    for (DenseMap<Pass*, Timer*>::iterator I = TimingData.begin(),
         E = TimingData.end(); I != E; ++I)
      delete I->second;
    // TimerGroup is deleted next, printing the report.
  }

  // createTheTimeInfo - This method either initializes the TheTimeInfo pointer
  // to a non null value (if the -time-passes option is enabled) or it leaves it
  // null.  It may be called multiple times.
  static void createTheTimeInfo();

  /// getPassTimer - Return the timer for the specified pass if it exists.
  Timer *getPassTimer(Pass *P) {
Dan Gohman's avatar
Dan Gohman committed
    if (P->getAsPMDataManager())
    sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
    if (T == 0)
      T = new Timer(P->getPassName(), TG);
//===----------------------------------------------------------------------===//
// PMTopLevelManager implementation

Devang Patel's avatar
Devang Patel committed
/// Initialize top level manager. Create first pass manager.
PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) {
  PMDM->setTopLevelManager(this);
  addPassManager(PMDM);
  activeStack.push(PMDM);
/// Set pass P as the last user of the given analysis passes.
Dan Gohman's avatar
Dan Gohman committed
void
PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) {
  unsigned PDepth = 0;
  if (P->getResolver())
    PDepth = P->getResolver()->getPMDataManager().getDepth();

Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<Pass *>::const_iterator I = AnalysisPasses.begin(),
         E = AnalysisPasses.end(); I != E; ++I) {
    Pass *AP = *I;
    LastUser[AP] = P;
Dan Gohman's avatar
Dan Gohman committed

Devang Patel's avatar
Devang Patel committed
    if (P == AP)
      continue;

    // Update the last users of passes that are required transitive by AP.
    AnalysisUsage *AnUsage = findAnalysisUsage(AP);
    const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
    SmallVector<Pass *, 12> LastUses;
    SmallVector<Pass *, 12> LastPMUses;
    for (AnalysisUsage::VectorType::const_iterator I = IDs.begin(),
         E = IDs.end(); I != E; ++I) {
      Pass *AnalysisPass = findAnalysisPass(*I);
      assert(AnalysisPass && "Expected analysis pass to exist.");
      AnalysisResolver *AR = AnalysisPass->getResolver();
      assert(AR && "Expected analysis resolver to exist.");
      unsigned APDepth = AR->getPMDataManager().getDepth();

      if (PDepth == APDepth)
        LastUses.push_back(AnalysisPass);
      else if (PDepth > APDepth)
        LastPMUses.push_back(AnalysisPass);
    }

    setLastUser(LastUses, P);

    // If this pass has a corresponding pass manager, push higher level
    // analysis to this pass manager.
    if (P->getResolver())
      setLastUser(LastPMUses, P->getResolver()->getPMDataManager().getAsPass());


    // If AP is the last user of other passes then make P last user of
    // such passes.
    for (DenseMap<Pass *, Pass *>::iterator LUI = LastUser.begin(),
           LUE = LastUser.end(); LUI != LUE; ++LUI) {
      if (LUI->second == AP)
        // DenseMap iterator is not invalidated here because
        // this is just updating existing entries.
        LastUser[LUI->first] = P;
    }
  }
}

/// Collect passes whose last user is P
void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
Dan Gohman's avatar
Dan Gohman committed
  DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator DMI =
    InversedLastUser.find(P);
  if (DMI == InversedLastUser.end())
    return;

  SmallPtrSet<Pass *, 8> &LU = DMI->second;
  for (SmallPtrSet<Pass *, 8>::iterator I = LU.begin(),
         E = LU.end(); I != E; ++I) {
    LastUses.push_back(*I);
  }

AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
  AnalysisUsage *AnUsage = NULL;
  DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.find(P);
Dan Gohman's avatar
Dan Gohman committed
  if (DMI != AnUsageMap.end())
    AnUsage = DMI->second;
  else {
    AnUsage = new AnalysisUsage();
    P->getAnalysisUsage(*AnUsage);
    AnUsageMap[P] = AnUsage;
  }
  return AnUsage;
}

/// Schedule pass P for execution. Make sure that passes required by
/// P are run before P is run. Update analysis info maintained by
/// the manager. Remove dead passes. This is a recursive function.
void PMTopLevelManager::schedulePass(Pass *P) {

Devang Patel's avatar
Devang Patel committed
  // TODO : Allocate function manager for this pass, other wise required set
  // may be inserted into previous function manager
  // Give pass a chance to prepare the stage.
  P->preparePassManager(activeStack);

Devang Patel's avatar
Devang Patel committed
  // If P is an analysis pass and it is available then do not
  // generate the analysis again. Stale analysis info should not be
  // available at this point.
  const PassInfo *PI =
    PassRegistry::getPassRegistry()->getPassInfo(P->getPassID());
  if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) {
  AnalysisUsage *AnUsage = findAnalysisUsage(P);

  bool checkAnalysis = true;
  while (checkAnalysis) {
    checkAnalysis = false;
Dan Gohman's avatar
Dan Gohman committed

    const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
    for (AnalysisUsage::VectorType::const_iterator I = RequiredSet.begin(),
           E = RequiredSet.end(); I != E; ++I) {
Dan Gohman's avatar
Dan Gohman committed

      Pass *AnalysisPass = findAnalysisPass(*I);
      if (!AnalysisPass) {
        const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);

        if (PI == NULL) {
          // Pass P is not in the global PassRegistry
          dbgs() << "Pass '"  << P->getPassName() << "' is not initialized." << "\n";
          dbgs() << "Verify if there is a pass dependency cycle." << "\n";
          dbgs() << "Required Passes:" << "\n";
          for (AnalysisUsage::VectorType::const_iterator I2 = RequiredSet.begin(),
                 E = RequiredSet.end(); I2 != E && I2 != I; ++I2) {
            Pass *AnalysisPass2 = findAnalysisPass(*I2);
            if (AnalysisPass2) {
              dbgs() << "\t" << AnalysisPass2->getPassName() << "\n";
              dbgs() << "\t"   << "Error: Required pass not found! Possible causes:"  << "\n";
              dbgs() << "\t\t" << "- Pass misconfiguration (e.g.: missing macros)"    << "\n";
              dbgs() << "\t\t" << "- Corruption of the global PassRegistry"           << "\n";
            }
          }
        }

        assert(PI && "Expected required passes to be initialized");
        AnalysisPass = PI->createPass();
        if (P->getPotentialPassManagerType () ==
            AnalysisPass->getPotentialPassManagerType())
          // Schedule analysis pass that is managed by the same pass manager.
          schedulePass(AnalysisPass);
        else if (P->getPotentialPassManagerType () >
                 AnalysisPass->getPotentialPassManagerType()) {
          // Schedule analysis pass that is managed by a new manager.
          schedulePass(AnalysisPass);
          // Recheck analysis passes to ensure that required analyses that
          // are already checked are still available.
          checkAnalysis = true;
Dan Gohman's avatar
Dan Gohman committed
          // Do not schedule this analysis. Lower level analsyis
          // passes are run on the fly.
          delete AnalysisPass;
      }
    }
  }

  // Now all required passes are available.
  if (ImmutablePass *IP = P->getAsImmutablePass()) {
    // P is a immutable pass and it will be managed by this
    // top level manager. Set up analysis resolver to connect them.
    PMDataManager *DM = getAsPMDataManager();
    AnalysisResolver *AR = new AnalysisResolver(*DM);
    P->setResolver(AR);
    DM->initializeAnalysisImpl(P);
    addImmutablePass(IP);
    DM->recordAvailableAnalysis(IP);
    return;
  }

  if (PI && !PI->isAnalysis() &&
      GlobalPassDebugOpts->ShouldPrintBeforePass(PI)) {
    Pass *PP = P->createPrinterPass(
      dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***");
    PP->assignPassManager(activeStack, getTopLevelPassManagerType());
  }

  // Add the requested pass to the best available pass manager.
  P->assignPassManager(activeStack, getTopLevelPassManagerType());

  if (PI && !PI->isAnalysis() &&
      GlobalPassDebugOpts->ShouldPrintAfterPass(PI)) {
    Pass *PP = P->createPrinterPass(
      dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***");
    PP->assignPassManager(activeStack, getTopLevelPassManagerType());
  }
}

/// Find the pass that implements Analysis AID. Search immutable
/// passes and all pass managers. If desired pass is not found
/// then return NULL.
Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) {

Devang Patel's avatar
Devang Patel committed
  // Check pass managers
  for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
         E = PassManagers.end(); I != E; ++I)
    if (Pass *P = (*I)->findAnalysisPass(AID, false))
      return P;
Devang Patel's avatar
Devang Patel committed

  // Check other pass managers
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<PMDataManager *>::iterator
         I = IndirectPassManagers.begin(),
         E = IndirectPassManagers.end(); I != E; ++I)
    if (Pass *P = (*I)->findAnalysisPass(AID, false))
      return P;

  // Check the immutable passes. Iterate in reverse order so that we find
  // the most recently registered passes first.
  for (SmallVectorImpl<ImmutablePass *>::reverse_iterator I =
       ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; ++I) {
    AnalysisID PI = (*I)->getPassID();
    if (PI == AID)

    // If Pass not found then check the interfaces implemented by Immutable Pass
    const PassInfo *PassInf =
      PassRegistry::getPassRegistry()->getPassInfo(PI);
    assert(PassInf && "Expected all immutable passes to be initialized");
    const std::vector<const PassInfo*> &ImmPI =
      PassInf->getInterfacesImplemented();
    for (std::vector<const PassInfo*>::const_iterator II = ImmPI.begin(),
         EE = ImmPI.end(); II != EE; ++II) {
      if ((*II)->getTypeInfo() == AID)
        return *I;
// Print passes managed by this top level manager.
void PMTopLevelManager::dumpPasses() const {
  if (GlobalPassDebugOpts->PassDebugging < Structure)
  // Print out the immutable passes
  for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
    ImmutablePasses[i]->dumpPassStructure(0);
Dan Gohman's avatar
Dan Gohman committed

  // Every class that derives from PMDataManager also derives from Pass
  // (sometimes indirectly), but there's no inheritance relationship
  // between PMDataManager and Pass, so we have to getAsPass to get
  // from a PMDataManager* to a Pass*.
  for (SmallVectorImpl<PMDataManager *>::const_iterator I =
       PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
    (*I)->getAsPass()->dumpPassStructure(1);
void PMTopLevelManager::dumpArguments() const {
  if (GlobalPassDebugOpts->PassDebugging < Arguments)
David Greene's avatar
David Greene committed
  dbgs() << "Pass Arguments: ";
  for (SmallVectorImpl<ImmutablePass *>::const_iterator I =
       ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
    if (const PassInfo *PI =
        PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID())) {
      assert(PI && "Expected all immutable passes to be initialized");
      if (!PI->isAnalysisGroup())
        dbgs() << " -" << PI->getPassArgument();
  for (SmallVectorImpl<PMDataManager *>::const_iterator I =
       PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
David Greene's avatar
David Greene committed
  dbgs() << "\n";
void PMTopLevelManager::initializeAllAnalysisInfo() {
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
         E = PassManagers.end(); I != E; ++I)
    (*I)->initializeAnalysisInfo();
Dan Gohman's avatar
Dan Gohman committed

  // Initailize other pass managers
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<PMDataManager *>::iterator
Dan Gohman's avatar
Dan Gohman committed
       I = IndirectPassManagers.begin(), E = IndirectPassManagers.end();
       I != E; ++I)
  for (DenseMap<Pass *, Pass *>::iterator DMI = LastUser.begin(),
        DME = LastUser.end(); DMI != DME; ++DMI) {
Dan Gohman's avatar
Dan Gohman committed
    DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator InvDMI =
      InversedLastUser.find(DMI->second);
    if (InvDMI != InversedLastUser.end()) {
      SmallPtrSet<Pass *, 8> &L = InvDMI->second;
      L.insert(DMI->first);
    } else {
      SmallPtrSet<Pass *, 8> L; L.insert(DMI->first);
      InversedLastUser[DMI->second] = L;
    }
  }
/// Destructor
PMTopLevelManager::~PMTopLevelManager() {
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
         E = PassManagers.end(); I != E; ++I)
    delete *I;
Dan Gohman's avatar
Dan Gohman committed

Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<ImmutablePass *>::iterator
         I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
    delete *I;

  for (DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.begin(),
         DME = AnUsageMap.end(); DMI != DME; ++DMI)
    delete DMI->second;
//===----------------------------------------------------------------------===//
// PMDataManager implementation
/// Augement AvailableAnalysis by adding analysis made available by pass P.
void PMDataManager::recordAvailableAnalysis(Pass *P) {
  AnalysisID PI = P->getPassID();
Dan Gohman's avatar
Dan Gohman committed

  AvailableAnalysis[PI] = P;
Dan Gohman's avatar
Dan Gohman committed

  assert(!AvailableAnalysis.empty());
Dan Gohman's avatar
Dan Gohman committed
  // This pass is the current implementation of all of the interfaces it
  // implements as well.
  const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI);
  if (PInf == 0) return;
  const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
  for (unsigned i = 0, e = II.size(); i != e; ++i)
    AvailableAnalysis[II[i]->getTypeInfo()] = P;
// Return true if P preserves high level analysis used by other
// passes managed by this manager
bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) {
  AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
  if (AnUsage->getPreservesAll())
    return true;
Dan Gohman's avatar
Dan Gohman committed

  const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<Pass *>::iterator I = HigherLevelAnalysis.begin(),
         E = HigherLevelAnalysis.end(); I  != E; ++I) {
    Pass *P1 = *I;
    if (P1->getAsImmutablePass() == 0 &&
Dan Gohman's avatar
Dan Gohman committed
        std::find(PreservedSet.begin(), PreservedSet.end(),
Dan Gohman's avatar
Dan Gohman committed
                  P1->getPassID()) ==
Devang Patel's avatar
Devang Patel committed
           PreservedSet.end())
      return false;
Dan Gohman's avatar
Dan Gohman committed

/// verifyPreservedAnalysis -- Verify analysis preserved by pass P.
Devang Patel's avatar
Devang Patel committed
void PMDataManager::verifyPreservedAnalysis(Pass *P) {
  // Don't do this unless assertions are enabled.
#ifdef NDEBUG
  return;
#endif
  AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
  const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
  // Verify preserved analysis
  for (AnalysisUsage::VectorType::const_iterator I = PreservedSet.begin(),
Devang Patel's avatar
Devang Patel committed
         E = PreservedSet.end(); I != E; ++I) {
    AnalysisID AID = *I;
    if (Pass *AP = findAnalysisPass(AID, true)) {
      TimeRegion PassTimer(getPassTimer(AP));
Devang Patel's avatar
Devang Patel committed
/// Remove Analysis not preserved by Pass P
Devang Patel's avatar
Devang Patel committed
void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
  AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
  if (AnUsage->getPreservesAll())
  const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
  for (DenseMap<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
         E = AvailableAnalysis.end(); I != E; ) {
    DenseMap<AnalysisID, Pass*>::iterator Info = I++;
    if (Info->second->getAsImmutablePass() == 0 &&
Dan Gohman's avatar
Dan Gohman committed
        std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
Devang Patel's avatar
Devang Patel committed
        PreservedSet.end()) {
      if (GlobalPassDebugOpts->PassDebugging >= Details) {
Devang Patel's avatar
Devang Patel committed
        Pass *S = Info->second;
David Greene's avatar
David Greene committed
        dbgs() << " -- '" <<  P->getPassName() << "' is not preserving '";
        dbgs() << S->getPassName() << "'\n";
Devang Patel's avatar
Devang Patel committed
      }
      AvailableAnalysis.erase(Info);
Devang Patel's avatar
Devang Patel committed
    }
Dan Gohman's avatar
Dan Gohman committed

  // Check inherited analysis also. If P is not preserving analysis
  // provided by parent manager then remove it here.
  for (unsigned Index = 0; Index < PMT_Last; ++Index) {

    if (!InheritedAnalysis[Index])
      continue;

    for (DenseMap<AnalysisID, Pass*>::iterator
           I = InheritedAnalysis[Index]->begin(),
           E = InheritedAnalysis[Index]->end(); I != E; ) {
      DenseMap<AnalysisID, Pass *>::iterator Info = I++;
      if (Info->second->getAsImmutablePass() == 0 &&
Dan Gohman's avatar
Dan Gohman committed
          std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
        if (GlobalPassDebugOpts->PassDebugging >= Details) {
David Greene's avatar
David Greene committed
          dbgs() << " -- '" <<  P->getPassName() << "' is not preserving '";
          dbgs() << S->getPassName() << "'\n";
Devang Patel's avatar
Devang Patel committed
        InheritedAnalysis[Index]->erase(Info);
/// Remove analysis passes that are not used any longer
Daniel Dunbar's avatar
Daniel Dunbar committed
void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg,
                                     enum PassDebuggingString DBG_STR) {
  SmallVector<Pass *, 12> DeadPasses;
  // If this is a on the fly manager then it does not have TPM.
  TPM->collectLastUses(DeadPasses, P);

  if (GlobalPassDebugOpts->PassDebugging >= Details && !DeadPasses.empty()) {
David Greene's avatar
David Greene committed
    dbgs() << " -*- '" <<  P->getPassName();
    dbgs() << "' is the last user of following pass instances.";
    dbgs() << " Free these instances\n";
Dan Gohman's avatar
Dan Gohman committed
  for (SmallVectorImpl<Pass *>::iterator I = DeadPasses.begin(),
         E = DeadPasses.end(); I != E; ++I)
    freePass(*I, Msg, DBG_STR);
}
Daniel Dunbar's avatar
Daniel Dunbar committed
void PMDataManager::freePass(Pass *P, StringRef Msg,
                             enum PassDebuggingString DBG_STR) {
  dumpPassInfo(P, FREEING_MSG, DBG_STR, Msg);
  {
    // If the pass crashes releasing memory, remember this.
    PassManagerPrettyStackEntry X(P);
    TimeRegion PassTimer(getPassTimer(P));

  AnalysisID PI = P->getPassID();
  if (const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI)) {
    // Remove the pass itself (if it is not already removed).
    AvailableAnalysis.erase(PI);
    // Remove all interfaces this pass implements, for which it is also
    // listed as the available implementation.
    const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
    for (unsigned i = 0, e = II.size(); i != e; ++i) {
      DenseMap<AnalysisID, Pass*>::iterator Pos =
        AvailableAnalysis.find(II[i]->getTypeInfo());
      if (Pos != AvailableAnalysis.end() && Pos->second == P)
        AvailableAnalysis.erase(Pos);
Dan Gohman's avatar
Dan Gohman committed
/// Add pass P into the PassVector. Update
/// AvailableAnalysis appropriately if ProcessAnalysis is true.