LLVM  12.0.0git
CFGPrinter.cpp
Go to the documentation of this file.
1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a `-dot-cfg` analysis pass, which emits the
10 // `<prefix>.<fnname>.dot` file for each function in the program, with a graph
11 // of the CFG for that function. The default value for `<prefix>` is `cfg` but
12 // can be customized as needed.
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 
22 #include "llvm/InitializePasses.h"
23 #include "llvm/Pass.h"
26 #include <algorithm>
27 
28 using namespace llvm;
29 
31  CFGFuncName("cfg-func-name", cl::Hidden,
32  cl::desc("The name of a function (or its substring)"
33  " whose CFG is viewed/printed."));
34 
36  "cfg-dot-filename-prefix", cl::Hidden,
37  cl::desc("The prefix used for the CFG dot file names."));
38 
39 static cl::opt<bool> HideUnreachablePaths("cfg-hide-unreachable-paths",
40  cl::init(false));
41 
42 static cl::opt<bool> HideDeoptimizePaths("cfg-hide-deoptimize-paths",
43  cl::init(false));
44 
45 static cl::opt<bool> ShowHeatColors("cfg-heat-colors", cl::init(true),
46  cl::Hidden,
47  cl::desc("Show heat colors in CFG"));
48 
49 static cl::opt<bool> UseRawEdgeWeight("cfg-raw-weights", cl::init(false),
50  cl::Hidden,
51  cl::desc("Use raw weights for labels. "
52  "Use percentages as default."));
53 
54 static cl::opt<bool>
55  ShowEdgeWeight("cfg-weights", cl::init(false), cl::Hidden,
56  cl::desc("Show edges labeled with weights"));
57 
59  BranchProbabilityInfo *BPI, uint64_t MaxFreq,
60  bool CFGOnly = false) {
61  std::string Filename =
62  (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str();
63  errs() << "Writing '" << Filename << "'...";
64 
65  std::error_code EC;
66  raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
67 
68  DOTFuncInfo CFGInfo(&F, BFI, BPI, MaxFreq);
72 
73  if (!EC)
74  WriteGraph(File, &CFGInfo, CFGOnly);
75  else
76  errs() << " error opening file for writing!";
77  errs() << "\n";
78 }
79 
80 static void viewCFG(Function &F, const BlockFrequencyInfo *BFI,
81  const BranchProbabilityInfo *BPI, uint64_t MaxFreq,
82  bool CFGOnly = false) {
83  DOTFuncInfo CFGInfo(&F, BFI, BPI, MaxFreq);
87 
88  ViewGraph(&CFGInfo, "cfg." + F.getName(), CFGOnly);
89 }
90 
91 namespace {
92 struct CFGViewerLegacyPass : public FunctionPass {
93  static char ID; // Pass identifcation, replacement for typeid
94  CFGViewerLegacyPass() : FunctionPass(ID) {
96  }
97 
98  bool runOnFunction(Function &F) override {
99  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
100  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
101  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
102  return false;
103  }
104 
105  void print(raw_ostream &OS, const Module * = nullptr) const override {}
106 
107  void getAnalysisUsage(AnalysisUsage &AU) const override {
111  AU.setPreservesAll();
112  }
113 };
114 }
115 
116 char CFGViewerLegacyPass::ID = 0;
117 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false,
118  true)
119 
121  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
122  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
123  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
124  return PreservedAnalyses::all();
125 }
126 
127 namespace {
128 struct CFGOnlyViewerLegacyPass : public FunctionPass {
129  static char ID; // Pass identifcation, replacement for typeid
130  CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
132  }
133 
134  bool runOnFunction(Function &F) override {
135  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
136  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
137  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
138  return false;
139  }
140 
141  void print(raw_ostream &OS, const Module * = nullptr) const override {}
142 
143  void getAnalysisUsage(AnalysisUsage &AU) const override {
147  AU.setPreservesAll();
148  }
149 };
150 }
151 
153 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
154  "View CFG of function (with no function bodies)", false, true)
155 
158  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
159  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
160  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
161  return PreservedAnalyses::all();
162 }
163 
164 namespace {
165 struct CFGPrinterLegacyPass : public FunctionPass {
166  static char ID; // Pass identification, replacement for typeid
167  CFGPrinterLegacyPass() : FunctionPass(ID) {
169  }
170 
171  bool runOnFunction(Function &F) override {
172  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
173  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
175  return false;
176  }
177 
178  void print(raw_ostream &OS, const Module * = nullptr) const override {}
179 
180  void getAnalysisUsage(AnalysisUsage &AU) const override {
184  AU.setPreservesAll();
185  }
186 };
187 }
188 
189 char CFGPrinterLegacyPass::ID = 0;
190 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
191  "Print CFG of function to 'dot' file", false, true)
192 
195  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
196  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
198  return PreservedAnalyses::all();
199 }
200 
201 namespace {
202 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
203  static char ID; // Pass identification, replacement for typeid
204  CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
206  }
207 
208  bool runOnFunction(Function &F) override {
209  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
210  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
211  writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
212  return false;
213  }
214  void print(raw_ostream &OS, const Module * = nullptr) const override {}
215 
216  void getAnalysisUsage(AnalysisUsage &AU) const override {
220  AU.setPreservesAll();
221  }
222 };
223 }
224 
226 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
227  "Print CFG of function to 'dot' file (with no function bodies)",
228  false, true)
229 
232  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
233  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
234  writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
235  return PreservedAnalyses::all();
236 }
237 
238 /// viewCFG - This function is meant for use from the debugger. You can just
239 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
240 /// program, displaying the CFG of the current function. This depends on there
241 /// being a 'dot' and 'gv' program in your path.
242 ///
243 void Function::viewCFG() const { viewCFG(false, nullptr, nullptr); }
244 
245 void Function::viewCFG(bool ViewCFGOnly, const BlockFrequencyInfo *BFI,
246  const BranchProbabilityInfo *BPI) const {
247  if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
248  return;
249  DOTFuncInfo CFGInfo(this, BFI, BPI, BFI ? getMaxFreq(*this, BFI) : 0);
250  ViewGraph(&CFGInfo, "cfg" + getName(), ViewCFGOnly);
251 }
252 
253 /// viewCFGOnly - This function is meant for use from the debugger. It works
254 /// just like viewCFG, but it does not include the contents of basic blocks
255 /// into the nodes, just the label. If you are only interested in the CFG
256 /// this can make the graph smaller.
257 ///
258 void Function::viewCFGOnly() const { viewCFGOnly(nullptr, nullptr); }
259 
261  const BranchProbabilityInfo *BPI) const {
262  viewCFG(true, BFI, BPI);
263 }
264 
266  return new CFGPrinterLegacyPass();
267 }
268 
270  return new CFGOnlyPrinterLegacyPass();
271 }
272 
274  auto evaluateBB = [&](const BasicBlock *Node) {
275  if (succ_empty(Node)) {
276  const Instruction *TI = Node->getTerminator();
277  isHiddenBasicBlock[Node] =
278  (HideUnreachablePaths && isa<UnreachableInst>(TI)) ||
279  (HideDeoptimizePaths && Node->getTerminatingDeoptimizeCall());
280  return;
281  }
282  isHiddenBasicBlock[Node] =
283  llvm::all_of(successors(Node), [this](const BasicBlock *BB) {
284  return isHiddenBasicBlock[BB];
285  });
286  };
287  /// The post order traversal iteration is done to know the status of
288  /// isHiddenBasicBlock for all the successors on the current BB.
289  for_each(po_begin(&F->getEntryBlock()), po_end(&F->getEntryBlock()),
290  evaluateBB);
291 }
292 
294  const DOTFuncInfo *CFGInfo) {
295  // If both restricting flags are false, all nodes are displayed.
297  return false;
298  if (isHiddenBasicBlock.find(Node) == isHiddenBasicBlock.end())
299  computeHiddenNodes(Node->getParent());
300  return isHiddenBasicBlock[Node];
301 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static cl::opt< std::string > CFGFuncName("cfg-func-name", cl::Hidden, cl::desc("The name of a function (or its substring)" " whose CFG is viewed/printed."))
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
FunctionPass * createCFGPrinterLegacyPassPass()
Definition: CFGPrinter.cpp:265
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1498
static cl::opt< std::string > CFGDotFilenamePrefix("cfg-dot-filename-prefix", cl::Hidden, cl::desc("The prefix used for the CFG dot file names."))
F(f)
static void viewCFG(Function &F, const BlockFrequencyInfo *BFI, const BranchProbabilityInfo *BPI, uint64_t MaxFreq, bool CFGOnly=false)
Definition: CFGPrinter.cpp:80
*ViewGraph Emit a dot run run gv on the postscript *then cleanup For use from the debugger *void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
Definition: GraphWriter.h:374
AnalysisUsage & addRequired()
void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry &)
Legacy analysis pass which computes BlockFrequencyInfo.
static cl::opt< bool > HideUnreachablePaths("cfg-hide-unreachable-paths", cl::init(false))
Analysis pass which computes BranchProbabilityInfo.
void viewCFG() const
viewCFG - This function is meant for use from the debugger.
Definition: CFGPrinter.cpp:243
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:93
static cl::opt< bool > ShowEdgeWeight("cfg-weights", cl::init(false), cl::Hidden, cl::desc("Show edges labeled with weights"))
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
Definition: GraphWriter.h:307
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1491
Legacy analysis pass which computes BranchProbabilityInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:427
void viewCFGOnly() const
viewCFGOnly - This function is meant for use from the debugger.
Definition: CFGPrinter.cpp:258
FunctionPass * createCFGOnlyPrinterLegacyPassPass()
Definition: CFGPrinter.cpp:269
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
Instrumentation for Order File
Represent the analysis usage information of a pass.
void setEdgeWeights(bool EdgeWeights)
Definition: CFGPrinter.h:95
uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI)
Definition: HeatUtils.cpp:52
po_iterator< T > po_end(const T &G)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_NODISCARD bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition: StringRef.h:465
bool succ_empty(const Instruction *I)
Definition: CFG.h:254
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
Analysis pass which computes BlockFrequencyInfo.
static bool isNodeHidden(const void *, const GraphType &)
isNodeHidden - If the function returns true, the given node is not displayed in the graph.
void setPreservesAll()
Set by analyses that do not transform their input at all.
static cl::opt< bool > ShowHeatColors("cfg-heat-colors", cl::init(true), cl::Hidden, cl::desc("Show heat colors in CFG"))
void initializeCFGViewerLegacyPassPass(PassRegistry &)
void initializeCFGPrinterLegacyPassPass(PassRegistry &)
static void writeCFGToDotFile(Function &F, BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI, uint64_t MaxFreq, bool CFGOnly=false)
Definition: CFGPrinter.cpp:58
Analysis providing branch probability information.
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:425
void setHeatColors(bool ShowHeat)
Definition: CFGPrinter.h:87
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:295
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true) PreservedAnalyses CFGViewerPass
Definition: CFGPrinter.cpp:117
succ_range successors(Instruction *I)
Definition: CFG.h:260
static cl::opt< bool > UseRawEdgeWeight("cfg-raw-weights", cl::init(false), cl::Hidden, cl::desc("Use raw weights for labels. " "Use percentages as default."))
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
void setRawEdgeWeights(bool RawWeights)
Definition: CFGPrinter.h:91
A container for analyses that lazily runs them and caches their results.
static cl::opt< bool > HideDeoptimizePaths("cfg-hide-deoptimize-paths", cl::init(false))
po_iterator< T > po_begin(const T &G)
void initializeCFGOnlyViewerLegacyPassPass(PassRegistry &)