LLVM  13.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::OF_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 
273 /// Find all blocks on the paths which terminate with a deoptimize or
274 /// unreachable (i.e. all blocks which are post-dominated by a deoptimize
275 /// or unreachable). These paths are hidden if the corresponding cl::opts
276 /// are enabled.
278  const Function *F) {
279  auto evaluateBB = [&](const BasicBlock *Node) {
280  if (succ_empty(Node)) {
281  const Instruction *TI = Node->getTerminator();
282  isOnDeoptOrUnreachablePath[Node] =
283  (HideUnreachablePaths && isa<UnreachableInst>(TI)) ||
284  (HideDeoptimizePaths && Node->getTerminatingDeoptimizeCall());
285  return;
286  }
287  isOnDeoptOrUnreachablePath[Node] =
288  llvm::all_of(successors(Node), [this](const BasicBlock *BB) {
289  return isOnDeoptOrUnreachablePath[BB];
290  });
291  };
292  /// The post order traversal iteration is done to know the status of
293  /// isOnDeoptOrUnreachablePath for all the successors on the current BB.
294  llvm::for_each(post_order(&F->getEntryBlock()), evaluateBB);
295 }
296 
298  const DOTFuncInfo *CFGInfo) {
300  if (isOnDeoptOrUnreachablePath.find(Node) ==
301  isOnDeoptOrUnreachablePath.end())
302  computeDeoptOrUnreachablePaths(Node->getParent());
303  return isOnDeoptOrUnreachablePath[Node];
304  }
305  return false;
306 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm::createCFGOnlyPrinterLegacyPassPass
FunctionPass * createCFGOnlyPrinterLegacyPassPass()
Definition: CFGPrinter.cpp:269
INITIALIZE_PASS
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true) PreservedAnalyses CFGViewerPass
Definition: CFGPrinter.cpp:117
llvm
Definition: AllocatorList.h:23
FileSystem.h
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
llvm::Function
Definition: Function.h:61
CFGDotFilenamePrefix
static cl::opt< std::string > CFGDotFilenamePrefix("cfg-dot-filename-prefix", cl::Hidden, cl::desc("The prefix used for the CFG dot file names."))
llvm::getMaxFreq
uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI)
Definition: HeatUtils.cpp:52
Pass.h
llvm::BlockFrequencyInfoWrapperPass
Legacy analysis pass which computes BlockFrequencyInfo.
Definition: BlockFrequencyInfo.h:138
llvm::DOTFuncInfo::setHeatColors
void setHeatColors(bool ShowHeat)
Definition: CFGPrinter.h:87
contains
return AArch64::GPR64RegClass contains(Reg)
llvm::DefaultDOTGraphTraits::isNodeHidden
static bool isNodeHidden(const void *, const GraphType &)
isNodeHidden - If the function returns true, the given node is not displayed in the graph.
Definition: DOTGraphTraits.h:64
viewCFG
static void viewCFG(Function &F, const BlockFrequencyInfo *BFI, const BranchProbabilityInfo *BPI, uint64_t MaxFreq, bool CFGOnly=false)
Definition: CFGPrinter.cpp:80
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::DOTFuncInfo::setEdgeWeights
void setEdgeWeights(bool EdgeWeights)
Definition: CFGPrinter.h:95
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:892
llvm::ViewGraph
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
Definition: GraphWriter.h:375
llvm::successors
succ_range successors(Instruction *I)
Definition: CFG.h:262
llvm::succ_empty
bool succ_empty(const Instruction *I)
Definition: CFG.h:256
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::Function::viewCFG
void viewCFG() const
viewCFG - This function is meant for use from the debugger.
Definition: CFGPrinter.cpp:243
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
CommandLine.h
llvm::BranchProbabilityAnalysis
Analysis pass which computes BranchProbabilityInfo.
Definition: BranchProbabilityInfo.h:420
llvm::all_of
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:1482
llvm::BlockFrequencyInfo
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Definition: BlockFrequencyInfo.h:37
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::BranchProbabilityInfoWrapperPass
Legacy analysis pass which computes BranchProbabilityInfo.
Definition: BranchProbabilityInfo.h:446
llvm::initializeCFGViewerLegacyPassPass
void initializeCFGViewerLegacyPassPass(PassRegistry &)
llvm::BranchProbabilityInfo
Analysis providing branch probability information.
Definition: BranchProbabilityInfo.h:115
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
llvm::CFGViewerPass
Definition: CFGPrinter.h:34
llvm::initializeCFGOnlyPrinterLegacyPassPass
void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry &)
llvm::Instruction
Definition: Instruction.h:45
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::Function::viewCFGOnly
void viewCFGOnly() const
viewCFGOnly - This function is meant for use from the debugger.
Definition: CFGPrinter.cpp:258
llvm::BlockFrequencyAnalysis
Analysis pass which computes BlockFrequencyInfo.
Definition: BlockFrequencyInfo.h:112
llvm::DOTGraphTraits
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
Definition: DOTGraphTraits.h:161
HideUnreachablePaths
static cl::opt< bool > HideUnreachablePaths("cfg-hide-unreachable-paths", cl::init(false))
llvm::cl::opt
Definition: CommandLine.h:1422
CFGPrinter.h
llvm::sys::fs::OF_Text
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
Definition: FileSystem.h:762
llvm::for_each
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:1475
ShowEdgeWeight
static cl::opt< bool > ShowEdgeWeight("cfg-weights", cl::init(false), cl::Hidden, cl::desc("Show edges labeled with weights"))
llvm::createCFGPrinterLegacyPassPass
FunctionPass * createCFGPrinterLegacyPassPass()
Definition: CFGPrinter.cpp:265
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
writeCFGToDotFile
static void writeCFGToDotFile(Function &F, BlockFrequencyInfo *BFI, BranchProbabilityInfo *BPI, uint64_t MaxFreq, bool CFGOnly=false)
Definition: CFGPrinter.cpp:58
llvm::WriteGraph
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
Definition: GraphWriter.h:307
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::initializeCFGOnlyViewerLegacyPassPass
void initializeCFGOnlyViewerLegacyPassPass(PassRegistry &)
llvm::AMDGPUISD::BFI
@ BFI
Definition: AMDGPUISelLowering.h:418
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:294
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:432
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::CFGOnlyViewerPass
Definition: CFGPrinter.h:39
llvm::AnalysisUsage::setPreservesAll
void setPreservesAll()
Set by analyses that do not transform their input at all.
Definition: PassAnalysisSupport.h:130
llvm::DOTFuncInfo
Definition: CFGPrinter.h:54
HideDeoptimizePaths
static cl::opt< bool > HideDeoptimizePaths("cfg-hide-deoptimize-paths", cl::init(false))
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::post_order
iterator_range< po_iterator< T > > post_order(const T &G)
Definition: PostOrderIterator.h:188
ShowHeatColors
static cl::opt< bool > ShowHeatColors("cfg-heat-colors", cl::init(true), cl::Hidden, cl::desc("Show heat colors in CFG"))
llvm::CFGOnlyPrinterPass
Definition: CFGPrinter.h:49
PostOrderIterator.h
llvm::CFGPrinterPass
Definition: CFGPrinter.h:44
llvm::initializeCFGPrinterLegacyPassPass
void initializeCFGPrinterLegacyPassPass(PassRegistry &)
llvm::Pass::getAnalysisUsage
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:93
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
CFGFuncName
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."))
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::cl::desc
Definition: CommandLine.h:414
llvm::DOTFuncInfo::setRawEdgeWeights
void setRawEdgeWeights(bool RawWeights)
Definition: CFGPrinter.h:91
InitializePasses.h
File
Instrumentation for Order File
Definition: InstrOrderFile.cpp:206
UseRawEdgeWeight
static cl::opt< bool > UseRawEdgeWeight("cfg-raw-weights", cl::init(false), cl::Hidden, cl::desc("Use raw weights for labels. " "Use percentages as default."))
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38