llvm.org GIT mirror llvm / 8b6f52a
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335996 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Fertile 1 year, 2 months ago
12 changed file(s) with 941 addition(s) and 151 deletion(s). Raw diff Collapse all Expand all
2020
2121 #include "llvm/IR/CFG.h"
2222 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Module.h"
2324 #include "llvm/IR/Function.h"
2425 #include "llvm/IR/Instructions.h"
2526 #include "llvm/IR/PassManager.h"
27 #include "llvm/Analysis/BlockFrequencyInfo.h"
28 #include "llvm/Analysis/BranchProbabilityInfo.h"
29 #include "llvm/Analysis/HeatUtils.h"
30 #include "llvm/Support/FormatVariadic.h"
2631 #include "llvm/Support/GraphWriter.h"
2732
2833 namespace llvm {
2934 class CFGViewerPass
3035 : public PassInfoMixin {
3136 public:
32 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
37 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
3338 };
3439
3540 class CFGOnlyViewerPass
3641 : public PassInfoMixin {
3742 public:
38 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
43 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
3944 };
4045
4146 class CFGPrinterPass
4247 : public PassInfoMixin {
4348 public:
44 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
49 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
4550 };
4651
4752 class CFGOnlyPrinterPass
4853 : public PassInfoMixin {
4954 public:
50 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
51 };
52
53 template<>
54 struct DOTGraphTraits : public DefaultDOTGraphTraits {
55
56 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
57
58 static std::string getGraphName(const Function *F) {
59 return "CFG for '" + F->getName().str() + "' function";
60 }
61
62 static std::string getSimpleNodeLabel(const BasicBlock *Node,
63 const Function *) {
55 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
56 };
57
58 class CFGDOTInfo {
59 private:
60 const Function *F;
61 const BlockFrequencyInfo *BFI;
62 const BranchProbabilityInfo *BPI;
63 uint64_t MaxFreq;
64 bool ShowHeat;
65 bool Heuristic;
66 bool EdgeWeights;
67 bool RawWeights;
68
69 public:
70 CFGDOTInfo(const Function *F) : CFGDOTInfo(F, nullptr, nullptr, 0) { }
71
72 CFGDOTInfo(const Function *F, const BlockFrequencyInfo *BFI,
73 BranchProbabilityInfo *BPI, uint64_t MaxFreq)
74 : F(F), BFI(BFI), BPI(BPI), MaxFreq(MaxFreq) {
75 ShowHeat = false;
76 Heuristic = true;
77 EdgeWeights = true;
78 RawWeights = true;
79 }
80
81 const BlockFrequencyInfo *getBFI() { return BFI; }
82
83 const BranchProbabilityInfo *getBPI() { return BPI; }
84
85 const Function *getFunction() { return this->F; }
86
87 uint64_t getMaxFreq() { return MaxFreq; }
88
89 uint64_t getFreq(const BasicBlock *BB) {
90 return getBlockFreq(BB, BFI, Heuristic);
91 }
92
93 void setHeatColors(bool ShowHeat) { this->ShowHeat = ShowHeat; }
94
95 bool showHeatColors() { return ShowHeat; }
96
97 void setHeuristic(bool Heuristic) { this->Heuristic = Heuristic; }
98
99 bool useHeuristic() { return Heuristic; }
100
101 void setRawEdgeWeights(bool RawWeights) { this->RawWeights = RawWeights; }
102
103 bool useRawEdgeWeights() { return RawWeights; }
104
105 void setEdgeWeights(bool EdgeWeights) { this->EdgeWeights = EdgeWeights; }
106
107 bool showEdgeWeights() { return EdgeWeights; }
108 };
109
110 template <>
111 struct GraphTraits : public GraphTraits {
112 static NodeRef getEntryNode(CFGDOTInfo *CFGInfo) {
113 return &(CFGInfo->getFunction()->getEntryBlock());
114 }
115
116 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
117 using nodes_iterator = pointer_iterator;
118
119 static nodes_iterator nodes_begin(CFGDOTInfo *CFGInfo) {
120 return nodes_iterator(CFGInfo->getFunction()->begin());
121 }
122
123 static nodes_iterator nodes_end(CFGDOTInfo *CFGInfo) {
124 return nodes_iterator(CFGInfo->getFunction()->end());
125 }
126
127 static size_t size(CFGDOTInfo *CFGInfo) { return CFGInfo->getFunction()->size(); }
128 };
129
130 template <> struct DOTGraphTraits : public DefaultDOTGraphTraits {
131
132 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
133
134 static std::string getGraphName(CFGDOTInfo *CFGInfo) {
135 return "CFG for '" + CFGInfo->getFunction()->getName().str() + "' function";
136 }
137
138 static std::string getSimpleNodeLabel(const BasicBlock *Node, CFGDOTInfo *) {
64139 if (!Node->getName().empty())
65140 return Node->getName().str();
66141
72147 }
73148
74149 static std::string getCompleteNodeLabel(const BasicBlock *Node,
75 const Function *) {
150 CFGDOTInfo *) {
76151 enum { MaxColumns = 80 };
77152 std::string Str;
78153 raw_string_ostream OS(Str);
116191 return OutStr;
117192 }
118193
119 std::string getNodeLabel(const BasicBlock *Node,
120 const Function *Graph) {
194 std::string getNodeLabel(const BasicBlock *Node, CFGDOTInfo *CFGInfo) {
121195 if (isSimple())
122 return getSimpleNodeLabel(Node, Graph);
196 return getSimpleNodeLabel(Node, CFGInfo);
123197 else
124 return getCompleteNodeLabel(Node, Graph);
198 return getCompleteNodeLabel(Node, CFGInfo);
125199 }
126200
127201 static std::string getEdgeSourceLabel(const BasicBlock *Node,
148222
149223 /// Display the raw branch weights from PGO.
150224 std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
151 const Function *F) {
225 CFGDOTInfo *CFGInfo) {
226
227 if (!CFGInfo->showEdgeWeights())
228 return "";
229
230 const unsigned MaxEdgeWidth = 2;
231
152232 const TerminatorInst *TI = Node->getTerminator();
153233 if (TI->getNumSuccessors() == 1)
234 return "penwidth="+std::to_string(MaxEdgeWidth);
235
236 unsigned OpNo = I.getSuccessorIndex();
237
238 if (OpNo >= TI->getNumSuccessors())
154239 return "";
155240
156 MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
157 if (!WeightsNode)
241 std::string Attrs = "";
242
243 BasicBlock *SuccBB = TI->getSuccessor(OpNo);
244 auto BranchProb = CFGInfo->getBPI()->getEdgeProbability(Node,SuccBB);
245 double WeightPercent = ((double)BranchProb.getNumerator()) /
246 ((double)BranchProb.getDenominator());
247 double Width = 1+(MaxEdgeWidth-1)*WeightPercent;
248
249 if (CFGInfo->useRawEdgeWeights()) {
250 // Prepend a 'W' to indicate that this is a weight rather than the actual
251 // profile count (due to scaling).
252
253 uint64_t Freq = CFGInfo->getFreq(Node);
254 Attrs = formatv("label=\"W:{0}\" penwidth={1}", (uint64_t)(Freq*WeightPercent), Width);
255 if (Attrs.size())
256 return Attrs;
257
258 MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
259 if (!WeightsNode)
260 return Attrs;
261
262 MDString *MDName = cast(WeightsNode->getOperand(0));
263 if (MDName->getString() != "branch_weights")
264 return Attrs;
265
266 unsigned OpNo = I.getSuccessorIndex() + 1;
267 if (OpNo >= WeightsNode->getNumOperands())
268 return Attrs;
269 ConstantInt *Weight =
270 mdconst::dyn_extract(WeightsNode->getOperand(OpNo));
271 if (!Weight)
272 return Attrs;
273
274 Attrs = "label=\"W:" + std::to_string(Weight->getZExtValue()) + "\" penwidth=" + std::to_string(Width);
275 } else {
276 //formatting value to percentage
277 Attrs = formatv("label=\"{0:P}\" penwidth={1}", WeightPercent, Width);
278 }
279 return Attrs;
280 }
281
282 std::string getNodeAttributes(const BasicBlock *Node, CFGDOTInfo *CFGInfo) {
283
284 if (!CFGInfo->showHeatColors())
158285 return "";
159286
160 MDString *MDName = cast(WeightsNode->getOperand(0));
161 if (MDName->getString() != "branch_weights")
162 return "";
163
164 unsigned OpNo = I.getSuccessorIndex() + 1;
165 if (OpNo >= WeightsNode->getNumOperands())
166 return "";
167 ConstantInt *Weight =
168 mdconst::dyn_extract(WeightsNode->getOperand(OpNo));
169 if (!Weight)
170 return "";
171
172 // Prepend a 'W' to indicate that this is a weight rather than the actual
173 // profile count (due to scaling).
174 Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\"";
175 return Attrs.str();
176 }
177 };
178 } // End llvm namespace
287 uint64_t Freq = CFGInfo->getFreq(Node);
288 std::string Color = getHeatColor(Freq, CFGInfo->getMaxFreq());
289 std::string EdgeColor = (Freq <= (CFGInfo->getMaxFreq() / 2))
290 ? (getHeatColor(0))
291 : (getHeatColor(1));
292
293 std::string Attrs = "color=\"" + EdgeColor + "ff\", style=filled,"+
294 "fillcolor=\"" + Color + "70\"";
295 return Attrs;
296 }
297 };
298
299 } // namespace llvm
179300
180301 namespace llvm {
181 class FunctionPass;
182 FunctionPass *createCFGPrinterLegacyPassPass ();
183 FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
184 } // End llvm namespace
302 class ModulePass;
303 ModulePass *createCFGPrinterLegacyPassPass();
304 ModulePass *createCFGOnlyPrinterLegacyPassPass();
305 } // namespace llvm
185306
186307 #endif
0 //===-- HeatUtils.h - Utility for printing heat colors ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utility for printing heat colors based on heuristics or profiling
10 // information.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ANALYSIS_HEATUTILS_H
15 #define LLVM_ANALYSIS_HEATUTILS_H
16
17 #include "llvm/Analysis/BlockFrequencyInfo.h"
18 #include "llvm/IR/BasicBlock.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/IR/CallSite.h"
22
23 #include
24
25 namespace llvm {
26
27 bool hasProfiling(const Module &M);
28
29 uint64_t getBlockFreq(const BasicBlock *BB, const BlockFrequencyInfo *BFI,
30 bool useHeuristic = true);
31
32 uint64_t getNumOfCalls(Function &callerFunction, Function &calledFunction,
33 function_ref LookupBFI,
34 bool useHeuristic = true);
35
36 uint64_t getNumOfCalls(CallSite &callsite,
37 function_ref LookupBFI,
38 bool useHeuristic = true);
39
40 uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI,
41 bool useHeuristic = true);
42
43 uint64_t getMaxFreq(Module &M,
44 function_ref LookupBFI,
45 bool useHeuristic = true);
46
47 std::string getHeatColor(uint64_t freq, uint64_t maxFreq);
48
49 std::string getHeatColor(double percent);
50
51 } // namespace llvm
52
53 #endif
2121 #include "llvm/Support/FileSystem.h"
2222 using namespace llvm;
2323
24 static cl::opt CFGHeatPerFunction("cfg-heat-per-function",
25 cl::init(false), cl::Hidden,
26 cl::desc("Heat CFG per function"));
27
28 static cl::opt ShowHeatColors("cfg-heat-colors", cl::init(true),
29 cl::Hidden,
30 cl::desc("Show heat colors in CFG"));
31
32 static cl::opt UseRawEdgeWeight("cfg-raw-weights", cl::init(false),
33 cl::Hidden,
34 cl::desc("Use raw weights for labels. "
35 "Use percentages as default."));
36
37 static cl::opt ShowEdgeWeight("cfg-weights", cl::init(true), cl::Hidden,
38 cl::desc("Show edges labeled with weights"));
39
40 static void writeHeatCFGToDotFile(Function &F, BlockFrequencyInfo *BFI,
41 BranchProbabilityInfo *BPI, uint64_t MaxFreq,
42 bool UseHeuristic, bool isSimple) {
43 std::string Filename = ("cfg." + F.getName() + ".dot").str();
44 errs() << "Writing '" << Filename << "'...";
45
46 std::error_code EC;
47 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
48
49 CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
50 CFGInfo.setHeuristic(UseHeuristic);
51 CFGInfo.setHeatColors(ShowHeatColors);
52 CFGInfo.setEdgeWeights(ShowEdgeWeight);
53 CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
54
55 if (!EC)
56 WriteGraph(File, &CFGInfo, isSimple);
57 else
58 errs() << " error opening file for writing!";
59 errs() << "\n";
60 }
61
62 static void writeAllCFGsToDotFile(Module &M,
63 function_ref LookupBFI,
64 function_ref LookupBPI,
65 bool isSimple) {
66 bool UseHeuristic = true;
67 uint64_t MaxFreq = 0;
68 if (!CFGHeatPerFunction)
69 MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
70
71 for (auto &F : M) {
72 if (F.isDeclaration()) continue;
73 auto *BFI = LookupBFI(F);
74 auto *BPI = LookupBPI(F);
75 if (CFGHeatPerFunction)
76 MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
77 writeHeatCFGToDotFile(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
78 }
79
80 }
81
82 static void viewHeatCFG(Function &F, BlockFrequencyInfo *BFI,
83 BranchProbabilityInfo *BPI, uint64_t MaxFreq,
84 bool UseHeuristic, bool isSimple) {
85 CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
86 CFGInfo.setHeuristic(UseHeuristic);
87 CFGInfo.setHeatColors(ShowHeatColors);
88 CFGInfo.setEdgeWeights(ShowEdgeWeight);
89 CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
90
91 ViewGraph(&CFGInfo, "cfg." + F.getName(), isSimple);
92 }
93
94 static void viewAllCFGs(Module &M,
95 function_ref LookupBFI,
96 function_ref LookupBPI,
97 bool isSimple) {
98 bool UseHeuristic = true;
99 uint64_t MaxFreq = 0;
100 if (!CFGHeatPerFunction)
101 MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
102
103 for (auto &F : M) {
104 if (F.isDeclaration()) continue;
105 auto *BFI = LookupBFI(F);
106 auto *BPI = LookupBPI(F);
107 if (CFGHeatPerFunction)
108 MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
109 viewHeatCFG(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
110 }
111
112 }
113
24114 namespace {
25 struct CFGViewerLegacyPass : public FunctionPass {
115 struct CFGViewerLegacyPass : public ModulePass {
26116 static char ID; // Pass identifcation, replacement for typeid
27 CFGViewerLegacyPass() : FunctionPass(ID) {
117 CFGViewerLegacyPass() : ModulePass(ID) {
28118 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
29119 }
30120
31 bool runOnFunction(Function &F) override {
32 F.viewCFG();
121 bool runOnModule(Module &M) override {
122 auto LookupBFI = [this](Function &F) {
123 return &this->getAnalysis(F).getBFI();
124 };
125 auto LookupBPI = [this](Function &F) {
126 return &this->getAnalysis(F).getBPI();
127 };
128 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
33129 return false;
34130 }
35131
36 void print(raw_ostream &OS, const Module* = nullptr) const override {}
132 void print(raw_ostream &OS, const Module * = nullptr) const override {}
37133
38134 void getAnalysisUsage(AnalysisUsage &AU) const override {
135 ModulePass::getAnalysisUsage(AU);
136 AU.addRequired();
137 AU.addRequired();
39138 AU.setPreservesAll();
40139 }
140
41141 };
42142 }
43143
44144 char CFGViewerLegacyPass::ID = 0;
45145 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
46146
47 PreservedAnalyses CFGViewerPass::run(Function &F,
48 FunctionAnalysisManager &AM) {
49 F.viewCFG();
147 PreservedAnalyses CFGViewerPass::run(Module &M,
148 ModuleAnalysisManager &AM) {
149 auto &FAM = AM.getResult(M).getManager();
150 auto LookupBFI = [&FAM](Function &F) {
151 return &FAM.getResult(F);
152 };
153 auto LookupBPI = [&FAM](Function &F) {
154 return &FAM.getResult(F);
155 };
156 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
50157 return PreservedAnalyses::all();
51158 }
52159
53160
54161 namespace {
55 struct CFGOnlyViewerLegacyPass : public FunctionPass {
162 struct CFGOnlyViewerLegacyPass : public ModulePass {
56163 static char ID; // Pass identifcation, replacement for typeid
57 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
164 CFGOnlyViewerLegacyPass() : ModulePass(ID) {
58165 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
59166 }
60167
61 bool runOnFunction(Function &F) override {
62 F.viewCFGOnly();
168 bool runOnModule(Module &M) override {
169 auto LookupBFI = [this](Function &F) {
170 return &this->getAnalysis(F).getBFI();
171 };
172 auto LookupBPI = [this](Function &F) {
173 return &this->getAnalysis(F).getBPI();
174 };
175 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
63176 return false;
64177 }
65178
66 void print(raw_ostream &OS, const Module* = nullptr) const override {}
179 void print(raw_ostream &OS, const Module * = nullptr) const override {}
67180
68181 void getAnalysisUsage(AnalysisUsage &AU) const override {
182 ModulePass::getAnalysisUsage(AU);
183 AU.addRequired();
184 AU.addRequired();
69185 AU.setPreservesAll();
70186 }
187
71188 };
72189 }
73190
75192 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
76193 "View CFG of function (with no function bodies)", false, true)
77194
78 PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
79 FunctionAnalysisManager &AM) {
80 F.viewCFGOnly();
195 PreservedAnalyses CFGOnlyViewerPass::run(Module &M,
196 ModuleAnalysisManager &AM) {
197 auto &FAM = AM.getResult(M).getManager();
198 auto LookupBFI = [&FAM](Function &F) {
199 return &FAM.getResult(F);
200 };
201 auto LookupBPI = [&FAM](Function &F) {
202 return &FAM.getResult(F);
203 };
204 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
81205 return PreservedAnalyses::all();
82206 }
83207
84 static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
85 std::string Filename = ("cfg." + F.getName() + ".dot").str();
86 errs() << "Writing '" << Filename << "'...";
87
88 std::error_code EC;
89 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
90
91 if (!EC)
92 WriteGraph(File, (const Function*)&F, CFGOnly);
93 else
94 errs() << " error opening file for writing!";
95 errs() << "\n";
96 }
97
98208 namespace {
99 struct CFGPrinterLegacyPass : public FunctionPass {
209 struct CFGPrinterLegacyPass : public ModulePass {
100210 static char ID; // Pass identification, replacement for typeid
101 CFGPrinterLegacyPass() : FunctionPass(ID) {
211 CFGPrinterLegacyPass() : ModulePass(ID) {
102212 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
103213 }
104214
105 bool runOnFunction(Function &F) override {
106 writeCFGToDotFile(F);
215 bool runOnModule(Module &M) override {
216 auto LookupBFI = [this](Function &F) {
217 return &this->getAnalysis(F).getBFI();
218 };
219 auto LookupBPI = [this](Function &F) {
220 return &this->getAnalysis(F).getBPI();
221 };
222 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
107223 return false;
108224 }
109225
110 void print(raw_ostream &OS, const Module* = nullptr) const override {}
226 void print(raw_ostream &OS, const Module * = nullptr) const override {}
111227
112228 void getAnalysisUsage(AnalysisUsage &AU) const override {
229 ModulePass::getAnalysisUsage(AU);
230 AU.addRequired();
231 AU.addRequired();
113232 AU.setPreservesAll();
114233 }
234
115235 };
116236 }
117237
119239 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
120240 false, true)
121241
122 PreservedAnalyses CFGPrinterPass::run(Function &F,
123 FunctionAnalysisManager &AM) {
124 writeCFGToDotFile(F);
242 PreservedAnalyses CFGPrinterPass::run(Module &M,
243 ModuleAnalysisManager &AM) {
244 auto &FAM = AM.getResult(M).getManager();
245 auto LookupBFI = [&FAM](Function &F) {
246 return &FAM.getResult(F);
247 };
248 auto LookupBPI = [&FAM](Function &F) {
249 return &FAM.getResult(F);
250 };
251 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
125252 return PreservedAnalyses::all();
126253 }
127254
128255 namespace {
129 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
256 struct CFGOnlyPrinterLegacyPass : public ModulePass {
130257 static char ID; // Pass identification, replacement for typeid
131 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
258 CFGOnlyPrinterLegacyPass() : ModulePass(ID) {
132259 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
133260 }
134261
135 bool runOnFunction(Function &F) override {
136 writeCFGToDotFile(F, /*CFGOnly=*/true);
262 bool runOnModule(Module &M) override {
263 auto LookupBFI = [this](Function &F) {
264 return &this->getAnalysis(F).getBFI();
265 };
266 auto LookupBPI = [this](Function &F) {
267 return &this->getAnalysis(F).getBPI();
268 };
269 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
137270 return false;
138271 }
139 void print(raw_ostream &OS, const Module* = nullptr) const override {}
272
273 void print(raw_ostream &OS, const Module * = nullptr) const override {}
140274
141275 void getAnalysisUsage(AnalysisUsage &AU) const override {
276 ModulePass::getAnalysisUsage(AU);
277 AU.addRequired();
278 AU.addRequired();
142279 AU.setPreservesAll();
143280 }
281
144282 };
145283 }
146284
149287 "Print CFG of function to 'dot' file (with no function bodies)",
150288 false, true)
151289
152 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
153 FunctionAnalysisManager &AM) {
154 writeCFGToDotFile(F, /*CFGOnly=*/true);
290 PreservedAnalyses CFGOnlyPrinterPass::run(Module &M,
291 ModuleAnalysisManager &AM) {
292 auto &FAM = AM.getResult(M).getManager();
293 auto LookupBFI = [&FAM](Function &F) {
294 return &FAM.getResult(F);
295 };
296 auto LookupBPI = [&FAM](Function &F) {
297 return &FAM.getResult(F);
298 };
299 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
155300 return PreservedAnalyses::all();
156301 }
157302
161306 /// being a 'dot' and 'gv' program in your path.
162307 ///
163308 void Function::viewCFG() const {
164 ViewGraph(this, "cfg" + getName());
309
310 CFGDOTInfo CFGInfo(this);
311 ViewGraph(&CFGInfo, "cfg" + getName());
165312 }
166313
167314 /// viewCFGOnly - This function is meant for use from the debugger. It works
170317 /// this can make the graph smaller.
171318 ///
172319 void Function::viewCFGOnly() const {
173 ViewGraph(this, "cfg" + getName(), true);
174 }
175
176 FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
320
321 CFGDOTInfo CFGInfo(this);
322 ViewGraph(&CFGInfo, "cfg" + getName(), true);
323 }
324
325 ModulePass *llvm::createCFGPrinterLegacyPassPass() {
177326 return new CFGPrinterLegacyPass();
178327 }
179328
180 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
329 ModulePass *llvm::createCFGOnlyPrinterLegacyPassPass() {
181330 return new CFGOnlyPrinterLegacyPass();
182331 }
183
99 BlockFrequencyInfoImpl.cpp
1010 BranchProbabilityInfo.cpp
1111 CFG.cpp
12 HeatUtils.cpp
1213 CFGPrinter.cpp
1314 CFLAndersAliasAnalysis.cpp
1415 CFLSteensAliasAnalysis.cpp
1414 //===----------------------------------------------------------------------===//
1515
1616 #include "llvm/Analysis/CallPrinter.h"
17
18 #include "llvm/Analysis/BlockFrequencyInfo.h"
19 #include "llvm/Analysis/BranchProbabilityInfo.h"
1720 #include "llvm/Analysis/CallGraph.h"
1821 #include "llvm/Analysis/DOTGraphTraitsPass.h"
22 #include "llvm/Analysis/HeatUtils.h"
23
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/SmallSet.h"
1926
2027 using namespace llvm;
2128
29 static cl::opt ShowHeatColors("callgraph-heat-colors", cl::init(true),
30 cl::Hidden,
31 cl::desc("Show heat colors in call-graph"));
32
33 static cl::opt
34 EstimateEdgeWeight("callgraph-weights", cl::init(false), cl::Hidden,
35 cl::desc("Show edges labeled with weights"));
36
37 static cl::opt
38 FullCallGraph("callgraph-full", cl::init(false), cl::Hidden,
39 cl::desc("Show full call-graph (including external nodes)"));
40
41 static cl::opt UseCallCounter(
42 "callgraph-call-count", cl::init(false), cl::Hidden,
43 cl::desc("Use function's call counter as a heat metric. "
44 "The default is the function's maximum block frequency."));
45
2246 namespace llvm {
2347
24 template <> struct DOTGraphTraits : public DefaultDOTGraphTraits {
48 class CallGraphDOTInfo {
49 private:
50 Module *M;
51 CallGraph *CG;
52 DenseMap Freq;
53 uint64_t MaxFreq;
54 uint64_t MaxEdgeCount;
55
56 public:
57 std::function LookupBFI;
58
59 CallGraphDOTInfo(Module *M, CallGraph *CG,
60 function_ref LookupBFI)
61 : M(M), CG(CG), LookupBFI(LookupBFI) {
62 MaxFreq = 0;
63 MaxEdgeCount = 0;
64
65 for (Function &F : *M) {
66 Freq[&F] = 0;
67
68 if (FullCallGraph) {
69 for (User *U : F.users()) {
70 auto CS = CallSite(U);
71 if (!CS.getCaller()->isDeclaration()) {
72 uint64_t Counter = getNumOfCalls(CS, LookupBFI);
73 if (Counter > MaxEdgeCount) {
74 MaxEdgeCount = Counter;
75 }
76 }
77 }
78 }
79
80 if (F.isDeclaration())
81 continue;
82 uint64_t localMaxFreq = 0;
83 if (UseCallCounter) {
84 Function::ProfileCount EntryCount = F.getEntryCount();
85 if (EntryCount.hasValue())
86 localMaxFreq = EntryCount.getCount();
87 } else {
88 localMaxFreq = llvm::getMaxFreq(F, LookupBFI(F));
89 }
90 if (localMaxFreq >= MaxFreq)
91 MaxFreq = localMaxFreq;
92 Freq[&F] = localMaxFreq;
93
94 if (!FullCallGraph) {
95 for (Function &Callee : *M) {
96 uint64_t Counter = getNumOfCalls(F, Callee, LookupBFI);
97 if (Counter > MaxEdgeCount) {
98 MaxEdgeCount = Counter;
99 }
100 }
101 }
102 }
103 if (!FullCallGraph)
104 removeParallelEdges();
105 }
106
107 Module *getModule() const { return M; }
108 CallGraph *getCallGraph() const { return CG; }
109
110 uint64_t getFreq(const Function *F) { return Freq[F]; }
111
112 uint64_t getMaxFreq() { return MaxFreq; }
113
114 uint64_t getMaxEdgeCount() { return MaxEdgeCount; }
115
116 private:
117 void removeParallelEdges() {
118 for (auto &I : (*CG)) {
119 CallGraphNode *Node = I.second.get();
120
121 bool FoundParallelEdge = true;
122 while (FoundParallelEdge) {
123 SmallSet Visited;
124 FoundParallelEdge = false;
125 for (auto CI = Node->begin(), CE = Node->end(); CI != CE; CI++) {
126 if (!Visited.count(CI->second->getFunction()))
127 Visited.insert(CI->second->getFunction());
128 else {
129 FoundParallelEdge = true;
130 Node->removeCallEdge(CI);
131 break;
132 }
133 }
134 }
135 }
136 }
137 };
138
139 template <>
140 struct GraphTraits
141 : public GraphTraits {
142 static NodeRef getEntryNode(CallGraphDOTInfo *CGInfo) {
143 // Start at the external node!
144 return CGInfo->getCallGraph()->getExternalCallingNode();
145 }
146
147 typedef std::pair>
148 PairTy;
149 static const CallGraphNode *CGGetValuePtr(const PairTy &P) {
150 return P.second.get();
151 }
152
153 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
154 typedef mapped_iterator
155 nodes_iterator;
156
157 static nodes_iterator nodes_begin(CallGraphDOTInfo *CGInfo) {
158 return nodes_iterator(CGInfo->getCallGraph()->begin(), &CGGetValuePtr);
159 }
160 static nodes_iterator nodes_end(CallGraphDOTInfo *CGInfo) {
161 return nodes_iterator(CGInfo->getCallGraph()->end(), &CGGetValuePtr);
162 }
163 };
164
165 template <>
166 struct DOTGraphTraits : public DefaultDOTGraphTraits {
167
168 SmallSet VisitedCallSites;
169
25170 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
26171
27 static std::string getGraphName(CallGraph *Graph) { return "Call graph"; }
28
29 std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) {
172 static std::string getGraphName(CallGraphDOTInfo *CGInfo) {
173 return "Call graph: " +
174 std::string(CGInfo->getModule()->getModuleIdentifier());
175 }
176
177 static bool isNodeHidden(const CallGraphNode *Node) {
178 if (FullCallGraph)
179 return false;
180
181 if (Node->getFunction())
182 return false;
183
184 return true;
185 }
186
187 std::string getNodeLabel(const CallGraphNode *Node,
188 CallGraphDOTInfo *CGInfo) {
189 if (Node == CGInfo->getCallGraph()->getExternalCallingNode())
190 return "external caller";
191
192 if (Node == CGInfo->getCallGraph()->getCallsExternalNode())
193 return "external callee";
194
30195 if (Function *Func = Node->getFunction())
31196 return Func->getName();
32197
33198 return "external node";
34199 }
35 };
36
37 struct AnalysisCallGraphWrapperPassTraits {
38 static CallGraph *getGraph(CallGraphWrapperPass *P) {
39 return &P->getCallGraph();
40 }
41 };
42
43 } // end llvm namespace
200
201 static const CallGraphNode *CGGetValuePtr(CallGraphNode::CallRecord P) {
202 return P.second;
203 }
204
205 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
206 typedef mapped_iterator
207 decltype(&CGGetValuePtr)>
208 nodes_iterator;
209
210 std::string getEdgeAttributes(const CallGraphNode *Node, nodes_iterator I,
211 CallGraphDOTInfo *CGInfo) {
212 if (!EstimateEdgeWeight)
213 return "";
214
215 Function *Caller = Node->getFunction();
216 if (Caller == nullptr || Caller->isDeclaration())
217 return "";
218
219 Function *Callee = (*I)->getFunction();
220 if (Callee == nullptr)
221 return "";
222
223 uint64_t Counter = 0;
224 if (FullCallGraph) {
225 // looks for next call site between Caller and Callee
226 for (User *U : Callee->users()) {
227 auto CS = CallSite(U);
228 if (CS.getCaller() == Caller) {
229 if (VisitedCallSites.count(U))
230 continue;
231 VisitedCallSites.insert(U);
232 Counter = getNumOfCalls(CS, CGInfo->LookupBFI);
233 break;
234 }
235 }
236 } else {
237 Counter = getNumOfCalls(*Caller, *Callee, CGInfo->LookupBFI);
238 }
239
240 const unsigned MaxEdgeWidth = 3;
241
242 double Width =
243 1 + (MaxEdgeWidth - 1) * (double(Counter) / CGInfo->getMaxEdgeCount());
244 std::string Attrs = "label=\"" + std::to_string(Counter) +
245 "\" penwidth=" + std::to_string(Width);
246
247 return Attrs;
248 }
249
250 std::string getNodeAttributes(const CallGraphNode *Node,
251 CallGraphDOTInfo *CGInfo) {
252 Function *F = Node->getFunction();
253 if (F == nullptr || F->isDeclaration())
254 return "";
255
256 std::string attrs = "";
257 if (ShowHeatColors) {
258 uint64_t freq = CGInfo->getFreq(F);
259 std::string color = getHeatColor(freq, CGInfo->getMaxFreq());
260 std::string edgeColor = (freq <= (CGInfo->getMaxFreq() / 2))
261 ? getHeatColor(0)
262 : getHeatColor(1);
263
264 attrs = "color=\"" + edgeColor + "ff\", style=filled, fillcolor=\"" +
265 color + "80\"";
266 }
267 return attrs;
268 }
269 };
270
271 } // namespace llvm
44272
45273 namespace {
46274
47 struct CallGraphViewer
48 : public DOTGraphTraitsModuleViewer
49 AnalysisCallGraphWrapperPassTraits> {
275 // Viewer
276
277 class CallGraphViewer : public ModulePass {
278 public:
50279 static char ID;
51
52 CallGraphViewer()
53 : DOTGraphTraitsModuleViewer
54 AnalysisCallGraphWrapperPassTraits>(
55 "callgraph", ID) {
56 initializeCallGraphViewerPass(*PassRegistry::getPassRegistry());
57 }
58 };
59
60 struct CallGraphDOTPrinter : public DOTGraphTraitsModulePrinter<
61 CallGraphWrapperPass, true, CallGraph *,
62 AnalysisCallGraphWrapperPassTraits> {
280 CallGraphViewer() : ModulePass(ID) {}
281
282 void getAnalysisUsage(AnalysisUsage &AU) const override;
283 bool runOnModule(Module &M) override;
284 };
285
286 void CallGraphViewer::getAnalysisUsage(AnalysisUsage &AU) const {
287 ModulePass::getAnalysisUsage(AU);
288 AU.addRequired();
289 AU.setPreservesAll();
290 }
291
292 bool CallGraphViewer::runOnModule(Module &M) {
293 auto LookupBFI = [this](Function &F) {
294 return &this->getAnalysis(F).getBFI();
295 };
296
297 CallGraph CG(M);
298 CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
299
300 std::string Title =
301 DOTGraphTraits::getGraphName(&CFGInfo);
302 ViewGraph(&CFGInfo, "callgraph", true, Title);
303
304 return false;
305 }
306
307 // DOT Printer
308
309 class CallGraphDOTPrinter : public ModulePass {
310 public:
63311 static char ID;
64
65 CallGraphDOTPrinter()
66 : DOTGraphTraitsModulePrinter
67 AnalysisCallGraphWrapperPassTraits>(
68 "callgraph", ID) {
69 initializeCallGraphDOTPrinterPass(*PassRegistry::getPassRegistry());
70 }
71 };
312 CallGraphDOTPrinter() : ModulePass(ID) {}
313
314 void getAnalysisUsage(AnalysisUsage &AU) const override;
315 bool runOnModule(Module &M) override;
316 };
317
318 void CallGraphDOTPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
319 ModulePass::getAnalysisUsage(AU);
320 AU.addRequired();
321 AU.setPreservesAll();
322 }
323
324 bool CallGraphDOTPrinter::runOnModule(Module &M) {
325 auto LookupBFI = [this](Function &F) {
326 return &this->getAnalysis(F).getBFI();
327 };
328
329 std::string Filename =
330 (std::string(M.getModuleIdentifier()) + ".callgraph.dot");
331 errs() << "Writing '" << Filename << "'...";
332
333 std::error_code EC;
334 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
335
336 CallGraph CG(M);
337 CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
338
339 if (!EC)
340 WriteGraph(File, &CFGInfo);
341 else
342 errs() << " error opening file for writing!";
343 errs() << "\n";
344
345 return false;
346 }
72347
73348 } // end anonymous namespace
74349
3737 if (!BB)
3838 return "Post dominance root node";
3939
40
4140 if (isSimple())
42 return DOTGraphTraits
43 ::getSimpleNodeLabel(BB, BB->getParent());
41 return DOTGraphTraits
42 ::getSimpleNodeLabel(BB, nullptr);
4443 else
45 return DOTGraphTraits
46 ::getCompleteNodeLabel(BB, BB->getParent());
44 return DOTGraphTraits
45 ::getCompleteNodeLabel(BB, nullptr);
4746 }
4847 };
4948
0 //===-- HeatUtils.cpp - Utility for printing heat colors --------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utility for printing heat colors based on heuristics or profiling
10 // information.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Analysis/HeatUtils.h"
15 #include "llvm/IR/Instructions.h"
16
17 namespace llvm {
18
19 static const unsigned heatSize = 100;
20 static const std::string heatPalette[heatSize] = {
21 "#3d50c3", "#4055c8", "#4358cb", "#465ecf", "#4961d2", "#4c66d6", "#4f69d9",
22 "#536edd", "#5572df", "#5977e3", "#5b7ae5", "#5f7fe8", "#6282ea", "#6687ed",
23 "#6a8bef", "#6c8ff1", "#7093f3", "#7396f5", "#779af7", "#7a9df8", "#7ea1fa",
24 "#81a4fb", "#85a8fc", "#88abfd", "#8caffe", "#8fb1fe", "#93b5fe", "#96b7ff",
25 "#9abbff", "#9ebeff", "#a1c0ff", "#a5c3fe", "#a7c5fe", "#abc8fd", "#aec9fc",
26 "#b2ccfb", "#b5cdfa", "#b9d0f9", "#bbd1f8", "#bfd3f6", "#c1d4f4", "#c5d6f2",
27 "#c7d7f0", "#cbd8ee", "#cedaeb", "#d1dae9", "#d4dbe6", "#d6dce4", "#d9dce1",
28 "#dbdcde", "#dedcdb", "#e0dbd8", "#e3d9d3", "#e5d8d1", "#e8d6cc", "#ead5c9",
29 "#ecd3c5", "#eed0c0", "#efcebd", "#f1ccb8", "#f2cab5", "#f3c7b1", "#f4c5ad",
30 "#f5c1a9", "#f6bfa6", "#f7bca1", "#f7b99e", "#f7b599", "#f7b396", "#f7af91",
31 "#f7ac8e", "#f7a889", "#f6a385", "#f5a081", "#f59c7d", "#f4987a", "#f39475",
32 "#f29072", "#f08b6e", "#ef886b", "#ed8366", "#ec7f63", "#e97a5f", "#e8765c",
33 "#e57058", "#e36c55", "#e16751", "#de614d", "#dc5d4a", "#d85646", "#d65244",
34 "#d24b40", "#d0473d", "#cc403a", "#ca3b37", "#c53334", "#c32e31", "#be242e",
35 "#bb1b2c", "#b70d28"};
36
37 bool hasProfiling(const Module &M) {
38 for (auto &F : M) {
39 for (auto &BB : F) {
40 auto *TI = BB.getTerminator();
41 if (TI == nullptr)
42 continue;
43 if (TI->getMetadata(llvm::LLVMContext::MD_prof) != nullptr)
44 return true;
45 }
46 }
47 return false;
48 }
49
50 uint64_t getBlockFreq(const BasicBlock *BB, const BlockFrequencyInfo *BFI,
51 bool useHeuristic) {
52 uint64_t freqVal = 0;
53 if (!useHeuristic) {
54 Optional freq = BFI->getBlockProfileCount(BB);
55 if (freq.hasValue())
56 freqVal = freq.getValue();
57 } else {
58 freqVal = BFI->getBlockFreq(BB).getFrequency();
59 }
60 return freqVal;
61 }
62
63 uint64_t getNumOfCalls(CallSite &CS,
64 function_ref LookupBFI,
65 bool useHeuristic) {
66 if (CS.getInstruction()==nullptr) return 0;
67 if (CS.getInstruction()->getParent()==nullptr) return 0;
68 BasicBlock *BB = CS.getInstruction()->getParent();
69 return getBlockFreq(BB, LookupBFI(*CS.getCaller()));
70 }
71
72 uint64_t getNumOfCalls(Function &callerFunction, Function &calledFunction,
73 function_ref LookupBFI,
74 bool useHeuristic) {
75 uint64_t counter = 0;
76 for (User *U : calledFunction.users()) {
77 if (isa(U)) {
78 auto CS = CallSite(U);
79 if (CS.getCaller() == (&callerFunction)) {
80 counter += getNumOfCalls(CS, LookupBFI);
81 }
82 }
83 }
84 return counter;
85 }
86
87 uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI,
88 bool useHeuristic) {
89 uint64_t maxFreq = 0;
90 for (const BasicBlock &BB : F) {
91 uint64_t freqVal = getBlockFreq(&BB, BFI, useHeuristic);
92 if (freqVal >= maxFreq)
93 maxFreq = freqVal;
94 }
95 return maxFreq;
96 }
97
98 uint64_t getMaxFreq(Module &M,
99 function_ref LookupBFI,
100 bool useHeuristic) {
101 uint64_t maxFreq = 0;
102 for (auto &F : M) {
103 if (F.isDeclaration())
104 continue;
105 uint64_t localMaxFreq = getMaxFreq(F, LookupBFI(F), useHeuristic);
106 if (localMaxFreq >= maxFreq)
107 maxFreq = localMaxFreq;
108 }
109 return maxFreq;
110 }
111
112 std::string getHeatColor(uint64_t freq, uint64_t maxFreq) {
113 if (freq > maxFreq)
114 freq = maxFreq;
115 unsigned colorId =
116 unsigned(round((double(freq) / maxFreq) * (heatSize - 1.0)));
117 return heatPalette[colorId];
118 }
119
120 std::string getHeatColor(double percent) {
121 if (percent > 1.0)
122 percent = 1.0;
123 if (percent < 0.0)
124 percent = 0.0;
125 unsigned colorId = unsigned(round(percent * (heatSize - 1.0)));
126 return heatPalette[colorId];
127 }
128
129 } // namespace llvm
4646 BasicBlock *BB = Node->getNodeAs();
4747
4848 if (isSimple())
49 return DOTGraphTraits
50 ::getSimpleNodeLabel(BB, BB->getParent());
49 return DOTGraphTraits
50 ::getSimpleNodeLabel(BB, nullptr);
5151 else
52 return DOTGraphTraits
53 ::getCompleteNodeLabel(BB, BB->getParent());
52 return DOTGraphTraits
53 ::getCompleteNodeLabel(BB, nullptr);
5454 }
5555
5656 return "Not implemented";
4242 MODULE_PASS("constmerge", ConstantMergePass())
4343 MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
4444 MODULE_PASS("deadargelim", DeadArgumentEliminationPass())
45 MODULE_PASS("dot-cfg", CFGPrinterPass())
46 MODULE_PASS("dot-cfg-only", CFGOnlyPrinterPass())
4547 MODULE_PASS("elim-avail-extern", EliminateAvailableExternallyPass())
4648 MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
4749 MODULE_PASS("function-import", FunctionImportPass())
7577 MODULE_PASS("synthetic-counts-propagation", SyntheticCountsPropagation())
7678 MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
7779 MODULE_PASS("verify", VerifierPass())
80 MODULE_PASS("view-cfg", CFGViewerPass())
81 MODULE_PASS("view-cfg-only", CFGOnlyViewerPass())
7882 #undef MODULE_PASS
7983
8084 #ifndef CGSCC_ANALYSIS
150154 FUNCTION_PASS("dce", DCEPass())
151155 FUNCTION_PASS("div-rem-pairs", DivRemPairsPass())
152156 FUNCTION_PASS("dse", DSEPass())
153 FUNCTION_PASS("dot-cfg", CFGPrinterPass())
154 FUNCTION_PASS("dot-cfg-only", CFGOnlyPrinterPass())
155157 FUNCTION_PASS("early-cse", EarlyCSEPass(/*UseMemorySSA=*/false))
156158 FUNCTION_PASS("early-cse-memssa", EarlyCSEPass(/*UseMemorySSA=*/true))
157159 FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/false))
213215 FUNCTION_PASS("verify", LoopVerifierPass())
214216 FUNCTION_PASS("verify", MemorySSAVerifierPass())
215217 FUNCTION_PASS("verify", RegionInfoVerifierPass())
216 FUNCTION_PASS("view-cfg", CFGViewerPass())
217 FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
218218 #undef FUNCTION_PASS
219219
220220 #ifndef LOOP_ANALYSIS
895895
896896 #ifndef NDEBUG
897897 static std::string getBlockName(const BasicBlock *B) {
898 return DOTGraphTraits<const Function *>::getSimpleNodeLabel(B, nullptr);
898 return DOTGraphTraits<CFGDOTInfo *>::getSimpleNodeLabel(B, nullptr);
899899 }
900900 #endif
901901
0 //===-- HeatUtils.h - Utility for printing heat colors ----------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Utility for printing heat colors based on heuristics or profiling
10 // information.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ANALYSIS_HEATUTILS_H
15 #define LLVM_ANALYSIS_HEATUTILS_H
16
17 #include "llvm/Analysis/BlockFrequencyInfo.h"
18 #include "llvm/IR/BasicBlock.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/IR/CallSite.h"
22
23 #include
24
25 namespace llvm {
26
27 bool hasProfiling(const Module &M);
28
29 uint64_t getBlockFreq(const BasicBlock *BB, const BlockFrequencyInfo *BFI,
30 bool useHeuristic = true);
31
32 uint64_t getNumOfCalls(Function &callerFunction, Function &calledFunction,
33 function_ref LookupBFI,
34 bool useHeuristic = true);
35
36 uint64_t getNumOfCalls(CallSite &callsite,
37 function_ref LookupBFI,
38 bool useHeuristic = true);
39
40 uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI,
41 bool useHeuristic = true);
42
43 uint64_t getMaxFreq(Module &M,
44 function_ref LookupBFI,
45 bool useHeuristic = true);
46
47 std::string getHeatColor(uint64_t freq, uint64_t maxFreq);
48
49 std::string getHeatColor(double percent);
50
51 } // namespace llvm
52
53 #endif
0 ;RUN: opt < %s -analyze -dot-cfg-only 2>/dev/null
11 ;RUN: opt < %s -analyze -passes=dot-cfg-only 2>/dev/null
2 ;RUN: opt < %s -analyze -dot-cfg-only \
3 ;RUN: -cfg-heat-colors=true -cfg-weights=true 2>/dev/null
4 ;RUN: opt < %s -analyze -dot-cfg-only \
5 ;RUN: -cfg-heat-colors=false -cfg-weights=false 2>/dev/null
6 ;RUN: opt < %s -analyze -dot-cfg \
7 ;RUN: -cfg-heat-colors=true -cfg-weights=true 2>/dev/null
8 ;RUN: opt < %s -analyze -dot-cfg \
9 ;RUN: -cfg-heat-colors=false -cfg-weights=false 2>/dev/null
210 ;PR 1497
311
412 define void @foo() {