diff options
Diffstat (limited to 'llvm/lib/Analysis/CFGPrinter.cpp')
-rw-r--r-- | llvm/lib/Analysis/CFGPrinter.cpp | 250 |
1 files changed, 199 insertions, 51 deletions
diff --git a/llvm/lib/Analysis/CFGPrinter.cpp b/llvm/lib/Analysis/CFGPrinter.cpp index fb261755e5d..10be4e4bb95 100644 --- a/llvm/lib/Analysis/CFGPrinter.cpp +++ b/llvm/lib/Analysis/CFGPrinter.cpp @@ -22,53 +22,170 @@ #include "llvm/Support/FileSystem.h" using namespace llvm; +static cl::opt<bool> CFGHeatPerFunction("cfg-heat-per-function", + cl::init(false), cl::Hidden, + cl::desc("Heat CFG per function")); + +static cl::opt<bool> ShowHeatColors("cfg-heat-colors", cl::init(true), + cl::Hidden, + cl::desc("Show heat colors in CFG")); + +static cl::opt<bool> UseRawEdgeWeight("cfg-raw-weights", cl::init(false), + cl::Hidden, + cl::desc("Use raw weights for labels. " + "Use percentages as default.")); + +static cl::opt<bool> ShowEdgeWeight("cfg-weights", cl::init(true), cl::Hidden, + cl::desc("Show edges labeled with weights")); + +static void writeHeatCFGToDotFile(Function &F, BlockFrequencyInfo *BFI, + BranchProbabilityInfo *BPI, uint64_t MaxFreq, + bool UseHeuristic, bool isSimple) { + std::string Filename = ("cfg." + F.getName() + ".dot").str(); + errs() << "Writing '" << Filename << "'..."; + + std::error_code EC; + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); + + CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq); + CFGInfo.setHeuristic(UseHeuristic); + CFGInfo.setHeatColors(ShowHeatColors); + CFGInfo.setEdgeWeights(ShowEdgeWeight); + CFGInfo.setRawEdgeWeights(UseRawEdgeWeight); + + if (!EC) + WriteGraph(File, &CFGInfo, isSimple); + else + errs() << " error opening file for writing!"; + errs() << "\n"; +} + +static void writeAllCFGsToDotFile(Module &M, + function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, + function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, + bool isSimple) { + bool UseHeuristic = true; + uint64_t MaxFreq = 0; + if (!CFGHeatPerFunction) + MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic); + + for (auto &F : M) { + if (F.isDeclaration()) continue; + auto *BFI = LookupBFI(F); + auto *BPI = LookupBPI(F); + if (CFGHeatPerFunction) + MaxFreq = getMaxFreq(F, BFI, UseHeuristic); + writeHeatCFGToDotFile(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple); + } + +} + +static void viewHeatCFG(Function &F, BlockFrequencyInfo *BFI, + BranchProbabilityInfo *BPI, uint64_t MaxFreq, + bool UseHeuristic, bool isSimple) { + CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq); + CFGInfo.setHeuristic(UseHeuristic); + CFGInfo.setHeatColors(ShowHeatColors); + CFGInfo.setEdgeWeights(ShowEdgeWeight); + CFGInfo.setRawEdgeWeights(UseRawEdgeWeight); + + ViewGraph(&CFGInfo, "cfg." + F.getName(), isSimple); +} + +static void viewAllCFGs(Module &M, + function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, + function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, + bool isSimple) { + bool UseHeuristic = true; + uint64_t MaxFreq = 0; + if (!CFGHeatPerFunction) + MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic); + + for (auto &F : M) { + if (F.isDeclaration()) continue; + auto *BFI = LookupBFI(F); + auto *BPI = LookupBPI(F); + if (CFGHeatPerFunction) + MaxFreq = getMaxFreq(F, BFI, UseHeuristic); + viewHeatCFG(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple); + } + +} + namespace { - struct CFGViewerLegacyPass : public FunctionPass { + struct CFGViewerLegacyPass : public ModulePass { static char ID; // Pass identifcation, replacement for typeid - CFGViewerLegacyPass() : FunctionPass(ID) { + CFGViewerLegacyPass() : ModulePass(ID) { initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool runOnFunction(Function &F) override { - F.viewCFG(); + bool runOnModule(Module &M) override { + auto LookupBFI = [this](Function &F) { + return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI(); + }; + auto LookupBPI = [this](Function &F) { + return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI(); + }; + viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false); return false; } - void print(raw_ostream &OS, const Module* = nullptr) const override {} + void print(raw_ostream &OS, const Module * = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + ModulePass::getAnalysisUsage(AU); + AU.addRequired<BlockFrequencyInfoWrapperPass>(); + AU.addRequired<BranchProbabilityInfoWrapperPass>(); AU.setPreservesAll(); } + }; } char CFGViewerLegacyPass::ID = 0; INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true) -PreservedAnalyses CFGViewerPass::run(Function &F, - FunctionAnalysisManager &AM) { - F.viewCFG(); +PreservedAnalyses CFGViewerPass::run(Module &M, + ModuleAnalysisManager &AM) { + auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto LookupBFI = [&FAM](Function &F) { + return &FAM.getResult<BlockFrequencyAnalysis>(F); + }; + auto LookupBPI = [&FAM](Function &F) { + return &FAM.getResult<BranchProbabilityAnalysis>(F); + }; + viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false); return PreservedAnalyses::all(); } namespace { - struct CFGOnlyViewerLegacyPass : public FunctionPass { + struct CFGOnlyViewerLegacyPass : public ModulePass { static char ID; // Pass identifcation, replacement for typeid - CFGOnlyViewerLegacyPass() : FunctionPass(ID) { + CFGOnlyViewerLegacyPass() : ModulePass(ID) { initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool runOnFunction(Function &F) override { - F.viewCFGOnly(); + bool runOnModule(Module &M) override { + auto LookupBFI = [this](Function &F) { + return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI(); + }; + auto LookupBPI = [this](Function &F) { + return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI(); + }; + viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true); return false; } - void print(raw_ostream &OS, const Module* = nullptr) const override {} + void print(raw_ostream &OS, const Module * = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + ModulePass::getAnalysisUsage(AU); + AU.addRequired<BlockFrequencyInfoWrapperPass>(); + AU.addRequired<BranchProbabilityInfoWrapperPass>(); AU.setPreservesAll(); } + }; } @@ -76,43 +193,46 @@ char CFGOnlyViewerLegacyPass::ID = 0; INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only", "View CFG of function (with no function bodies)", false, true) -PreservedAnalyses CFGOnlyViewerPass::run(Function &F, - FunctionAnalysisManager &AM) { - F.viewCFGOnly(); +PreservedAnalyses CFGOnlyViewerPass::run(Module &M, + ModuleAnalysisManager &AM) { + auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto LookupBFI = [&FAM](Function &F) { + return &FAM.getResult<BlockFrequencyAnalysis>(F); + }; + auto LookupBPI = [&FAM](Function &F) { + return &FAM.getResult<BranchProbabilityAnalysis>(F); + }; + viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true); return PreservedAnalyses::all(); } -static void writeCFGToDotFile(Function &F, bool CFGOnly = false) { - std::string Filename = ("cfg." + F.getName() + ".dot").str(); - errs() << "Writing '" << Filename << "'..."; - - std::error_code EC; - raw_fd_ostream File(Filename, EC, sys::fs::F_Text); - - if (!EC) - WriteGraph(File, (const Function*)&F, CFGOnly); - else - errs() << " error opening file for writing!"; - errs() << "\n"; -} - namespace { - struct CFGPrinterLegacyPass : public FunctionPass { + struct CFGPrinterLegacyPass : public ModulePass { static char ID; // Pass identification, replacement for typeid - CFGPrinterLegacyPass() : FunctionPass(ID) { + CFGPrinterLegacyPass() : ModulePass(ID) { initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool runOnFunction(Function &F) override { - writeCFGToDotFile(F); + bool runOnModule(Module &M) override { + auto LookupBFI = [this](Function &F) { + return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI(); + }; + auto LookupBPI = [this](Function &F) { + return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI(); + }; + writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false); return false; } - void print(raw_ostream &OS, const Module* = nullptr) const override {} + void print(raw_ostream &OS, const Module * = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + ModulePass::getAnalysisUsage(AU); + AU.addRequired<BlockFrequencyInfoWrapperPass>(); + AU.addRequired<BranchProbabilityInfoWrapperPass>(); AU.setPreservesAll(); } + }; } @@ -120,28 +240,46 @@ char CFGPrinterLegacyPass::ID = 0; INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file", false, true) -PreservedAnalyses CFGPrinterPass::run(Function &F, - FunctionAnalysisManager &AM) { - writeCFGToDotFile(F); +PreservedAnalyses CFGPrinterPass::run(Module &M, + ModuleAnalysisManager &AM) { + auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto LookupBFI = [&FAM](Function &F) { + return &FAM.getResult<BlockFrequencyAnalysis>(F); + }; + auto LookupBPI = [&FAM](Function &F) { + return &FAM.getResult<BranchProbabilityAnalysis>(F); + }; + writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false); return PreservedAnalyses::all(); } namespace { - struct CFGOnlyPrinterLegacyPass : public FunctionPass { + struct CFGOnlyPrinterLegacyPass : public ModulePass { static char ID; // Pass identification, replacement for typeid - CFGOnlyPrinterLegacyPass() : FunctionPass(ID) { + CFGOnlyPrinterLegacyPass() : ModulePass(ID) { initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool runOnFunction(Function &F) override { - writeCFGToDotFile(F, /*CFGOnly=*/true); + bool runOnModule(Module &M) override { + auto LookupBFI = [this](Function &F) { + return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI(); + }; + auto LookupBPI = [this](Function &F) { + return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI(); + }; + writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true); return false; } - void print(raw_ostream &OS, const Module* = nullptr) const override {} + + void print(raw_ostream &OS, const Module * = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + ModulePass::getAnalysisUsage(AU); + AU.addRequired<BlockFrequencyInfoWrapperPass>(); + AU.addRequired<BranchProbabilityInfoWrapperPass>(); AU.setPreservesAll(); } + }; } @@ -150,9 +288,16 @@ INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only", "Print CFG of function to 'dot' file (with no function bodies)", false, true) -PreservedAnalyses CFGOnlyPrinterPass::run(Function &F, - FunctionAnalysisManager &AM) { - writeCFGToDotFile(F, /*CFGOnly=*/true); +PreservedAnalyses CFGOnlyPrinterPass::run(Module &M, + ModuleAnalysisManager &AM) { + auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + auto LookupBFI = [&FAM](Function &F) { + return &FAM.getResult<BlockFrequencyAnalysis>(F); + }; + auto LookupBPI = [&FAM](Function &F) { + return &FAM.getResult<BranchProbabilityAnalysis>(F); + }; + writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true); return PreservedAnalyses::all(); } @@ -162,7 +307,9 @@ PreservedAnalyses CFGOnlyPrinterPass::run(Function &F, /// being a 'dot' and 'gv' program in your path. /// void Function::viewCFG() const { - ViewGraph(this, "cfg" + getName()); + + CFGDOTInfo CFGInfo(this); + ViewGraph(&CFGInfo, "cfg" + getName()); } /// viewCFGOnly - This function is meant for use from the debugger. It works @@ -171,14 +318,15 @@ void Function::viewCFG() const { /// this can make the graph smaller. /// void Function::viewCFGOnly() const { - ViewGraph(this, "cfg" + getName(), true); + + CFGDOTInfo CFGInfo(this); + ViewGraph(&CFGInfo, "cfg" + getName(), true); } -FunctionPass *llvm::createCFGPrinterLegacyPassPass () { +ModulePass *llvm::createCFGPrinterLegacyPassPass() { return new CFGPrinterLegacyPass(); } -FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () { +ModulePass *llvm::createCFGOnlyPrinterLegacyPassPass() { return new CFGOnlyPrinterLegacyPass(); } - |