20
20
21
21
#include " llvm/Analysis/BlockFrequencyInfo.h"
22
22
#include " llvm/Analysis/BranchProbabilityInfo.h"
23
+ #include " llvm/Analysis/HeatUtils.h"
23
24
#include " llvm/IR/CFG.h"
24
25
#include " llvm/IR/Constants.h"
25
26
#include " llvm/IR/Function.h"
29
30
#include " llvm/Support/GraphWriter.h"
30
31
31
32
namespace llvm {
32
- class CFGViewerPass
33
- : public PassInfoMixin<CFGViewerPass> {
33
+ class CFGViewerPass : public PassInfoMixin <CFGViewerPass> {
34
34
public:
35
35
PreservedAnalyses run (Function &F, FunctionAnalysisManager &AM);
36
36
};
37
37
38
- class CFGOnlyViewerPass
39
- : public PassInfoMixin<CFGOnlyViewerPass> {
38
+ class CFGOnlyViewerPass : public PassInfoMixin <CFGOnlyViewerPass> {
40
39
public:
41
40
PreservedAnalyses run (Function &F, FunctionAnalysisManager &AM);
42
41
};
43
42
44
- class CFGPrinterPass
45
- : public PassInfoMixin<CFGPrinterPass> {
43
+ class CFGPrinterPass : public PassInfoMixin <CFGPrinterPass> {
46
44
public:
47
45
PreservedAnalyses run (Function &F, FunctionAnalysisManager &AM);
48
46
};
49
47
50
- class CFGOnlyPrinterPass
51
- : public PassInfoMixin<CFGOnlyPrinterPass> {
48
+ class CFGOnlyPrinterPass : public PassInfoMixin <CFGOnlyPrinterPass> {
52
49
public:
53
50
PreservedAnalyses run (Function &F, FunctionAnalysisManager &AM);
54
51
};
@@ -58,20 +55,45 @@ class DOTFuncInfo {
58
55
const Function *F;
59
56
const BlockFrequencyInfo *BFI;
60
57
const BranchProbabilityInfo *BPI;
58
+ uint64_t MaxFreq;
59
+ bool ShowHeat;
60
+ bool EdgeWeights;
61
+ bool RawWeights;
61
62
62
63
public:
63
- DOTFuncInfo (const Function *F) : DOTFuncInfo(F, nullptr , nullptr ) {}
64
+ DOTFuncInfo (const Function *F) : DOTFuncInfo(F, nullptr , nullptr , 0 ) {}
64
65
65
66
DOTFuncInfo (const Function *F, const BlockFrequencyInfo *BFI,
66
- BranchProbabilityInfo *BPI)
67
- : F(F), BFI(BFI), BPI(BPI) {
67
+ BranchProbabilityInfo *BPI, uint64_t MaxFreq)
68
+ : F(F), BFI(BFI), BPI(BPI), MaxFreq(MaxFreq) {
69
+ ShowHeat = false ;
70
+ EdgeWeights = true ;
71
+ RawWeights = true ;
68
72
}
69
73
70
74
const BlockFrequencyInfo *getBFI () { return BFI; }
71
75
72
76
const BranchProbabilityInfo *getBPI () { return BPI; }
73
77
74
78
const Function *getFunction () { return this ->F ; }
79
+
80
+ uint64_t getMaxFreq () { return MaxFreq; }
81
+
82
+ uint64_t getFreq (const BasicBlock *BB) {
83
+ return BFI->getBlockFreq (BB).getFrequency ();
84
+ }
85
+
86
+ void setHeatColors (bool ShowHeat) { this ->ShowHeat = ShowHeat; }
87
+
88
+ bool showHeatColors () { return ShowHeat; }
89
+
90
+ void setRawEdgeWeights (bool RawWeights) { this ->RawWeights = RawWeights; }
91
+
92
+ bool useRawEdgeWeights () { return RawWeights; }
93
+
94
+ void setEdgeWeights (bool EdgeWeights) { this ->EdgeWeights = EdgeWeights; }
95
+
96
+ bool showEdgeWeights () { return EdgeWeights; }
75
97
};
76
98
77
99
template <>
@@ -96,12 +118,13 @@ struct GraphTraits<DOTFuncInfo *> : public GraphTraits<const BasicBlock *> {
96
118
}
97
119
};
98
120
99
- template <> struct DOTGraphTraits <DOTFuncInfo *> : public DefaultDOTGraphTraits {
121
+ template <>
122
+ struct DOTGraphTraits <DOTFuncInfo *> : public DefaultDOTGraphTraits {
100
123
101
124
// Cache for is hidden property
102
- llvm::DenseMap <const BasicBlock *, bool > isHiddenBasicBlock;
125
+ llvm::DenseMap<const BasicBlock *, bool > isHiddenBasicBlock;
103
126
104
- DOTGraphTraits (bool isSimple= false ) : DefaultDOTGraphTraits(isSimple) {}
127
+ DOTGraphTraits (bool isSimple = false ) : DefaultDOTGraphTraits(isSimple) {}
105
128
106
129
static std::string getGraphName (DOTFuncInfo *CFGInfo) {
107
130
return " CFG for '" + CFGInfo->getFunction ()->getName ().str () + " ' function" ;
@@ -131,40 +154,39 @@ template <> struct DOTGraphTraits<DOTFuncInfo *> : public DefaultDOTGraphTraits
131
154
132
155
OS << *Node;
133
156
std::string OutStr = OS.str ();
134
- if (OutStr[0 ] == ' \n ' ) OutStr.erase (OutStr.begin ());
157
+ if (OutStr[0 ] == ' \n ' )
158
+ OutStr.erase (OutStr.begin ());
135
159
136
160
// Process string output to make it nicer...
137
161
unsigned ColNum = 0 ;
138
162
unsigned LastSpace = 0 ;
139
163
for (unsigned i = 0 ; i != OutStr.length (); ++i) {
140
- if (OutStr[i] == ' \n ' ) { // Left justify
164
+ if (OutStr[i] == ' \n ' ) { // Left justify
141
165
OutStr[i] = ' \\ ' ;
142
- OutStr.insert (OutStr.begin ()+i+ 1 , ' l' );
166
+ OutStr.insert (OutStr.begin () + i + 1 , ' l' );
143
167
ColNum = 0 ;
144
168
LastSpace = 0 ;
145
- } else if (OutStr[i] == ' ;' ) { // Delete comments!
146
- unsigned Idx = OutStr.find (' \n ' , i+ 1 ); // Find end of line
147
- OutStr.erase (OutStr.begin ()+ i, OutStr.begin ()+ Idx);
169
+ } else if (OutStr[i] == ' ;' ) { // Delete comments!
170
+ unsigned Idx = OutStr.find (' \n ' , i + 1 ); // Find end of line
171
+ OutStr.erase (OutStr.begin () + i, OutStr.begin () + Idx);
148
172
--i;
149
- } else if (ColNum == MaxColumns) { // Wrap lines.
173
+ } else if (ColNum == MaxColumns) { // Wrap lines.
150
174
// Wrap very long names even though we can't find a space.
151
175
if (!LastSpace)
152
176
LastSpace = i;
153
177
OutStr.insert (LastSpace, " \\ l..." );
154
178
ColNum = i - LastSpace;
155
179
LastSpace = 0 ;
156
180
i += 3 ; // The loop will advance 'i' again.
157
- }
158
- else
181
+ } else
159
182
++ColNum;
160
183
if (OutStr[i] == ' ' )
161
184
LastSpace = i;
162
185
}
163
186
return OutStr;
164
187
}
165
188
166
- std::string getNodeLabel (const BasicBlock *Node,
167
- DOTFuncInfo *CFGInfo) {
189
+ std::string getNodeLabel (const BasicBlock *Node, DOTFuncInfo *CFGInfo) {
168
190
169
191
if (isSimple ())
170
192
return getSimpleNodeLabel (Node, CFGInfo);
@@ -183,7 +205,8 @@ template <> struct DOTGraphTraits<DOTFuncInfo *> : public DefaultDOTGraphTraits
183
205
if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator ())) {
184
206
unsigned SuccNo = I.getSuccessorIndex ();
185
207
186
- if (SuccNo == 0 ) return " def" ;
208
+ if (SuccNo == 0 )
209
+ return " def" ;
187
210
188
211
std::string Str;
189
212
raw_string_ostream OS (Str);
@@ -197,37 +220,80 @@ template <> struct DOTGraphTraits<DOTFuncInfo *> : public DefaultDOTGraphTraits
197
220
// / Display the raw branch weights from PGO.
198
221
std::string getEdgeAttributes (const BasicBlock *Node, const_succ_iterator I,
199
222
DOTFuncInfo *CFGInfo) {
223
+ if (!CFGInfo->showEdgeWeights ())
224
+ return " " ;
225
+
200
226
const Instruction *TI = Node->getTerminator ();
201
227
if (TI->getNumSuccessors () == 1 )
228
+ return " penwidth=2" ;
229
+
230
+ unsigned OpNo = I.getSuccessorIndex ();
231
+
232
+ if (OpNo >= TI->getNumSuccessors ())
202
233
return " " ;
234
+
235
+ BasicBlock *SuccBB = TI->getSuccessor (OpNo);
236
+ auto BranchProb = CFGInfo->getBPI ()->getEdgeProbability (Node, SuccBB);
237
+ double WeightPercent = ((double )BranchProb.getNumerator ()) /
238
+ ((double )BranchProb.getDenominator ());
239
+ double Width = 1 + WeightPercent;
240
+
241
+ if (!CFGInfo->useRawEdgeWeights ())
242
+ return formatv (" label=\" {0:P}\" penwidth={1}" , WeightPercent, Width)
243
+ .str ();
244
+
245
+ // Prepend a 'W' to indicate that this is a weight rather than the actual
246
+ // profile count (due to scaling).
247
+
248
+ uint64_t Freq = CFGInfo->getFreq (Node);
249
+ std::string Attrs = formatv (" label=\" W:{0}\" penwidth={1}" ,
250
+ (uint64_t )(Freq * WeightPercent), Width);
251
+ if (Attrs.size ())
252
+ return Attrs;
253
+
203
254
MDNode *WeightsNode = TI->getMetadata (LLVMContext::MD_prof);
204
255
if (!WeightsNode)
205
256
return " " ;
206
257
207
258
MDString *MDName = cast<MDString>(WeightsNode->getOperand (0 ));
208
259
if (MDName->getString () != " branch_weights" )
209
260
return " " ;
210
- unsigned OpNo = I.getSuccessorIndex () + 1 ;
261
+
262
+ OpNo = I.getSuccessorIndex () + 1 ;
211
263
if (OpNo >= WeightsNode->getNumOperands ())
212
264
return " " ;
213
265
ConstantInt *Weight =
214
266
mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand (OpNo));
215
267
if (!Weight)
216
268
return " " ;
269
+ return (" label=\" W:" + std::to_string (Weight->getZExtValue ()) +
270
+ " \" penwidth=" + std::to_string (Width));
271
+ }
217
272
218
- // Prepend a 'W' to indicate that this is a weight rather than the actual
219
- // profile count (due to scaling).
220
- return (" label=\" W:" + Twine (Weight->getZExtValue ()) + " \" " ).str ();
273
+ std::string getNodeAttributes (const BasicBlock *Node, DOTFuncInfo *CFGInfo) {
274
+
275
+ if (!CFGInfo->showHeatColors ())
276
+ return " " ;
277
+
278
+ uint64_t Freq = CFGInfo->getFreq (Node);
279
+ std::string Color = getHeatColor (Freq, CFGInfo->getMaxFreq ());
280
+ std::string EdgeColor = (Freq <= (CFGInfo->getMaxFreq () / 2 ))
281
+ ? (getHeatColor (0 ))
282
+ : (getHeatColor (1 ));
283
+
284
+ std::string Attrs = " color=\" " + EdgeColor + " ff\" , style=filled," +
285
+ " fillcolor=\" " + Color + " 70\" " ;
286
+ return Attrs;
221
287
}
222
288
bool isNodeHidden (const BasicBlock *Node);
223
289
void computeHiddenNodes (const Function *F);
224
290
};
225
291
} // End llvm namespace
226
292
227
293
namespace llvm {
228
- class FunctionPass ;
229
- FunctionPass *createCFGPrinterLegacyPassPass ();
230
- FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
294
+ class FunctionPass ;
295
+ FunctionPass *createCFGPrinterLegacyPassPass ();
296
+ FunctionPass *createCFGOnlyPrinterLegacyPassPass ();
231
297
} // End llvm namespace
232
298
233
299
#endif
0 commit comments