diff options
| -rw-r--r-- | llvm/include/llvm/DebugInfoProbe.h | 67 | ||||
| -rw-r--r-- | llvm/lib/Analysis/LoopPass.cpp | 23 | ||||
| -rw-r--r-- | llvm/lib/VMCore/DebugInfoProbe.cpp | 237 | ||||
| -rw-r--r-- | llvm/lib/VMCore/PassManager.cpp | 23 | 
4 files changed, 347 insertions, 3 deletions
diff --git a/llvm/include/llvm/DebugInfoProbe.h b/llvm/include/llvm/DebugInfoProbe.h new file mode 100644 index 00000000000..78d00dfeedd --- /dev/null +++ b/llvm/include/llvm/DebugInfoProbe.h @@ -0,0 +1,67 @@ +//===-- DebugInfoProbe.h - DebugInfo Probe ----------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a probe, DebugInfoProbe, that can be used by pass +// manager to analyze how optimizer is treating debugging information. +//  +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_DEBUGINFOPROBE_H +#define LLVM_TRANSFORMS_UTILS_DEBUGINFOPROBE_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +  class Function; +  class Pass; +  class DebugInfoProbeImpl; + +  /// DebugInfoProbe - This class provides a interface to monitor +  /// how an optimization pass is preserving debugging information. +  class DebugInfoProbe { +    public: +    DebugInfoProbe(); +    ~DebugInfoProbe(); + +    /// initialize - Collect information before running an optimization pass. +    void initialize(StringRef PName, Function &F); + +    /// finalize - Collect information after running an optimization pass. This +    /// must be used after initialization. +    void finalize(Function &F); + +    /// report - Report findings. This should be invoked after finalize. +    void report(); + +    private: +    DebugInfoProbeImpl *pImpl; +  }; + +  /// DebugInfoProbeInfo - This class provides an interface that a pass manager +  /// can use to manage debug info probes. +  class DebugInfoProbeInfo { +    StringMap<DebugInfoProbe *> Probes; +  public: +    DebugInfoProbeInfo() {} + +    /// ~DebugInfoProbeInfo - Report data collected by all probes before deleting +    /// them. +    ~DebugInfoProbeInfo(); + +    /// initialize - Collect information before running an optimization pass. +    void initialize(Pass *P, Function &F); + +    /// finalize - Collect information after running an optimization pass. This +    /// must be used after initialization. +    void finalize(Pass *P, Function &F); +  }; + +} // End llvm namespace + +#endif diff --git a/llvm/lib/Analysis/LoopPass.cpp b/llvm/lib/Analysis/LoopPass.cpp index 8e1a7bfef69..10e3f297f9c 100644 --- a/llvm/lib/Analysis/LoopPass.cpp +++ b/llvm/lib/Analysis/LoopPass.cpp @@ -14,8 +14,10 @@  //===----------------------------------------------------------------------===//  #include "llvm/Analysis/LoopPass.h" +#include "llvm/DebugInfoProbe.h"  #include "llvm/Assembly/PrintModulePass.h"  #include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h"  #include "llvm/Support/Timer.h"  using namespace llvm; @@ -52,6 +54,20 @@ char PrintLoopPass::ID = 0;  }  //===----------------------------------------------------------------------===// +// DebugInfoProbe + +static DebugInfoProbeInfo *TheDebugProbe; +static void createDebugInfoProbe() { +  if (TheDebugProbe) return; +       +  // Constructed the first time this is called. This guarantees that the  +  // object will be constructed, if -enable-debug-info-probe is set,  +  // before static globals, thus it will be destroyed before them. +  static ManagedStatic<DebugInfoProbeInfo> DIP; +  TheDebugProbe = &*DIP; +} + +//===----------------------------------------------------------------------===//  // LPPassManager  // @@ -223,6 +239,7 @@ void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const {  bool LPPassManager::runOnFunction(Function &F) {    LI = &getAnalysis<LoopInfo>();    bool Changed = false; +  createDebugInfoProbe();    // Collect inherited analysis from Module level pass manager.    populateInheritedAnalysis(TPM->activeStack); @@ -254,19 +271,21 @@ bool LPPassManager::runOnFunction(Function &F) {      // Run all passes on the current Loop.      for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {          LoopPass *P = getContainedPass(Index); -        dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG,                     CurrentLoop->getHeader()->getName());        dumpRequiredSet(P);        initializeAnalysisImpl(P); - +      if (TheDebugProbe) +        TheDebugProbe->initialize(P, F);        {          PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader());          TimeRegion PassTimer(getPassTimer(P));          Changed |= P->runOnLoop(CurrentLoop, *this);        } +      if (TheDebugProbe) +        TheDebugProbe->finalize(P, F);        if (Changed)          dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, diff --git a/llvm/lib/VMCore/DebugInfoProbe.cpp b/llvm/lib/VMCore/DebugInfoProbe.cpp new file mode 100644 index 00000000000..4a5e659ef27 --- /dev/null +++ b/llvm/lib/VMCore/DebugInfoProbe.cpp @@ -0,0 +1,237 @@ +//===-- DebugInfoProbe.cpp - DebugInfo Probe ------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements DebugInfoProbe. This probe can be used by a pass +// manager to analyze how optimizer is treating debugging information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "debuginfoprobe" +#include "llvm/DebugInfoProbe.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Metadata.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringRef.h" +#include <set> +#include <string> + +using namespace llvm; + +static cl::opt<bool> +EnableDebugInfoProbe("enable-debug-info-probe", cl::Hidden, +                     cl::desc("Enable debug info probe")); + +// CreateInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } + +//===----------------------------------------------------------------------===// +// DebugInfoProbeImpl - This class implements a interface to monitor +// how an optimization pass is preserving debugging information. + +namespace llvm { + +  class DebugInfoProbeImpl { +  public: +    DebugInfoProbeImpl() : NumDbgLineLost(0),NumDbgValueLost(0) {} +    void initialize(StringRef PName, Function &F); +    void finalize(Function &F); +    void report(); +  private: +    unsigned NumDbgLineLost, NumDbgValueLost; +    std::string PassName; +    Function *TheFn; +    std::set<unsigned> LineNos; +    std::set<MDNode *> DbgVariables; +  }; +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbeImpl + +static void collect(Function &F, std::set<unsigned> &Lines) { +  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) +    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();  +         BI != BE; ++BI) { +      const DebugLoc &DL = BI->getDebugLoc(); +      unsigned LineNo = 0; +      if (!DL.isUnknown()) { +        if (MDNode *N = DL.getInlinedAt(F.getContext())) +          LineNo = DebugLoc::getFromDILocation(N).getLine(); +        else +          LineNo = DL.getLine(); + +        Lines.insert(LineNo); +      } +    } +} + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbeImpl::initialize(StringRef PName, Function &F) { +  if (!EnableDebugInfoProbe) return; +  PassName = PName; +  NumDbgLineLost = 0; +  NumDbgValueLost = 0; + +  LineNos.clear(); +  DbgVariables.clear(); +  TheFn = &F; +  collect(F, LineNos); + +  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) +    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();  +         BI != BE; ++BI) { +      if (!isa<DbgInfoIntrinsic>(BI)) continue; +      Value *Addr = NULL; +      MDNode *Node = NULL; +      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) { +        Addr = DDI->getAddress(); +        Node = DDI->getVariable(); +      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) { +        Addr = DVI->getValue(); +        Node = DVI->getVariable(); +      } +      if (Addr) continue; +      DbgVariables.insert(Node); +    } +} + +/// report - Report findings. This should be invoked after finalize. +void DebugInfoProbeImpl::report() { +  if (!EnableDebugInfoProbe) return; +  if (NumDbgLineLost || NumDbgValueLost) { +    raw_ostream *OutStream = CreateInfoOutputFile(); +    if (NumDbgLineLost) +      *OutStream << NumDbgLineLost +                 << "\t times line number info lost by " +                 << PassName << "\n"; +    if (NumDbgValueLost) +      *OutStream << NumDbgValueLost +                 << "\t times variable info lost by    " +                 << PassName << "\n"; +    delete OutStream; +  } +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbeImpl::finalize(Function &F) { +  if (!EnableDebugInfoProbe) return; +  std::set<unsigned> LineNos2; +  collect(F, LineNos2); +  assert (TheFn == &F && "Invalid function to measure!"); + +  for (std::set<unsigned>::iterator I = LineNos.begin(), +         E = LineNos.end(); I != E; ++I) { +    unsigned LineNo = *I; +    if (LineNos2.count(LineNo) == 0) { +      DEBUG(dbgs() << "Losing dbg info intrinsic at line " << LineNo << " "); +      ++NumDbgLineLost; +    } +  } + +  std::set<MDNode *>DbgVariables2; +  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) +    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end();  +         BI != BE; ++BI) { +      if (!isa<DbgInfoIntrinsic>(BI)) continue; +      Value *Addr = NULL; +      MDNode *Node = NULL; +      if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) { +        Addr = DDI->getAddress(); +        Node = DDI->getVariable(); +      } else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) { +        Addr = DVI->getValue(); +        Node = DVI->getVariable(); +      } +      if (Addr) continue; +      DbgVariables2.insert(Node); +    } + +  for (std::set<MDNode *>::iterator I = DbgVariables.begin(),  +         E = DbgVariables.end(); I != E; ++I) { +    if (DbgVariables2.count(*I) == 0) { +      DEBUG(dbgs() << "Losing dbg info for variable: "); +      DEBUG((*I)->print(dbgs())); +      ++NumDbgValueLost; +    } +  } +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbe + +DebugInfoProbe::DebugInfoProbe() { +  pImpl = new DebugInfoProbeImpl(); +} + +DebugInfoProbe::~DebugInfoProbe() { +  delete pImpl; +} + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbe::initialize(StringRef PName, Function &F) { +  pImpl->initialize(PName, F); +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbe::finalize(Function &F) { +  pImpl->finalize(F); +} + +/// report - Report findings. This should be invoked after finalize. +void DebugInfoProbe::report() { +  pImpl->report(); +} + +//===----------------------------------------------------------------------===// +// DebugInfoProbeInfo + +/// ~DebugInfoProbeInfo - Report data collected by all probes before deleting +/// them. +DebugInfoProbeInfo::~DebugInfoProbeInfo() { +  if (!EnableDebugInfoProbe) return; +    for (StringMap<DebugInfoProbe*>::iterator I = Probes.begin(), +           E = Probes.end(); I != E; ++I) { +      I->second->report(); +      delete I->second; +    } +  } + +/// initialize - Collect information before running an optimization pass. +void DebugInfoProbeInfo::initialize(Pass *P, Function &F) { +  if (!EnableDebugInfoProbe) return; +  if (P->getAsPMDataManager()) +    return; + +  StringMapEntry<DebugInfoProbe *> &Entry = +    Probes.GetOrCreateValue(P->getPassName()); +  DebugInfoProbe *&Probe = Entry.getValue(); +  if (!Probe) +    Probe = new DebugInfoProbe(); +  Probe->initialize(P->getPassName(), F); +} + +/// finalize - Collect information after running an optimization pass. This +/// must be used after initialization. +void DebugInfoProbeInfo::finalize(Pass *P, Function &F) { +  if (!EnableDebugInfoProbe) return; +  if (P->getAsPMDataManager()) +    return; +  StringMapEntry<DebugInfoProbe *> &Entry = +    Probes.GetOrCreateValue(P->getPassName()); +  DebugInfoProbe *&Probe = Entry.getValue(); +  assert (Probe && "DebugInfoProbe is not initialized!"); +  Probe->finalize(F); +} diff --git a/llvm/lib/VMCore/PassManager.cpp b/llvm/lib/VMCore/PassManager.cpp index cd170dff181..ca4455a436a 100644 --- a/llvm/lib/VMCore/PassManager.cpp +++ b/llvm/lib/VMCore/PassManager.cpp @@ -14,6 +14,7 @@  #include "llvm/PassManagers.h"  #include "llvm/PassManager.h" +#include "llvm/DebugInfoProbe.h"  #include "llvm/Assembly/PrintModulePass.h"  #include "llvm/Assembly/Writer.h"  #include "llvm/Support/CommandLine.h" @@ -25,6 +26,7 @@  #include "llvm/Support/PassNameParser.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/Support/Mutex.h" +#include "llvm/ADT/StringMap.h"  #include <algorithm>  #include <cstdio>  #include <map> @@ -442,6 +444,20 @@ char PassManagerImpl::ID = 0;  namespace {  //===----------------------------------------------------------------------===// +// DebugInfoProbe + +static DebugInfoProbeInfo *TheDebugProbe; +static void createDebugInfoProbe() { +  if (TheDebugProbe) return; +       +  // Constructed the first time this is called. This guarantees that the  +  // object will be constructed, if -enable-debug-info-probe is set,  +  // before static globals, thus it will be destroyed before them. +  static ManagedStatic<DebugInfoProbeInfo> DIP; +  TheDebugProbe = &*DIP; +} + +//===----------------------------------------------------------------------===//  /// 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. @@ -1430,6 +1446,7 @@ void FunctionPassManagerImpl::releaseMemoryOnTheFly() {  bool FunctionPassManagerImpl::run(Function &F) {    bool Changed = false;    TimingInfo::createTheTimeInfo(); +  createDebugInfoProbe();    initializeAllAnalysisInfo();    for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) @@ -1477,13 +1494,16 @@ bool FPPassManager::runOnFunction(Function &F) {      dumpRequiredSet(FP);      initializeAnalysisImpl(FP); - +    if (TheDebugProbe) +      TheDebugProbe->initialize(FP, F);      {        PassManagerPrettyStackEntry X(FP, F);        TimeRegion PassTimer(getPassTimer(FP));        LocalChanged |= FP->runOnFunction(F);      } +    if (TheDebugProbe) +      TheDebugProbe->finalize(FP, F);      Changed |= LocalChanged;      if (LocalChanged) @@ -1631,6 +1651,7 @@ Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){  bool PassManagerImpl::run(Module &M) {    bool Changed = false;    TimingInfo::createTheTimeInfo(); +  createDebugInfoProbe();    dumpArguments();    dumpPasses();  | 

