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"
36 struct DOTGraphTraits
<SelectionDAG
*> : public DefaultDOTGraphTraits
{
38 explicit DOTGraphTraits(bool isSimple
=false) :
39 DefaultDOTGraphTraits(isSimple
) {}
41 static bool hasEdgeDestLabels() {
45 static unsigned numEdgeDestLabels(const void *Node
) {
46 return ((const SDNode
*) Node
)->getNumValues();
49 static std::string
getEdgeDestLabel(const void *Node
, unsigned i
) {
50 return ((const SDNode
*) Node
)->getValueType(i
).getEVTString();
53 template<typename EdgeIter
>
54 static std::string
getEdgeSourceLabel(const void *Node
, EdgeIter I
) {
55 return itostr(I
- SDNodeIterator::begin((SDNode
*) Node
));
58 /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
59 /// should actually target another edge source, not a node. If this method
60 /// is implemented, getEdgeTarget should be implemented.
61 template<typename EdgeIter
>
62 static bool edgeTargetsEdgeSource(const void *Node
, EdgeIter I
) {
66 /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
67 /// called to determine which outgoing edge of Node is the target of this
69 template<typename EdgeIter
>
70 static EdgeIter
getEdgeTarget(const void *Node
, EdgeIter I
) {
71 SDNode
*TargetNode
= *I
;
72 SDNodeIterator NI
= SDNodeIterator::begin(TargetNode
);
73 std::advance(NI
, I
.getNode()->getOperand(I
.getOperand()).getResNo());
77 static std::string
getGraphName(const SelectionDAG
*G
) {
78 return G
->getMachineFunction().getFunction()->getName();
81 static bool renderGraphFromBottomUp() {
85 static bool hasNodeAddressLabel(const SDNode
*Node
,
86 const SelectionDAG
*Graph
) {
90 /// If you want to override the dot attributes printed for a particular
91 /// edge, override this method.
92 template<typename EdgeIter
>
93 static std::string
getEdgeAttributes(const void *Node
, EdgeIter EI
,
94 const SelectionDAG
*Graph
) {
95 SDValue Op
= EI
.getNode()->getOperand(EI
.getOperand());
96 EVT VT
= Op
.getValueType();
98 return "color=red,style=bold";
99 else if (VT
== MVT::Other
)
100 return "color=blue,style=dashed";
105 static std::string
getSimpleNodeLabel(const SDNode
*Node
,
106 const SelectionDAG
*G
) {
107 std::string Result
= Node
->getOperationName(G
);
109 raw_string_ostream
OS(Result
);
110 Node
->print_details(OS
, G
);
114 std::string
getNodeLabel(const SDNode
*Node
, const SelectionDAG
*Graph
);
115 static std::string
getNodeAttributes(const SDNode
*N
,
116 const SelectionDAG
*Graph
) {
118 const std::string
&Attrs
= Graph
->getGraphAttrs(N
);
119 if (!Attrs
.empty()) {
120 if (Attrs
.find("shape=") == std::string::npos
)
121 return std::string("shape=Mrecord,") + Attrs
;
126 return "shape=Mrecord";
129 static void addCustomGraphFeatures(SelectionDAG
*G
,
130 GraphWriter
<SelectionDAG
*> &GW
) {
131 GW
.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
132 if (G
->getRoot().getNode())
133 GW
.emitEdge(0, -1, G
->getRoot().getNode(), G
->getRoot().getResNo(),
134 "color=blue,style=dashed");
139 std::string DOTGraphTraits
<SelectionDAG
*>::getNodeLabel(const SDNode
*Node
,
140 const SelectionDAG
*G
) {
141 return DOTGraphTraits
<SelectionDAG
*>::getSimpleNodeLabel(Node
, G
);
145 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
146 /// rendered using 'dot'.
148 void SelectionDAG::viewGraph(const std::string
&Title
) {
149 // This code is only for debugging!
151 ViewGraph(this, "dag." + getMachineFunction().getFunction()->getNameStr(),
154 errs() << "SelectionDAG::viewGraph is only available in debug builds on "
155 << "systems with Graphviz or gv!\n";
159 // This overload is defined out-of-line here instead of just using a
160 // default parameter because this is easiest for gdb to call.
161 void SelectionDAG::viewGraph() {
165 /// clearGraphAttrs - Clear all previously defined node graph attributes.
166 /// Intended to be used from a debugging tool (eg. gdb).
167 void SelectionDAG::clearGraphAttrs() {
169 NodeGraphAttrs
.clear();
171 errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds"
172 << " on systems with Graphviz or gv!\n";
177 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
179 void SelectionDAG::setGraphAttrs(const SDNode
*N
, const char *Attrs
) {
181 NodeGraphAttrs
[N
] = Attrs
;
183 errs() << "SelectionDAG::setGraphAttrs is only available in debug builds"
184 << " on systems with Graphviz or gv!\n";
189 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
190 /// Used from getNodeAttributes.
191 const std::string
SelectionDAG::getGraphAttrs(const SDNode
*N
) const {
193 std::map
<const SDNode
*, std::string
>::const_iterator I
=
194 NodeGraphAttrs
.find(N
);
196 if (I
!= NodeGraphAttrs
.end())
201 errs() << "SelectionDAG::getGraphAttrs is only available in debug builds"
202 << " on systems with Graphviz or gv!\n";
203 return std::string();
207 /// setGraphColor - Convenience for setting node color attribute.
209 void SelectionDAG::setGraphColor(const SDNode
*N
, const char *Color
) {
211 NodeGraphAttrs
[N
] = std::string("color=") + Color
;
213 errs() << "SelectionDAG::setGraphColor is only available in debug builds"
214 << " on systems with Graphviz or gv!\n";
218 /// setSubgraphColorHelper - Implement setSubgraphColor. Return
219 /// whether we truncated the search.
221 bool SelectionDAG::setSubgraphColorHelper(SDNode
*N
, const char *Color
, DenseSet
<SDNode
*> &visited
,
222 int level
, bool &printed
) {
223 bool hit_limit
= false;
229 DEBUG(dbgs() << "setSubgraphColor hit max level\n");
234 unsigned oldSize
= visited
.size();
236 if (visited
.size() != oldSize
) {
237 setGraphColor(N
, Color
);
238 for(SDNodeIterator i
= SDNodeIterator::begin(N
), iend
= SDNodeIterator::end(N
);
241 hit_limit
= setSubgraphColorHelper(*i
, Color
, visited
, level
+1, printed
) || hit_limit
;
245 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
246 << " on systems with Graphviz or gv!\n";
251 /// setSubgraphColor - Convenience for setting subgraph color attribute.
253 void SelectionDAG::setSubgraphColor(SDNode
*N
, const char *Color
) {
255 DenseSet
<SDNode
*> visited
;
256 bool printed
= false;
257 if (setSubgraphColorHelper(N
, Color
, visited
, 0, printed
)) {
258 // Visually mark that we hit the limit
259 if (strcmp(Color
, "red") == 0) {
260 setSubgraphColorHelper(N
, "blue", visited
, 0, printed
);
261 } else if (strcmp(Color
, "yellow") == 0) {
262 setSubgraphColorHelper(N
, "green", visited
, 0, printed
);
267 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
268 << " on systems with Graphviz or gv!\n";
272 std::string
ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit
*SU
) const {
274 raw_string_ostream
O(s
);
275 O
<< "SU(" << SU
->NodeNum
<< "): ";
277 SmallVector
<SDNode
*, 4> GluedNodes
;
278 for (SDNode
*N
= SU
->getNode(); N
; N
= N
->getGluedNode())
279 GluedNodes
.push_back(N
);
280 while (!GluedNodes
.empty()) {
281 O
<< DOTGraphTraits
<SelectionDAG
*>
282 ::getSimpleNodeLabel(GluedNodes
.back(), DAG
);
283 GluedNodes
.pop_back();
284 if (!GluedNodes
.empty())
288 O
<< "CROSS RC COPY";
293 void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter
<ScheduleDAG
*> &GW
) const {
295 // Draw a special "GraphRoot" node to indicate the root of the graph.
296 GW
.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
297 const SDNode
*N
= DAG
->getRoot().getNode();
298 if (N
&& N
->getNodeId() != -1)
299 GW
.emitEdge(0, -1, &SUnits
[N
->getNodeId()], -1,
300 "color=blue,style=dashed");