blob: 10be4e4bb9538e4b018453aba5a54e123bab0d6b [file] [log] [blame]
Chris Lattnera93d11b2003-10-22 16:03:49 +00001//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
Misha Brukman01808ca2005-04-21 21:13:18 +00002//
Chris Lattnera93d11b2003-10-22 16:03:49 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukman01808ca2005-04-21 21:13:18 +00007//
Chris Lattnera93d11b2003-10-22 16:03:49 +00008//===----------------------------------------------------------------------===//
9//
Duncan Sands9c40c282008-09-23 12:47:39 +000010// This file defines a '-dot-cfg' analysis pass, which emits the
Chris Lattnera93d11b2003-10-22 16:03:49 +000011// cfg.<fnname>.dot file for each function in the program, with a graph of the
12// CFG for that function.
13//
14// The other main feature of this file is that it implements the
15// Function::viewCFG method, which is useful for debugging passes which operate
16// on the CFG.
17//
18//===----------------------------------------------------------------------===//
19
Brian Gaeke104341f2004-04-26 16:27:08 +000020#include "llvm/Analysis/CFGPrinter.h"
Chris Lattnerda424262009-10-18 04:09:11 +000021#include "llvm/Pass.h"
Benjamin Kramerd59664f2014-04-29 23:26:49 +000022#include "llvm/Support/FileSystem.h"
Chris Lattner62aff842003-12-11 21:48:18 +000023using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000024
Sean Fertile3b0535b2018-06-29 17:13:58 +000025static cl::opt<bool> CFGHeatPerFunction("cfg-heat-per-function",
26 cl::init(false), cl::Hidden,
27 cl::desc("Heat CFG per function"));
28
29static cl::opt<bool> ShowHeatColors("cfg-heat-colors", cl::init(true),
30 cl::Hidden,
31 cl::desc("Show heat colors in CFG"));
32
33static cl::opt<bool> UseRawEdgeWeight("cfg-raw-weights", cl::init(false),
34 cl::Hidden,
35 cl::desc("Use raw weights for labels. "
36 "Use percentages as default."));
37
38static cl::opt<bool> ShowEdgeWeight("cfg-weights", cl::init(true), cl::Hidden,
39 cl::desc("Show edges labeled with weights"));
40
41static void writeHeatCFGToDotFile(Function &F, BlockFrequencyInfo *BFI,
42 BranchProbabilityInfo *BPI, uint64_t MaxFreq,
43 bool UseHeuristic, bool isSimple) {
44 std::string Filename = ("cfg." + F.getName() + ".dot").str();
45 errs() << "Writing '" << Filename << "'...";
46
47 std::error_code EC;
48 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
49
50 CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
51 CFGInfo.setHeuristic(UseHeuristic);
52 CFGInfo.setHeatColors(ShowHeatColors);
53 CFGInfo.setEdgeWeights(ShowEdgeWeight);
54 CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
55
56 if (!EC)
57 WriteGraph(File, &CFGInfo, isSimple);
58 else
59 errs() << " error opening file for writing!";
60 errs() << "\n";
61}
62
63static void writeAllCFGsToDotFile(Module &M,
64 function_ref<BlockFrequencyInfo *(Function &)> LookupBFI,
65 function_ref<BranchProbabilityInfo *(Function &)> LookupBPI,
66 bool isSimple) {
67 bool UseHeuristic = true;
68 uint64_t MaxFreq = 0;
69 if (!CFGHeatPerFunction)
70 MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
71
72 for (auto &F : M) {
73 if (F.isDeclaration()) continue;
74 auto *BFI = LookupBFI(F);
75 auto *BPI = LookupBPI(F);
76 if (CFGHeatPerFunction)
77 MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
78 writeHeatCFGToDotFile(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
79 }
80
81}
82
83static void viewHeatCFG(Function &F, BlockFrequencyInfo *BFI,
84 BranchProbabilityInfo *BPI, uint64_t MaxFreq,
85 bool UseHeuristic, bool isSimple) {
86 CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
87 CFGInfo.setHeuristic(UseHeuristic);
88 CFGInfo.setHeatColors(ShowHeatColors);
89 CFGInfo.setEdgeWeights(ShowEdgeWeight);
90 CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
91
92 ViewGraph(&CFGInfo, "cfg." + F.getName(), isSimple);
93}
94
95static void viewAllCFGs(Module &M,
96 function_ref<BlockFrequencyInfo *(Function &)> LookupBFI,
97 function_ref<BranchProbabilityInfo *(Function &)> LookupBPI,
98 bool isSimple) {
99 bool UseHeuristic = true;
100 uint64_t MaxFreq = 0;
101 if (!CFGHeatPerFunction)
102 MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
103
104 for (auto &F : M) {
105 if (F.isDeclaration()) continue;
106 auto *BFI = LookupBFI(F);
107 auto *BPI = LookupBPI(F);
108 if (CFGHeatPerFunction)
109 MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
110 viewHeatCFG(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
111 }
112
113}
114
Chris Lattnera93d11b2003-10-22 16:03:49 +0000115namespace {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000116 struct CFGViewerLegacyPass : public ModulePass {
Dan Gohman90d97ac2007-05-14 14:25:08 +0000117 static char ID; // Pass identifcation, replacement for typeid
Sean Fertile3b0535b2018-06-29 17:13:58 +0000118 CFGViewerLegacyPass() : ModulePass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000119 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000120 }
Devang Patel864970e2008-03-18 00:39:19 +0000121
Sean Fertile3b0535b2018-06-29 17:13:58 +0000122 bool runOnModule(Module &M) override {
123 auto LookupBFI = [this](Function &F) {
124 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
125 };
126 auto LookupBPI = [this](Function &F) {
127 return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
128 };
129 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
Dan Gohman90d97ac2007-05-14 14:25:08 +0000130 return false;
131 }
132
Sean Fertile3b0535b2018-06-29 17:13:58 +0000133 void print(raw_ostream &OS, const Module * = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +0000134
Craig Toppere9ba7592014-03-05 07:30:04 +0000135 void getAnalysisUsage(AnalysisUsage &AU) const override {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000136 ModulePass::getAnalysisUsage(AU);
137 AU.addRequired<BlockFrequencyInfoWrapperPass>();
138 AU.addRequired<BranchProbabilityInfoWrapperPass>();
Dan Gohman90d97ac2007-05-14 14:25:08 +0000139 AU.setPreservesAll();
140 }
Sean Fertile3b0535b2018-06-29 17:13:58 +0000141
Dan Gohman90d97ac2007-05-14 14:25:08 +0000142 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000143}
Dan Gohman90d97ac2007-05-14 14:25:08 +0000144
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000145char CFGViewerLegacyPass::ID = 0;
146INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
147
Sean Fertile3b0535b2018-06-29 17:13:58 +0000148PreservedAnalyses CFGViewerPass::run(Module &M,
149 ModuleAnalysisManager &AM) {
150 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
151 auto LookupBFI = [&FAM](Function &F) {
152 return &FAM.getResult<BlockFrequencyAnalysis>(F);
153 };
154 auto LookupBPI = [&FAM](Function &F) {
155 return &FAM.getResult<BranchProbabilityAnalysis>(F);
156 };
157 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000158 return PreservedAnalyses::all();
159}
160
Dan Gohman90d97ac2007-05-14 14:25:08 +0000161
Dan Gohmand78c4002008-05-13 00:00:25 +0000162namespace {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000163 struct CFGOnlyViewerLegacyPass : public ModulePass {
Dan Gohman90d97ac2007-05-14 14:25:08 +0000164 static char ID; // Pass identifcation, replacement for typeid
Sean Fertile3b0535b2018-06-29 17:13:58 +0000165 CFGOnlyViewerLegacyPass() : ModulePass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000166 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000167 }
Devang Patel864970e2008-03-18 00:39:19 +0000168
Sean Fertile3b0535b2018-06-29 17:13:58 +0000169 bool runOnModule(Module &M) override {
170 auto LookupBFI = [this](Function &F) {
171 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
172 };
173 auto LookupBPI = [this](Function &F) {
174 return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
175 };
176 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
Dan Gohman90d97ac2007-05-14 14:25:08 +0000177 return false;
178 }
179
Sean Fertile3b0535b2018-06-29 17:13:58 +0000180 void print(raw_ostream &OS, const Module * = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +0000181
Craig Toppere9ba7592014-03-05 07:30:04 +0000182 void getAnalysisUsage(AnalysisUsage &AU) const override {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000183 ModulePass::getAnalysisUsage(AU);
184 AU.addRequired<BlockFrequencyInfoWrapperPass>();
185 AU.addRequired<BranchProbabilityInfoWrapperPass>();
Dan Gohman90d97ac2007-05-14 14:25:08 +0000186 AU.setPreservesAll();
187 }
Sean Fertile3b0535b2018-06-29 17:13:58 +0000188
Dan Gohman90d97ac2007-05-14 14:25:08 +0000189 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000190}
Dan Gohman90d97ac2007-05-14 14:25:08 +0000191
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000192char CFGOnlyViewerLegacyPass::ID = 0;
193INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000194 "View CFG of function (with no function bodies)", false, true)
Dan Gohman90d97ac2007-05-14 14:25:08 +0000195
Sean Fertile3b0535b2018-06-29 17:13:58 +0000196PreservedAnalyses CFGOnlyViewerPass::run(Module &M,
197 ModuleAnalysisManager &AM) {
198 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
199 auto LookupBFI = [&FAM](Function &F) {
200 return &FAM.getResult<BlockFrequencyAnalysis>(F);
201 };
202 auto LookupBPI = [&FAM](Function &F) {
203 return &FAM.getResult<BranchProbabilityAnalysis>(F);
204 };
205 viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000206 return PreservedAnalyses::all();
207}
208
Dan Gohmand78c4002008-05-13 00:00:25 +0000209namespace {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000210 struct CFGPrinterLegacyPass : public ModulePass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000211 static char ID; // Pass identification, replacement for typeid
Sean Fertile3b0535b2018-06-29 17:13:58 +0000212 CFGPrinterLegacyPass() : ModulePass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000213 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000214 }
Devang Patel864970e2008-03-18 00:39:19 +0000215
Sean Fertile3b0535b2018-06-29 17:13:58 +0000216 bool runOnModule(Module &M) override {
217 auto LookupBFI = [this](Function &F) {
218 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
219 };
220 auto LookupBPI = [this](Function &F) {
221 return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
222 };
223 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000224 return false;
225 }
226
Sean Fertile3b0535b2018-06-29 17:13:58 +0000227 void print(raw_ostream &OS, const Module * = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000228
Craig Toppere9ba7592014-03-05 07:30:04 +0000229 void getAnalysisUsage(AnalysisUsage &AU) const override {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000230 ModulePass::getAnalysisUsage(AU);
231 AU.addRequired<BlockFrequencyInfoWrapperPass>();
232 AU.addRequired<BranchProbabilityInfoWrapperPass>();
Chris Lattnera93d11b2003-10-22 16:03:49 +0000233 AU.setPreservesAll();
234 }
Sean Fertile3b0535b2018-06-29 17:13:58 +0000235
Chris Lattnera93d11b2003-10-22 16:03:49 +0000236 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000237}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000238
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000239char CFGPrinterLegacyPass::ID = 0;
240INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000241 false, true)
Chris Lattner62aff842003-12-11 21:48:18 +0000242
Sean Fertile3b0535b2018-06-29 17:13:58 +0000243PreservedAnalyses CFGPrinterPass::run(Module &M,
244 ModuleAnalysisManager &AM) {
245 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
246 auto LookupBFI = [&FAM](Function &F) {
247 return &FAM.getResult<BlockFrequencyAnalysis>(F);
248 };
249 auto LookupBPI = [&FAM](Function &F) {
250 return &FAM.getResult<BranchProbabilityAnalysis>(F);
251 };
252 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000253 return PreservedAnalyses::all();
254}
255
Dan Gohmand78c4002008-05-13 00:00:25 +0000256namespace {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000257 struct CFGOnlyPrinterLegacyPass : public ModulePass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000258 static char ID; // Pass identification, replacement for typeid
Sean Fertile3b0535b2018-06-29 17:13:58 +0000259 CFGOnlyPrinterLegacyPass() : ModulePass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000260 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000261 }
Craig Toppere9ba7592014-03-05 07:30:04 +0000262
Sean Fertile3b0535b2018-06-29 17:13:58 +0000263 bool runOnModule(Module &M) override {
264 auto LookupBFI = [this](Function &F) {
265 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
266 };
267 auto LookupBPI = [this](Function &F) {
268 return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
269 };
270 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
Chris Lattner62aff842003-12-11 21:48:18 +0000271 return false;
272 }
Sean Fertile3b0535b2018-06-29 17:13:58 +0000273
274 void print(raw_ostream &OS, const Module * = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000275
Craig Toppere9ba7592014-03-05 07:30:04 +0000276 void getAnalysisUsage(AnalysisUsage &AU) const override {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000277 ModulePass::getAnalysisUsage(AU);
278 AU.addRequired<BlockFrequencyInfoWrapperPass>();
279 AU.addRequired<BranchProbabilityInfoWrapperPass>();
Chris Lattner62aff842003-12-11 21:48:18 +0000280 AU.setPreservesAll();
281 }
Sean Fertile3b0535b2018-06-29 17:13:58 +0000282
Chris Lattner62aff842003-12-11 21:48:18 +0000283 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000284}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000285
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000286char CFGOnlyPrinterLegacyPass::ID = 0;
287INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
Owen Andersond31d82d2010-08-23 17:52:01 +0000288 "Print CFG of function to 'dot' file (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000289 false, true)
Dan Gohmand78c4002008-05-13 00:00:25 +0000290
Sean Fertile3b0535b2018-06-29 17:13:58 +0000291PreservedAnalyses CFGOnlyPrinterPass::run(Module &M,
292 ModuleAnalysisManager &AM) {
293 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
294 auto LookupBFI = [&FAM](Function &F) {
295 return &FAM.getResult<BlockFrequencyAnalysis>(F);
296 };
297 auto LookupBPI = [&FAM](Function &F) {
298 return &FAM.getResult<BranchProbabilityAnalysis>(F);
299 };
300 writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000301 return PreservedAnalyses::all();
302}
303
Chris Lattnera93d11b2003-10-22 16:03:49 +0000304/// viewCFG - This function is meant for use from the debugger. You can just
305/// say 'call F->viewCFG()' and a ghostview window should pop up from the
306/// program, displaying the CFG of the current function. This depends on there
307/// being a 'dot' and 'gv' program in your path.
308///
309void Function::viewCFG() const {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000310
311 CFGDOTInfo CFGInfo(this);
312 ViewGraph(&CFGInfo, "cfg" + getName());
Chris Lattnera93d11b2003-10-22 16:03:49 +0000313}
314
315/// viewCFGOnly - This function is meant for use from the debugger. It works
316/// just like viewCFG, but it does not include the contents of basic blocks
Eric Christopher650c8f22014-05-20 17:11:11 +0000317/// into the nodes, just the label. If you are only interested in the CFG
318/// this can make the graph smaller.
Chris Lattnera93d11b2003-10-22 16:03:49 +0000319///
320void Function::viewCFGOnly() const {
Sean Fertile3b0535b2018-06-29 17:13:58 +0000321
322 CFGDOTInfo CFGInfo(this);
323 ViewGraph(&CFGInfo, "cfg" + getName(), true);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000324}
Brian Gaeke104341f2004-04-26 16:27:08 +0000325
Sean Fertile3b0535b2018-06-29 17:13:58 +0000326ModulePass *llvm::createCFGPrinterLegacyPassPass() {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000327 return new CFGPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000328}
329
Sean Fertile3b0535b2018-06-29 17:13:58 +0000330ModulePass *llvm::createCFGOnlyPrinterLegacyPassPass() {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000331 return new CFGOnlyPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000332}