LLVM  14.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 
46  "cfg-hide-cold-paths", cl::init(0.0),
47  cl::desc("Hide blocks with relative frequency below the given value"));
48 
49 static cl::opt<bool> ShowHeatColors("cfg-heat-colors", cl::init(true),
50  cl::Hidden,
51  cl::desc("Show heat colors in CFG"));
52 
53 static cl::opt<bool> UseRawEdgeWeight("cfg-raw-weights", cl::init(false),
54  cl::Hidden,
55  cl::desc("Use raw weights for labels. "
56  "Use percentages as default."));
57 
58 static cl::opt<bool>
59  ShowEdgeWeight("cfg-weights", cl::init(false), cl::Hidden,
60  cl::desc("Show edges labeled with weights"));
61 
63  BranchProbabilityInfo *BPI, uint64_t MaxFreq,
64  bool CFGOnly = false) {
65  std::string Filename =
66  (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str();
67  errs() << "Writing '" << Filename << "'...";
68 
69  std::error_code EC;
70  raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
71 
72  DOTFuncInfo CFGInfo(&F, BFI, BPI, MaxFreq);
76 
77  if (!EC)
78  WriteGraph(File, &CFGInfo, CFGOnly);
79  else
80  errs() << " error opening file for writing!";
81  errs() << "\n";
82 }
83 
84 static void viewCFG(Function &F, const BlockFrequencyInfo *BFI,
85  const BranchProbabilityInfo *BPI, uint64_t MaxFreq,
86  bool CFGOnly = false) {
87  DOTFuncInfo CFGInfo(&F, BFI, BPI, MaxFreq);
91 
92  ViewGraph(&CFGInfo, "cfg." + F.getName(), CFGOnly);
93 }
94 
95 namespace {
96 struct CFGViewerLegacyPass : public FunctionPass {
97  static char ID; // Pass identifcation, replacement for typeid
98  CFGViewerLegacyPass() : FunctionPass(ID) {
100  }
101 
102  bool runOnFunction(Function &F) override {
103  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
104  return false;
105  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
106  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
107  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
108  return false;
109  }
110 
111  void print(raw_ostream &OS, const Module * = nullptr) const override {}
112 
113  void getAnalysisUsage(AnalysisUsage &AU) const override {
117  AU.setPreservesAll();
118  }
119 };
120 } // namespace
121 
122 char CFGViewerLegacyPass::ID = 0;
123 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false,
124  true)
125 
127  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
128  return PreservedAnalyses::all();
129  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
130  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
131  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI));
132  return PreservedAnalyses::all();
133 }
134 
135 namespace {
136 struct CFGOnlyViewerLegacyPass : public FunctionPass {
137  static char ID; // Pass identifcation, replacement for typeid
138  CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
140  }
141 
142  bool runOnFunction(Function &F) override {
143  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
144  return false;
145  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
146  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
147  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
148  return false;
149  }
150 
151  void print(raw_ostream &OS, const Module * = nullptr) const override {}
152 
153  void getAnalysisUsage(AnalysisUsage &AU) const override {
157  AU.setPreservesAll();
158  }
159 };
160 } // namespace
161 
163 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
164  "View CFG of function (with no function bodies)", false, true)
165 
168  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
169  return PreservedAnalyses::all();
170  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
171  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
172  viewCFG(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
173  return PreservedAnalyses::all();
174 }
175 
176 namespace {
177 struct CFGPrinterLegacyPass : public FunctionPass {
178  static char ID; // Pass identification, replacement for typeid
179  CFGPrinterLegacyPass() : FunctionPass(ID) {
181  }
182 
183  bool runOnFunction(Function &F) override {
184  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
185  return false;
186  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
187  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
189  return false;
190  }
191 
192  void print(raw_ostream &OS, const Module * = nullptr) const override {}
193 
194  void getAnalysisUsage(AnalysisUsage &AU) const override {
198  AU.setPreservesAll();
199  }
200 };
201 } // namespace
202 
203 char CFGPrinterLegacyPass::ID = 0;
204 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg",
205  "Print CFG of function to 'dot' file", false, true)
206 
209  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
210  return PreservedAnalyses::all();
211  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
212  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
214  return PreservedAnalyses::all();
215 }
216 
217 namespace {
218 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
219  static char ID; // Pass identification, replacement for typeid
220  CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
222  }
223 
224  bool runOnFunction(Function &F) override {
225  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
226  return false;
227  auto *BPI = &getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
228  auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
229  writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
230  return false;
231  }
232  void print(raw_ostream &OS, const Module * = nullptr) const override {}
233 
234  void getAnalysisUsage(AnalysisUsage &AU) const override {
238  AU.setPreservesAll();
239  }
240 };
241 } // namespace
242 
244 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
245  "Print CFG of function to 'dot' file (with no function bodies)",
246  false, true)
247 
250  if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
251  return PreservedAnalyses::all();
252  auto *BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
253  auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(F);
254  writeCFGToDotFile(F, BFI, BPI, getMaxFreq(F, BFI), /*CFGOnly=*/true);
255  return PreservedAnalyses::all();
256 }
257 
258 /// viewCFG - This function is meant for use from the debugger. You can just
259 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
260 /// program, displaying the CFG of the current function. This depends on there
261 /// being a 'dot' and 'gv' program in your path.
262 ///
263 void Function::viewCFG() const { viewCFG(false, nullptr, nullptr); }
264 
265 void Function::viewCFG(bool ViewCFGOnly, const BlockFrequencyInfo *BFI,
266  const BranchProbabilityInfo *BPI) const {
267  if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
268  return;
269  DOTFuncInfo CFGInfo(this, BFI, BPI, BFI ? getMaxFreq(*this, BFI) : 0);
270  ViewGraph(&CFGInfo, "cfg" + getName(), ViewCFGOnly);
271 }
272 
273 /// viewCFGOnly - This function is meant for use from the debugger. It works
274 /// just like viewCFG, but it does not include the contents of basic blocks
275 /// into the nodes, just the label. If you are only interested in the CFG
276 /// this can make the graph smaller.
277 ///
278 void Function::viewCFGOnly() const { viewCFGOnly(nullptr, nullptr); }
279 
281  const BranchProbabilityInfo *BPI) const {
282  viewCFG(true, BFI, BPI);
283 }
284 
286  return new CFGPrinterLegacyPass();
287 }
288 
290  return new CFGOnlyPrinterLegacyPass();
291 }
292 
293 /// Find all blocks on the paths which terminate with a deoptimize or
294 /// unreachable (i.e. all blocks which are post-dominated by a deoptimize
295 /// or unreachable). These paths are hidden if the corresponding cl::opts
296 /// are enabled.
298  const Function *F) {
299  auto evaluateBB = [&](const BasicBlock *Node) {
300  if (succ_empty(Node)) {
301  const Instruction *TI = Node->getTerminator();
302  isOnDeoptOrUnreachablePath[Node] =
303  (HideUnreachablePaths && isa<UnreachableInst>(TI)) ||
304  (HideDeoptimizePaths && Node->getTerminatingDeoptimizeCall());
305  return;
306  }
307  isOnDeoptOrUnreachablePath[Node] =
308  llvm::all_of(successors(Node), [this](const BasicBlock *BB) {
309  return isOnDeoptOrUnreachablePath[BB];
310  });
311  };
312  /// The post order traversal iteration is done to know the status of
313  /// isOnDeoptOrUnreachablePath for all the successors on the current BB.
314  llvm::for_each(post_order(&F->getEntryBlock()), evaluateBB);
315 }
316 
318  const DOTFuncInfo *CFGInfo) {
319  if (HideColdPaths.getNumOccurrences() > 0)
320  if (auto *BFI = CFGInfo->getBFI()) {
321  uint64_t NodeFreq = BFI->getBlockFreq(Node).getFrequency();
322  uint64_t EntryFreq = BFI->getEntryFreq();
323  // Hide blocks with relative frequency below HideColdPaths threshold.
324  if ((double)NodeFreq / EntryFreq < HideColdPaths)
325  return true;
326  }
328  if (isOnDeoptOrUnreachablePath.find(Node) ==
329  isOnDeoptOrUnreachablePath.end())
330  computeDeoptOrUnreachablePaths(Node->getParent());
331  return isOnDeoptOrUnreachablePath[Node];
332  }
333  return false;
334 }
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:289
INITIALIZE_PASS
INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true) PreservedAnalyses CFGViewerPass
Definition: CFGPrinter.cpp:123
llvm
---------------------— PointerInfo ------------------------------------—
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:51
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:84
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::DOTFuncInfo::getBFI
const BlockFrequencyInfo * getBFI() const
Definition: CFGPrinter.h:75
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:263
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
CommandLine.h
llvm::BranchProbabilityAnalysis
Analysis pass which computes BranchProbabilityInfo.
Definition: BranchProbabilityInfo.h:414
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:1551
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:440
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:53
llvm::Function::viewCFGOnly
void viewCFGOnly() const
viewCFGOnly - This function is meant for use from the debugger.
Definition: CFGPrinter.cpp:278
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:1434
CFGPrinter.h
uint64_t
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:761
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:1544
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:285
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:62
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
HideColdPaths
static cl::opt< double > HideColdPaths("cfg-hide-cold-paths", cl::init(0.0), cl::desc("Hide blocks with relative frequency below the given value"))
llvm::initializeCFGOnlyViewerLegacyPassPass
void initializeCFGOnlyViewerLegacyPassPass(PassRegistry &)
llvm::AMDGPUISD::BFI
@ BFI
Definition: AMDGPUISelLowering.h:421
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:443
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:205
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:37