[Alignment][NFC] Support compile time constants
[llvm-core.git] / include / llvm / Analysis / CFGPrinter.h
blobaaefc11653dda5cef454bbb6f0c28b0b392bef2d
1 //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
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 // cfg.<fnname>.dot file for each function in the program, with a graph of the
11 // CFG for that function.
13 // This file defines external functions that can be called to explicitly
14 // instantiate the CFG printer.
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_ANALYSIS_CFGPRINTER_H
19 #define LLVM_ANALYSIS_CFGPRINTER_H
21 #include "llvm/IR/CFG.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/PassManager.h"
26 #include "llvm/Support/GraphWriter.h"
28 namespace llvm {
29 class CFGViewerPass
30 : public PassInfoMixin<CFGViewerPass> {
31 public:
32 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
35 class CFGOnlyViewerPass
36 : public PassInfoMixin<CFGOnlyViewerPass> {
37 public:
38 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
41 class CFGPrinterPass
42 : public PassInfoMixin<CFGPrinterPass> {
43 public:
44 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
47 class CFGOnlyPrinterPass
48 : public PassInfoMixin<CFGOnlyPrinterPass> {
49 public:
50 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
53 template<>
54 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
56 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
58 static std::string getGraphName(const Function *F) {
59 return "CFG for '" + F->getName().str() + "' function";
62 static std::string getSimpleNodeLabel(const BasicBlock *Node,
63 const Function *) {
64 if (!Node->getName().empty())
65 return Node->getName().str();
67 std::string Str;
68 raw_string_ostream OS(Str);
70 Node->printAsOperand(OS, false);
71 return OS.str();
74 static std::string getCompleteNodeLabel(const BasicBlock *Node,
75 const Function *) {
76 enum { MaxColumns = 80 };
77 std::string Str;
78 raw_string_ostream OS(Str);
80 if (Node->getName().empty()) {
81 Node->printAsOperand(OS, false);
82 OS << ":";
85 OS << *Node;
86 std::string OutStr = OS.str();
87 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
89 // Process string output to make it nicer...
90 unsigned ColNum = 0;
91 unsigned LastSpace = 0;
92 for (unsigned i = 0; i != OutStr.length(); ++i) {
93 if (OutStr[i] == '\n') { // Left justify
94 OutStr[i] = '\\';
95 OutStr.insert(OutStr.begin()+i+1, 'l');
96 ColNum = 0;
97 LastSpace = 0;
98 } else if (OutStr[i] == ';') { // Delete comments!
99 unsigned Idx = OutStr.find('\n', i+1); // Find end of line
100 OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
101 --i;
102 } else if (ColNum == MaxColumns) { // Wrap lines.
103 // Wrap very long names even though we can't find a space.
104 if (!LastSpace)
105 LastSpace = i;
106 OutStr.insert(LastSpace, "\\l...");
107 ColNum = i - LastSpace;
108 LastSpace = 0;
109 i += 3; // The loop will advance 'i' again.
111 else
112 ++ColNum;
113 if (OutStr[i] == ' ')
114 LastSpace = i;
116 return OutStr;
119 std::string getNodeLabel(const BasicBlock *Node,
120 const Function *Graph) {
121 if (isSimple())
122 return getSimpleNodeLabel(Node, Graph);
123 else
124 return getCompleteNodeLabel(Node, Graph);
127 static std::string getEdgeSourceLabel(const BasicBlock *Node,
128 succ_const_iterator I) {
129 // Label source of conditional branches with "T" or "F"
130 if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
131 if (BI->isConditional())
132 return (I == succ_begin(Node)) ? "T" : "F";
134 // Label source of switch edges with the associated value.
135 if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
136 unsigned SuccNo = I.getSuccessorIndex();
138 if (SuccNo == 0) return "def";
140 std::string Str;
141 raw_string_ostream OS(Str);
142 auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
143 OS << Case.getCaseValue()->getValue();
144 return OS.str();
146 return "";
149 /// Display the raw branch weights from PGO.
150 std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I,
151 const Function *F) {
152 const Instruction *TI = Node->getTerminator();
153 if (TI->getNumSuccessors() == 1)
154 return "";
156 MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof);
157 if (!WeightsNode)
158 return "";
160 MDString *MDName = cast<MDString>(WeightsNode->getOperand(0));
161 if (MDName->getString() != "branch_weights")
162 return "";
164 unsigned OpNo = I.getSuccessorIndex() + 1;
165 if (OpNo >= WeightsNode->getNumOperands())
166 return "";
167 ConstantInt *Weight =
168 mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(OpNo));
169 if (!Weight)
170 return "";
172 // Prepend a 'W' to indicate that this is a weight rather than the actual
173 // profile count (due to scaling).
174 return ("label=\"W:" + Twine(Weight->getZExtValue()) + "\"").str();
177 } // End llvm namespace
179 namespace llvm {
180 class FunctionPass;
181 FunctionPass *createCFGPrinterLegacyPassPass ();
182 FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
183 } // End llvm namespace
185 #endif