llvm.org GIT mirror llvm / 551913f
Revert "Extend CFGPrinter and CallPrinter with Heat Colors" This reverts r335996 which broke graph printing in Polly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336000 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Fertile 1 year, 2 months ago
12 changed file(s) with 132 addition(s) and 922 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"
2423 #include "llvm/IR/Function.h"
2524 #include "llvm/IR/Instructions.h"
2625 #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"
3126 #include "llvm/Support/GraphWriter.h"
3227
3328 namespace llvm {
3429 class CFGViewerPass
3530 : public PassInfoMixin {
3631 public:
37 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
32 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
3833 };
3934
4035 class CFGOnlyViewerPass
4136 : public PassInfoMixin {
4237 public:
43 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
38 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
4439 };
4540
4641 class CFGPrinterPass
4742 : public PassInfoMixin {
4843 public:
49 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
44 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
5045 };
5146
5247 class CFGOnlyPrinterPass
5348 : public PassInfoMixin {
5449 public:
55 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
50 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
5651 };
5752
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;
53 template<>
54 struct DOTGraphTraits : public DefaultDOTGraphTraits {
6855
69 public:
70 CFGDOTInfo(const Function *F) : CFGDOTInfo(F, nullptr, nullptr, 0) { }
56 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
7157
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;
58 static std::string getGraphName(const Function *F) {
59 return "CFG for '" + F->getName().str() + "' function";
7960 }
8061
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 *) {
62 static std::string getSimpleNodeLabel(const BasicBlock *Node,
63 const Function *) {
13964 if (!Node->getName().empty())
14065 return Node->getName().str();
14166
14772 }
14873
14974 static std::string getCompleteNodeLabel(const BasicBlock *Node,
150 CFGDOTInfo *) {
75 const Function *) {
15176 enum { MaxColumns = 80 };
15277 std::string Str;
15378 raw_string_ostream OS(Str);
191116 return OutStr;
192117 }
193118
194 std::string getNodeLabel(const BasicBlock *Node, CFGDOTInfo *CFGInfo) {
119 std::string getNodeLabel(const BasicBlock *Node,
120 const Function *Graph) {
195121 if (isSimple())
196 return getSimpleNodeLabel(Node, CFGInfo);
122 return getSimpleNodeLabel(Node, Graph);
197123 else
198 return getCompleteNodeLabel(Node, CFGInfo);
124 return getCompleteNodeLabel(Node, Graph);
199125 }
200126
201127 static std::string getEdgeSourceLabel(const BasicBlock *Node,
222148
223149 /// Display the raw branch weights from PGO.
224150 std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
225 CFGDOTInfo *CFGInfo) {
226
227 if (!CFGInfo->showEdgeWeights())
151 const Function *F) {
152 const TerminatorInst *TI = Node->getTerminator();
153 if (TI->getNumSuccessors() == 1)
228154 return "";
229155
230 const unsigned MaxEdgeWidth = 2;
231
232 const TerminatorInst *TI = Node->getTerminator();
233 if (TI->getNumSuccessors() == 1)
234 return "penwidth="+std::to_string(MaxEdgeWidth);
235
236 unsigned OpNo = I.getSuccessorIndex();
237
238 if (OpNo >= TI->getNumSuccessors())
156 MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
157 if (!WeightsNode)
239158 return "";
240159
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())
160 MDString *MDName = cast(WeightsNode->getOperand(0));
161 if (MDName->getString() != "branch_weights")
285162 return "";
286163
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));
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 "";
292171
293 std::string Attrs = "color=\"" + EdgeColor + "ff\", style=filled,"+
294 "fillcolor=\"" + Color + "70\"";
295 return Attrs;
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();
296176 }
297177 };
298
299 } // namespace llvm
178 } // End llvm namespace
300179
301180 namespace llvm {
302 class ModulePass;
303 ModulePass *createCFGPrinterLegacyPassPass();
304 ModulePass *createCFGOnlyPrinterLegacyPassPass();
305 } // namespace llvm
181 class FunctionPass;
182 FunctionPass *createCFGPrinterLegacyPassPass ();
183 FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
184 } // End llvm namespace
306185
307186 #endif
+0
-54
include/llvm/Analysis/HeatUtils.h less more
None //===-- 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
11424 namespace {
115 struct CFGViewerLegacyPass : public ModulePass {
25 struct CFGViewerLegacyPass : public FunctionPass {
11626 static char ID; // Pass identifcation, replacement for typeid
117 CFGViewerLegacyPass() : ModulePass(ID) {
27 CFGViewerLegacyPass() : FunctionPass(ID) {
11828 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
11929 }
12030
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);
31 bool runOnFunction(Function &F) override {
32 F.viewCFG();
12933 return false;
13034 }
13135
132 void print(raw_ostream &OS, const Module * = nullptr) const override {}
36 void print(raw_ostream &OS, const Module* = nullptr) const override {}
13337
13438 void getAnalysisUsage(AnalysisUsage &AU) const override {
135 ModulePass::getAnalysisUsage(AU);
136 AU.addRequired();
137 AU.addRequired();
13839 AU.setPreservesAll();
13940 }
140
14141 };
14242 }
14343
14444 char CFGViewerLegacyPass::ID = 0;
14545 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
14646
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);
47 PreservedAnalyses CFGViewerPass::run(Function &F,
48 FunctionAnalysisManager &AM) {
49 F.viewCFG();
15750 return PreservedAnalyses::all();
15851 }
15952
16053
16154 namespace {
162 struct CFGOnlyViewerLegacyPass : public ModulePass {
55 struct CFGOnlyViewerLegacyPass : public FunctionPass {
16356 static char ID; // Pass identifcation, replacement for typeid
164 CFGOnlyViewerLegacyPass() : ModulePass(ID) {
57 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
16558 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
16659 }
16760
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);
61 bool runOnFunction(Function &F) override {
62 F.viewCFGOnly();
17663 return false;
17764 }
17865
179 void print(raw_ostream &OS, const Module * = nullptr) const override {}
66 void print(raw_ostream &OS, const Module* = nullptr) const override {}
18067
18168 void getAnalysisUsage(AnalysisUsage &AU) const override {
182 ModulePass::getAnalysisUsage(AU);
183 AU.addRequired();
184 AU.addRequired();
18569 AU.setPreservesAll();
18670 }
187
18871 };
18972 }
19073
19275 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
19376 "View CFG of function (with no function bodies)", false, true)
19477
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);
78 PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
79 FunctionAnalysisManager &AM) {
80 F.viewCFGOnly();
20581 return PreservedAnalyses::all();
20682 }
20783
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
20898 namespace {
209 struct CFGPrinterLegacyPass : public ModulePass {
99 struct CFGPrinterLegacyPass : public FunctionPass {
210100 static char ID; // Pass identification, replacement for typeid
211 CFGPrinterLegacyPass() : ModulePass(ID) {
101 CFGPrinterLegacyPass() : FunctionPass(ID) {
212102 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
213103 }
214104
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);
105 bool runOnFunction(Function &F) override {
106 writeCFGToDotFile(F);
223107 return false;
224108 }
225109
226 void print(raw_ostream &OS, const Module * = nullptr) const override {}
110 void print(raw_ostream &OS, const Module* = nullptr) const override {}
227111
228112 void getAnalysisUsage(AnalysisUsage &AU) const override {
229 ModulePass::getAnalysisUsage(AU);
230 AU.addRequired();
231 AU.addRequired();
232113 AU.setPreservesAll();
233114 }
234
235115 };
236116 }
237117
239119 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
240120 false, true)
241121
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);
122 PreservedAnalyses CFGPrinterPass::run(Function &F,
123 FunctionAnalysisManager &AM) {
124 writeCFGToDotFile(F);
252125 return PreservedAnalyses::all();
253126 }
254127
255128 namespace {
256 struct CFGOnlyPrinterLegacyPass : public ModulePass {
129 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
257130 static char ID; // Pass identification, replacement for typeid
258 CFGOnlyPrinterLegacyPass() : ModulePass(ID) {
131 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
259132 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
260133 }
261134
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);
135 bool runOnFunction(Function &F) override {
136 writeCFGToDotFile(F, /*CFGOnly=*/true);
270137 return false;
271138 }
272
273 void print(raw_ostream &OS, const Module * = nullptr) const override {}
139 void print(raw_ostream &OS, const Module* = nullptr) const override {}
274140
275141 void getAnalysisUsage(AnalysisUsage &AU) const override {
276 ModulePass::getAnalysisUsage(AU);
277 AU.addRequired();
278 AU.addRequired();
279142 AU.setPreservesAll();
280143 }
281
282144 };
283145 }
284146
287149 "Print CFG of function to 'dot' file (with no function bodies)",
288150 false, true)
289151
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);
152 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
153 FunctionAnalysisManager &AM) {
154 writeCFGToDotFile(F, /*CFGOnly=*/true);
300155 return PreservedAnalyses::all();
301156 }
302157
306161 /// being a 'dot' and 'gv' program in your path.
307162 ///
308163 void Function::viewCFG() const {
309
310 CFGDOTInfo CFGInfo(this);
311 ViewGraph(&CFGInfo, "cfg" + getName());
164 ViewGraph(this, "cfg" + getName());
312165 }
313166
314167 /// viewCFGOnly - This function is meant for use from the debugger. It works
317170 /// this can make the graph smaller.
318171 ///
319172 void Function::viewCFGOnly() const {
320
321 CFGDOTInfo CFGInfo(this);
322 ViewGraph(&CFGInfo, "cfg" + getName(), true);
173 ViewGraph(this, "cfg" + getName(), true);
323174 }
324175
325 ModulePass *llvm::createCFGPrinterLegacyPassPass() {
176 FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
326177 return new CFGPrinterLegacyPass();
327178 }
328179
329 ModulePass *llvm::createCFGOnlyPrinterLegacyPassPass() {
180 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
330181 return new CFGOnlyPrinterLegacyPass();
331182 }
183
99 BlockFrequencyInfoImpl.cpp
1010 BranchProbabilityInfo.cpp
1111 CFG.cpp
12 HeatUtils.cpp
1312 CFGPrinter.cpp
1413 CFLAndersAliasAnalysis.cpp
1514 CFLSteensAliasAnalysis.cpp
1414 //===----------------------------------------------------------------------===//
1515
1616 #include "llvm/Analysis/CallPrinter.h"
17
18 #include "llvm/Analysis/BlockFrequencyInfo.h"
19 #include "llvm/Analysis/BranchProbabilityInfo.h"
2017 #include "llvm/Analysis/CallGraph.h"
2118 #include "llvm/Analysis/DOTGraphTraitsPass.h"
22 #include "llvm/Analysis/HeatUtils.h"
23
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/ADT/SmallSet.h"
2619
2720 using namespace llvm;
2821
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
4622 namespace llvm {
4723
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
24 template <> struct DOTGraphTraits : public DefaultDOTGraphTraits {
17025 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
17126
172 static std::string getGraphName(CallGraphDOTInfo *CGInfo) {
173 return "Call graph: " +
174 std::string(CGInfo->getModule()->getModuleIdentifier());
175 }
27 static std::string getGraphName(CallGraph *Graph) { return "Call graph"; }
17628
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
29 std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) {
19530 if (Function *Func = Node->getFunction())
19631 return Func->getName();
19732
19833 return "external node";
19934 }
35 };
20036
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;
37 struct AnalysisCallGraphWrapperPassTraits {
38 static CallGraph *getGraph(CallGraphWrapperPass *P) {
39 return &P->getCallGraph();
26840 }
26941 };
27042
271 } // namespace llvm
43 } // end llvm namespace
27244
27345 namespace {
27446
275 // Viewer
47 struct CallGraphViewer
48 : public DOTGraphTraitsModuleViewer
49 AnalysisCallGraphWrapperPassTraits> {
50 static char ID;
27651
277 class CallGraphViewer : public ModulePass {
278 public:
279 static char ID;
280 CallGraphViewer() : ModulePass(ID) {}
281
282 void getAnalysisUsage(AnalysisUsage &AU) const override;
283 bool runOnModule(Module &M) override;
52 CallGraphViewer()
53 : DOTGraphTraitsModuleViewer
54 AnalysisCallGraphWrapperPassTraits>(
55 "callgraph", ID) {
56 initializeCallGraphViewerPass(*PassRegistry::getPassRegistry());
57 }
28458 };
28559
286 void CallGraphViewer::getAnalysisUsage(AnalysisUsage &AU) const {
287 ModulePass::getAnalysisUsage(AU);
288 AU.addRequired();
289 AU.setPreservesAll();
290 }
60 struct CallGraphDOTPrinter : public DOTGraphTraitsModulePrinter<
61 CallGraphWrapperPass, true, CallGraph *,
62 AnalysisCallGraphWrapperPassTraits> {
63 static char ID;
29164
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:
311 static char ID;
312 CallGraphDOTPrinter() : ModulePass(ID) {}
313
314 void getAnalysisUsage(AnalysisUsage &AU) const override;
315 bool runOnModule(Module &M) override;
65 CallGraphDOTPrinter()
66 : DOTGraphTraitsModulePrinter
67 AnalysisCallGraphWrapperPassTraits>(
68 "callgraph", ID) {
69 initializeCallGraphDOTPrinterPass(*PassRegistry::getPassRegistry());
70 }
31671 };
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 }
34772
34873 } // end anonymous namespace
34974
3737 if (!BB)
3838 return "Post dominance root node";
3939
40
4041 if (isSimple())
41 return DOTGraphTraits
42 ::getSimpleNodeLabel(BB, nullptr);
42 return DOTGraphTraits
43 ::getSimpleNodeLabel(BB, BB->getParent());
4344 else
44 return DOTGraphTraits
45 ::getCompleteNodeLabel(BB, nullptr);
45 return DOTGraphTraits
46 ::getCompleteNodeLabel(BB, BB->getParent());
4647 }
4748 };
4849
+0
-130
lib/Analysis/HeatUtils.cpp less more
None //===-- 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, nullptr);
49 return DOTGraphTraits
50 ::getSimpleNodeLabel(BB, BB->getParent());
5151 else
52 return DOTGraphTraits
53 ::getCompleteNodeLabel(BB, nullptr);
52 return DOTGraphTraits
53 ::getCompleteNodeLabel(BB, BB->getParent());
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())
4745 MODULE_PASS("elim-avail-extern", EliminateAvailableExternallyPass())
4846 MODULE_PASS("forceattrs", ForceFunctionAttrsPass())
4947 MODULE_PASS("function-import", FunctionImportPass())
7775 MODULE_PASS("synthetic-counts-propagation", SyntheticCountsPropagation())
7876 MODULE_PASS("wholeprogramdevirt", WholeProgramDevirtPass())
7977 MODULE_PASS("verify", VerifierPass())
80 MODULE_PASS("view-cfg", CFGViewerPass())
81 MODULE_PASS("view-cfg-only", CFGOnlyViewerPass())
8278 #undef MODULE_PASS
8379
8480 #ifndef CGSCC_ANALYSIS
154150 FUNCTION_PASS("dce", DCEPass())
155151 FUNCTION_PASS("div-rem-pairs", DivRemPairsPass())
156152 FUNCTION_PASS("dse", DSEPass())
153 FUNCTION_PASS("dot-cfg", CFGPrinterPass())
154 FUNCTION_PASS("dot-cfg-only", CFGOnlyPrinterPass())
157155 FUNCTION_PASS("early-cse", EarlyCSEPass(/*UseMemorySSA=*/false))
158156 FUNCTION_PASS("early-cse-memssa", EarlyCSEPass(/*UseMemorySSA=*/true))
159157 FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/false))
215213 FUNCTION_PASS("verify", LoopVerifierPass())
216214 FUNCTION_PASS("verify", MemorySSAVerifierPass())
217215 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<CFGDOTInfo *>::getSimpleNodeLabel(B, nullptr);
898 return DOTGraphTraits<const Function *>::getSimpleNodeLabel(B, nullptr);
899899 }
900900 #endif
901901
+0
-54
llvm/Analysis/HeatUtils.h less more
None //===-- 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
102 ;PR 1497
113
124 define void @foo() {