1 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This implements the SelectionDAG::viewGraph method.
12 //===----------------------------------------------------------------------===//
14 #include "ScheduleDAGSDNodes.h"
15 #include "llvm/Constants.h"
16 #include "llvm/Function.h"
17 #include "llvm/Assembly/Writer.h"
18 #include "llvm/CodeGen/SelectionDAG.h"
19 #include "llvm/CodeGen/MachineConstantPool.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineModuleInfo.h"
22 #include "llvm/CodeGen/PseudoSourceValue.h"
23 #include "llvm/Analysis/DebugInfo.h"
24 #include "llvm/Target/TargetRegisterInfo.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/GraphWriter.h"
28 #include "llvm/Support/raw_ostream.h"
29 #include "llvm/ADT/DenseSet.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/Config/config.h"
37 struct DOTGraphTraits
<SelectionDAG
*> : public DefaultDOTGraphTraits
{
38 static bool hasEdgeDestLabels() {
42 static unsigned numEdgeDestLabels(const void *Node
) {
43 return ((const SDNode
*) Node
)->getNumValues();
46 static std::string
getEdgeDestLabel(const void *Node
, unsigned i
) {
47 return ((const SDNode
*) Node
)->getValueType(i
).getMVTString();
50 /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
51 /// should actually target another edge source, not a node. If this method is
52 /// implemented, getEdgeTarget should be implemented.
53 template<typename EdgeIter
>
54 static bool edgeTargetsEdgeSource(const void *Node
, EdgeIter I
) {
58 /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
59 /// called to determine which outgoing edge of Node is the target of this
61 template<typename EdgeIter
>
62 static EdgeIter
getEdgeTarget(const void *Node
, EdgeIter I
) {
63 SDNode
*TargetNode
= *I
;
64 SDNodeIterator NI
= SDNodeIterator::begin(TargetNode
);
65 std::advance(NI
, I
.getNode()->getOperand(I
.getOperand()).getResNo());
69 static std::string
getGraphName(const SelectionDAG
*G
) {
70 return G
->getMachineFunction().getFunction()->getName();
73 static bool renderGraphFromBottomUp() {
77 static bool hasNodeAddressLabel(const SDNode
*Node
,
78 const SelectionDAG
*Graph
) {
82 /// If you want to override the dot attributes printed for a particular
83 /// edge, override this method.
84 template<typename EdgeIter
>
85 static std::string
getEdgeAttributes(const void *Node
, EdgeIter EI
) {
86 SDValue Op
= EI
.getNode()->getOperand(EI
.getOperand());
87 MVT VT
= Op
.getValueType();
89 return "color=red,style=bold";
90 else if (VT
== MVT::Other
)
91 return "color=blue,style=dashed";
96 static std::string
getNodeLabel(const SDNode
*Node
,
97 const SelectionDAG
*Graph
);
98 static std::string
getNodeAttributes(const SDNode
*N
,
99 const SelectionDAG
*Graph
) {
101 const std::string
&Attrs
= Graph
->getGraphAttrs(N
);
102 if (!Attrs
.empty()) {
103 if (Attrs
.find("shape=") == std::string::npos
)
104 return std::string("shape=Mrecord,") + Attrs
;
109 return "shape=Mrecord";
112 static void addCustomGraphFeatures(SelectionDAG
*G
,
113 GraphWriter
<SelectionDAG
*> &GW
) {
114 GW
.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
115 if (G
->getRoot().getNode())
116 GW
.emitEdge(0, -1, G
->getRoot().getNode(), G
->getRoot().getResNo(),
117 "color=blue,style=dashed");
122 std::string DOTGraphTraits
<SelectionDAG
*>::getNodeLabel(const SDNode
*Node
,
123 const SelectionDAG
*G
) {
124 std::string Op
= Node
->getOperationName(G
);
126 if (const ConstantSDNode
*CSDN
= dyn_cast
<ConstantSDNode
>(Node
)) {
127 Op
+= ": " + utostr(CSDN
->getZExtValue());
128 } else if (const ConstantFPSDNode
*CSDN
= dyn_cast
<ConstantFPSDNode
>(Node
)) {
129 Op
+= ": " + ftostr(CSDN
->getValueAPF());
130 } else if (const GlobalAddressSDNode
*GADN
=
131 dyn_cast
<GlobalAddressSDNode
>(Node
)) {
132 Op
+= ": " + GADN
->getGlobal()->getName();
133 if (int64_t Offset
= GADN
->getOffset()) {
135 Op
+= "+" + itostr(Offset
);
137 Op
+= itostr(Offset
);
139 } else if (const FrameIndexSDNode
*FIDN
= dyn_cast
<FrameIndexSDNode
>(Node
)) {
140 Op
+= " " + itostr(FIDN
->getIndex());
141 } else if (const JumpTableSDNode
*JTDN
= dyn_cast
<JumpTableSDNode
>(Node
)) {
142 Op
+= " " + itostr(JTDN
->getIndex());
143 } else if (const ConstantPoolSDNode
*CP
= dyn_cast
<ConstantPoolSDNode
>(Node
)){
144 if (CP
->isMachineConstantPoolEntry()) {
147 raw_string_ostream
OSS(Op
);
148 OSS
<< *CP
->getMachineCPVal();
152 if (ConstantFP
*CFP
= dyn_cast
<ConstantFP
>(CP
->getConstVal()))
153 Op
+= "<" + ftostr(CFP
->getValueAPF()) + ">";
154 else if (ConstantInt
*CI
= dyn_cast
<ConstantInt
>(CP
->getConstVal()))
155 Op
+= "<" + utostr(CI
->getZExtValue()) + ">";
159 raw_string_ostream
OSS(Op
);
160 WriteAsOperand(OSS
, CP
->getConstVal(), false);
165 Op
+= " A=" + itostr(CP
->getAlignment());
166 } else if (const BasicBlockSDNode
*BBDN
= dyn_cast
<BasicBlockSDNode
>(Node
)) {
168 const Value
*LBB
= (const Value
*)BBDN
->getBasicBlock()->getBasicBlock();
170 Op
+= LBB
->getName();
171 //Op += " " + (const void*)BBDN->getBasicBlock();
172 } else if (const RegisterSDNode
*R
= dyn_cast
<RegisterSDNode
>(Node
)) {
173 if (G
&& R
->getReg() != 0 &&
174 TargetRegisterInfo::isPhysicalRegister(R
->getReg())) {
176 G
->getTarget().getRegisterInfo()->getName(R
->getReg());
178 Op
+= " #" + utostr(R
->getReg());
180 } else if (const DbgStopPointSDNode
*D
= dyn_cast
<DbgStopPointSDNode
>(Node
)) {
181 DICompileUnit
CU(cast
<GlobalVariable
>(D
->getCompileUnit()));
183 Op
+= ": " + CU
.getFilename(FN
);
184 Op
+= ":" + utostr(D
->getLine());
185 if (D
->getColumn() != 0)
186 Op
+= ":" + utostr(D
->getColumn());
187 } else if (const LabelSDNode
*L
= dyn_cast
<LabelSDNode
>(Node
)) {
188 Op
+= ": LabelID=" + utostr(L
->getLabelID());
189 } else if (const CallSDNode
*C
= dyn_cast
<CallSDNode
>(Node
)) {
190 Op
+= ": CallingConv=" + utostr(C
->getCallingConv());
194 Op
+= ", isTailCall";
195 } else if (const ExternalSymbolSDNode
*ES
=
196 dyn_cast
<ExternalSymbolSDNode
>(Node
)) {
197 Op
+= "'" + std::string(ES
->getSymbol()) + "'";
198 } else if (const SrcValueSDNode
*M
= dyn_cast
<SrcValueSDNode
>(Node
)) {
200 Op
+= "<" + M
->getValue()->getName() + ">";
203 } else if (const MemOperandSDNode
*M
= dyn_cast
<MemOperandSDNode
>(Node
)) {
204 const Value
*V
= M
->MO
.getValue();
208 } else if (const PseudoSourceValue
*PSV
= dyn_cast
<PseudoSourceValue
>(V
)) {
209 // PseudoSourceValues don't have names, so use their print method.
210 raw_string_ostream
OSS(Op
);
215 Op
+= '+' + itostr(M
->MO
.getOffset()) + '>';
216 } else if (const ARG_FLAGSSDNode
*N
= dyn_cast
<ARG_FLAGSSDNode
>(Node
)) {
217 Op
= Op
+ " AF=" + N
->getArgFlags().getArgFlagsString();
218 } else if (const VTSDNode
*N
= dyn_cast
<VTSDNode
>(Node
)) {
219 Op
= Op
+ " VT=" + N
->getVT().getMVTString();
220 } else if (const LoadSDNode
*LD
= dyn_cast
<LoadSDNode
>(Node
)) {
222 switch (LD
->getExtensionType()) {
223 default: doExt
= false; break;
225 Op
= Op
+ "<anyext ";
235 Op
+= LD
->getMemoryVT().getMVTString() + ">";
236 if (LD
->isVolatile())
238 Op
+= LD
->getIndexedModeName(LD
->getAddressingMode());
239 if (LD
->getAlignment() > 1)
240 Op
+= " A=" + utostr(LD
->getAlignment());
241 } else if (const StoreSDNode
*ST
= dyn_cast
<StoreSDNode
>(Node
)) {
242 if (ST
->isTruncatingStore())
243 Op
+= "<trunc " + ST
->getMemoryVT().getMVTString() + ">";
244 if (ST
->isVolatile())
246 Op
+= ST
->getIndexedModeName(ST
->getAddressingMode());
247 if (ST
->getAlignment() > 1)
248 Op
+= " A=" + utostr(ST
->getAlignment());
252 Op
+= " Id=" + itostr(Node
->getNodeId());
259 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
260 /// rendered using 'dot'.
262 void SelectionDAG::viewGraph(const std::string
&Title
) {
263 // This code is only for debugging!
265 ViewGraph(this, "dag." + getMachineFunction().getFunction()->getName(),
268 cerr
<< "SelectionDAG::viewGraph is only available in debug builds on "
269 << "systems with Graphviz or gv!\n";
273 // This overload is defined out-of-line here instead of just using a
274 // default parameter because this is easiest for gdb to call.
275 void SelectionDAG::viewGraph() {
279 /// clearGraphAttrs - Clear all previously defined node graph attributes.
280 /// Intended to be used from a debugging tool (eg. gdb).
281 void SelectionDAG::clearGraphAttrs() {
283 NodeGraphAttrs
.clear();
285 cerr
<< "SelectionDAG::clearGraphAttrs is only available in debug builds"
286 << " on systems with Graphviz or gv!\n";
291 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
293 void SelectionDAG::setGraphAttrs(const SDNode
*N
, const char *Attrs
) {
295 NodeGraphAttrs
[N
] = Attrs
;
297 cerr
<< "SelectionDAG::setGraphAttrs is only available in debug builds"
298 << " on systems with Graphviz or gv!\n";
303 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
304 /// Used from getNodeAttributes.
305 const std::string
SelectionDAG::getGraphAttrs(const SDNode
*N
) const {
307 std::map
<const SDNode
*, std::string
>::const_iterator I
=
308 NodeGraphAttrs
.find(N
);
310 if (I
!= NodeGraphAttrs
.end())
315 cerr
<< "SelectionDAG::getGraphAttrs is only available in debug builds"
316 << " on systems with Graphviz or gv!\n";
317 return std::string("");
321 /// setGraphColor - Convenience for setting node color attribute.
323 void SelectionDAG::setGraphColor(const SDNode
*N
, const char *Color
) {
325 NodeGraphAttrs
[N
] = std::string("color=") + Color
;
327 cerr
<< "SelectionDAG::setGraphColor is only available in debug builds"
328 << " on systems with Graphviz or gv!\n";
332 /// setSubgraphColorHelper - Implement setSubgraphColor. Return
333 /// whether we truncated the search.
335 bool SelectionDAG::setSubgraphColorHelper(SDNode
*N
, const char *Color
, DenseSet
<SDNode
*> &visited
,
336 int level
, bool &printed
) {
337 bool hit_limit
= false;
343 DOUT
<< "setSubgraphColor hit max level\n";
348 unsigned oldSize
= visited
.size();
350 if (visited
.size() != oldSize
) {
351 setGraphColor(N
, Color
);
352 for(SDNodeIterator i
= SDNodeIterator::begin(N
), iend
= SDNodeIterator::end(N
);
355 hit_limit
= setSubgraphColorHelper(*i
, Color
, visited
, level
+1, printed
) || hit_limit
;
359 cerr
<< "SelectionDAG::setSubgraphColor is only available in debug builds"
360 << " on systems with Graphviz or gv!\n";
365 /// setSubgraphColor - Convenience for setting subgraph color attribute.
367 void SelectionDAG::setSubgraphColor(SDNode
*N
, const char *Color
) {
369 DenseSet
<SDNode
*> visited
;
370 bool printed
= false;
371 if (setSubgraphColorHelper(N
, Color
, visited
, 0, printed
)) {
372 // Visually mark that we hit the limit
373 if (strcmp(Color
, "red") == 0) {
374 setSubgraphColorHelper(N
, "blue", visited
, 0, printed
);
376 else if (strcmp(Color
, "yellow") == 0) {
377 setSubgraphColorHelper(N
, "green", visited
, 0, printed
);
382 cerr
<< "SelectionDAG::setSubgraphColor is only available in debug builds"
383 << " on systems with Graphviz or gv!\n";
387 std::string
ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit
*SU
) const {
389 raw_string_ostream
O(s
);
390 O
<< "SU(" << SU
->NodeNum
<< "): ";
392 SmallVector
<SDNode
*, 4> FlaggedNodes
;
393 for (SDNode
*N
= SU
->getNode(); N
; N
= N
->getFlaggedNode())
394 FlaggedNodes
.push_back(N
);
395 while (!FlaggedNodes
.empty()) {
396 O
<< DOTGraphTraits
<SelectionDAG
*>::getNodeLabel(FlaggedNodes
.back(), DAG
);
397 FlaggedNodes
.pop_back();
398 if (!FlaggedNodes
.empty())
402 O
<< "CROSS RC COPY";
407 void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter
<ScheduleDAG
*> &GW
) const {
409 // Draw a special "GraphRoot" node to indicate the root of the graph.
410 GW
.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
411 const SDNode
*N
= DAG
->getRoot().getNode();
412 if (N
&& N
->getNodeId() != -1)
413 GW
.emitEdge(0, -1, &SUnits
[N
->getNodeId()], -1,
414 "color=blue,style=dashed");