summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/CFGPrinter.cpp
diff options
context:
space:
mode:
authorSean Fertile <sfertile@ca.ibm.com>2018-06-29 17:13:58 +0000
committerSean Fertile <sfertile@ca.ibm.com>2018-06-29 17:13:58 +0000
commit3b0535b424aca711375fa4e2a25c40509d6c6ed3 (patch)
tree95a4f46d923c0c9d8b13f305fbfe6884759a1125 /llvm/lib/Analysis/CFGPrinter.cpp
parent8eeece38efaf0ef487ef43964a5884aa74a25286 (diff)
downloadbcm5719-llvm-3b0535b424aca711375fa4e2a25c40509d6c6ed3.tar.gz
bcm5719-llvm-3b0535b424aca711375fa4e2a25c40509d6c6ed3.zip
Extend CFGPrinter and CallPrinter with Heat Colors
Extends the CFGPrinter and CallPrinter with heat colors based on heuristics or profiling information. The colors are enabled by default and can be toggled on/off for CFGPrinter by using the option -cfg-heat-colors for both -dot-cfg[-only] and -view-cfg[-only]. Similarly, the colors can be toggled on/off for CallPrinter by using the option -callgraph-heat-colors for both -dot-callgraph and -view-callgraph. Patch by Rodrigo Caetano Rocha! Differential Revision: https://reviews.llvm.org/D40425 llvm-svn: 335996
Diffstat (limited to 'llvm/lib/Analysis/CFGPrinter.cpp')
-rw-r--r--llvm/lib/Analysis/CFGPrinter.cpp250
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();
}
-
OpenPOWER on IntegriCloud