diff options
author | Devang Patel <dpatel@apple.com> | 2011-03-10 00:21:25 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2011-03-10 00:21:25 +0000 |
commit | 6af531febe488adb655c7e3de96c7c6bd6536eac (patch) | |
tree | 8c6e75ff86035d8621ec2cd8f4a08e0097d80d39 /lib/VMCore | |
parent | b0519e15f70cef7ba16b712f258d4782ade17e13 (diff) | |
download | external_llvm-6af531febe488adb655c7e3de96c7c6bd6536eac.zip external_llvm-6af531febe488adb655c7e3de96c7c6bd6536eac.tar.gz external_llvm-6af531febe488adb655c7e3de96c7c6bd6536eac.tar.bz2 |
Introduce DebugInfoProbe. This is used to monitor how llvm optimizer is treating debugging information.
It generates output that lools like
8 times line number info lost by Scalar Replacement of Aggregates (SSAUp)
1 times line number info lost by Simplify well-known library calls
12 times variable info lost by Jump Threading
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127381 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/DebugInfoProbe.cpp | 237 | ||||
-rw-r--r-- | lib/VMCore/PassManager.cpp | 23 |
2 files changed, 259 insertions, 1 deletions
diff --git a/lib/VMCore/DebugInfoProbe.cpp b/lib/VMCore/DebugInfoProbe.cpp new file mode 100644 index 0000000..4a5e659 --- /dev/null +++ b/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/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index cd170df..ca4455a 100644 --- a/lib/VMCore/PassManager.cpp +++ b/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(); |