From 314fa8e40a439b36eb86984d48579083cc01e90a Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 14 Jul 2009 07:41:11 +0000 Subject: Move main llvm-prof functionality into a ModulePass. - To support using the ProfileInfo analysis results instead of accessing the ProfileInfoLoader directly. - Based on (part of) a patch by Andreas Neustifter. - No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75625 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-prof/llvm-prof.cpp | 258 ++++++++++++++++++++++++------------------ 1 file changed, 148 insertions(+), 110 deletions(-) (limited to 'tools/llvm-prof') diff --git a/tools/llvm-prof/llvm-prof.cpp b/tools/llvm-prof/llvm-prof.cpp index 2cff296ba9..d5dae76e6b 100644 --- a/tools/llvm-prof/llvm-prof.cpp +++ b/tools/llvm-prof/llvm-prof.cpp @@ -16,7 +16,9 @@ #include "llvm/InstrTypes.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" +#include "llvm/PassManager.h" #include "llvm/Assembly/AsmAnnotationWriter.h" +#include "llvm/Analysis/ProfileInfo.h" #include "llvm/Analysis/ProfileInfoLoader.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" @@ -113,6 +115,141 @@ namespace { }; } +namespace { + /// ProfileInfoPrinterPass - Helper pass to dump the profile information for + /// a module. + // + // FIXME: This should move elsewhere. + class ProfileInfoPrinterPass : public ModulePass { + ProfileInfoLoader &PIL; + public: + static char ID; // Class identification, replacement for typeinfo. + explicit ProfileInfoPrinterPass(ProfileInfoLoader &_PIL) + : ModulePass(&ID), PIL(_PIL) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + bool runOnModule(Module &M); + }; +} + +char ProfileInfoPrinterPass::ID = 0; + +bool ProfileInfoPrinterPass::runOnModule(Module &M) { + std::map FuncFreqs; + std::map BlockFreqs; + std::map EdgeFreqs; + + // Output a report. Eventually, there will be multiple reports selectable on + // the command line, for now, just keep things simple. + + // Emit the most frequent function table... + std::vector > FunctionCounts; + PIL.getFunctionCounts(FunctionCounts); + FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end()); + + // Sort by the frequency, backwards. + sort(FunctionCounts.begin(), FunctionCounts.end(), + PairSecondSortReverse()); + + uint64_t TotalExecutions = 0; + for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) + TotalExecutions += FunctionCounts[i].second; + + std::cout << "===" << std::string(73, '-') << "===\n" + << "LLVM profiling output for execution"; + if (PIL.getNumExecutions() != 1) std::cout << "s"; + std::cout << ":\n"; + + for (unsigned i = 0, e = PIL.getNumExecutions(); i != e; ++i) { + std::cout << " "; + if (e != 1) std::cout << i+1 << ". "; + std::cout << PIL.getExecution(i) << "\n"; + } + + std::cout << "\n===" << std::string(73, '-') << "===\n"; + std::cout << "Function execution frequencies:\n\n"; + + // Print out the function frequencies... + std::cout << " ## Frequency\n"; + for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { + if (FunctionCounts[i].second == 0) { + std::cout << "\n NOTE: " << e-i << " function" << + (e-i-1 ? "s were" : " was") << " never executed!\n"; + break; + } + + std::cout << std::setw(3) << i+1 << ". " + << std::setw(5) << FunctionCounts[i].second << "/" + << TotalExecutions << " " + << FunctionCounts[i].first->getName().c_str() << "\n"; + } + + std::set FunctionsToPrint; + + // If we have block count information, print out the LLVM module with + // frequency annotations. + if (PIL.hasAccurateBlockCounts()) { + std::vector > Counts; + PIL.getBlockCounts(Counts); + + TotalExecutions = 0; + for (unsigned i = 0, e = Counts.size(); i != e; ++i) + TotalExecutions += Counts[i].second; + + // Sort by the frequency, backwards. + sort(Counts.begin(), Counts.end(), + PairSecondSortReverse()); + + std::cout << "\n===" << std::string(73, '-') << "===\n"; + std::cout << "Top 20 most frequently executed basic blocks:\n\n"; + + // Print out the function frequencies... + std::cout <<" ## %% \tFrequency\n"; + unsigned BlocksToPrint = Counts.size(); + if (BlocksToPrint > 20) BlocksToPrint = 20; + for (unsigned i = 0; i != BlocksToPrint; ++i) { + if (Counts[i].second == 0) break; + Function *F = Counts[i].first->getParent(); + std::cout << std::setw(3) << i+1 << ". " + << std::setw(5) << std::setprecision(2) + << Counts[i].second/(double)TotalExecutions*100 << "% " + << std::setw(5) << Counts[i].second << "/" + << TotalExecutions << "\t" + << F->getName().c_str() << "() - " + << Counts[i].first->getName().c_str() << "\n"; + FunctionsToPrint.insert(F); + } + + BlockFreqs.insert(Counts.begin(), Counts.end()); + } + + if (PIL.hasAccurateEdgeCounts()) { + std::vector > Counts; + PIL.getEdgeCounts(Counts); + EdgeFreqs.insert(Counts.begin(), Counts.end()); + } + + if (PrintAnnotatedLLVM || PrintAllCode) { + std::cout << "\n===" << std::string(73, '-') << "===\n"; + std::cout << "Annotated LLVM code for the module:\n\n"; + + ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs); + + if (FunctionsToPrint.empty() || PrintAllCode) + M.print(std::cout, &PA); + else + // Print just a subset of the functions. + for (std::set::iterator I = FunctionsToPrint.begin(), + E = FunctionsToPrint.end(); I != E; ++I) + (*I)->print(std::cout, &PA); + } + + return false; +} int main(int argc, char **argv) { // Print a stack trace if we signal out. @@ -138,117 +275,17 @@ int main(int argc, char **argv) { return 1; } - // Read the profiling information - ProfileInfoLoader PI(argv[0], ProfileDataFile, *M); - - std::map FuncFreqs; - std::map BlockFreqs; - std::map EdgeFreqs; - - // Output a report. Eventually, there will be multiple reports selectable on - // the command line, for now, just keep things simple. - - // Emit the most frequent function table... - std::vector > FunctionCounts; - PI.getFunctionCounts(FunctionCounts); - FuncFreqs.insert(FunctionCounts.begin(), FunctionCounts.end()); - - // Sort by the frequency, backwards. - sort(FunctionCounts.begin(), FunctionCounts.end(), - PairSecondSortReverse()); - - uint64_t TotalExecutions = 0; - for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) - TotalExecutions += FunctionCounts[i].second; - - std::cout << "===" << std::string(73, '-') << "===\n" - << "LLVM profiling output for execution"; - if (PI.getNumExecutions() != 1) std::cout << "s"; - std::cout << ":\n"; - - for (unsigned i = 0, e = PI.getNumExecutions(); i != e; ++i) { - std::cout << " "; - if (e != 1) std::cout << i+1 << ". "; - std::cout << PI.getExecution(i) << "\n"; - } - - std::cout << "\n===" << std::string(73, '-') << "===\n"; - std::cout << "Function execution frequencies:\n\n"; + // Read the profiling information. This is redundant since we load it again + // using the standard profile info provider pass, but for now this gives us + // access to additional information not exposed via the ProfileInfo + // interface. + ProfileInfoLoader PIL(argv[0], ProfileDataFile, *M); - // Print out the function frequencies... - std::cout << " ## Frequency\n"; - for (unsigned i = 0, e = FunctionCounts.size(); i != e; ++i) { - if (FunctionCounts[i].second == 0) { - std::cout << "\n NOTE: " << e-i << " function" << - (e-i-1 ? "s were" : " was") << " never executed!\n"; - break; - } - - std::cout << std::setw(3) << i+1 << ". " - << std::setw(5) << FunctionCounts[i].second << "/" - << TotalExecutions << " " - << FunctionCounts[i].first->getName().c_str() << "\n"; - } - - std::set FunctionsToPrint; - - // If we have block count information, print out the LLVM module with - // frequency annotations. - if (PI.hasAccurateBlockCounts()) { - std::vector > Counts; - PI.getBlockCounts(Counts); - - TotalExecutions = 0; - for (unsigned i = 0, e = Counts.size(); i != e; ++i) - TotalExecutions += Counts[i].second; - - // Sort by the frequency, backwards. - sort(Counts.begin(), Counts.end(), - PairSecondSortReverse()); - - std::cout << "\n===" << std::string(73, '-') << "===\n"; - std::cout << "Top 20 most frequently executed basic blocks:\n\n"; - - // Print out the function frequencies... - std::cout <<" ## %% \tFrequency\n"; - unsigned BlocksToPrint = Counts.size(); - if (BlocksToPrint > 20) BlocksToPrint = 20; - for (unsigned i = 0; i != BlocksToPrint; ++i) { - if (Counts[i].second == 0) break; - Function *F = Counts[i].first->getParent(); - std::cout << std::setw(3) << i+1 << ". " - << std::setw(5) << std::setprecision(2) - << Counts[i].second/(double)TotalExecutions*100 << "% " - << std::setw(5) << Counts[i].second << "/" - << TotalExecutions << "\t" - << F->getName().c_str() << "() - " - << Counts[i].first->getName().c_str() << "\n"; - FunctionsToPrint.insert(F); - } - - BlockFreqs.insert(Counts.begin(), Counts.end()); - } - - if (PI.hasAccurateEdgeCounts()) { - std::vector > Counts; - PI.getEdgeCounts(Counts); - EdgeFreqs.insert(Counts.begin(), Counts.end()); - } - - if (PrintAnnotatedLLVM || PrintAllCode) { - std::cout << "\n===" << std::string(73, '-') << "===\n"; - std::cout << "Annotated LLVM code for the module:\n\n"; - - ProfileAnnotator PA(FuncFreqs, BlockFreqs, EdgeFreqs); - - if (FunctionsToPrint.empty() || PrintAllCode) - M->print(std::cout, &PA); - else - // Print just a subset of the functions. - for (std::set::iterator I = FunctionsToPrint.begin(), - E = FunctionsToPrint.end(); I != E; ++I) - (*I)->print(std::cout, &PA); - } + // Run the printer pass. + PassManager PassMgr; + PassMgr.add(createProfileLoaderPass(ProfileDataFile)); + PassMgr.add(new ProfileInfoPrinterPass(PIL)); + PassMgr.run(*M); return 0; } catch (const std::string& msg) { @@ -256,5 +293,6 @@ int main(int argc, char **argv) { } catch (...) { std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n"; } + return 1; } -- cgit v1.2.3