SelectionDAGPrinter.cpp revision ec6ffc713f5f6e584debda7c55e1b37652e63617
1//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This implements the SelectionDAG::viewGraph method.
11//
12//===----------------------------------------------------------------------===//
13
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"
32#include <fstream>
33using namespace llvm;
34
35namespace llvm {
36  template<>
37  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
38    static bool hasEdgeDestLabels() {
39      return true;
40    }
41
42    static unsigned numEdgeDestLabels(const void *Node) {
43      return ((const SDNode *) Node)->getNumValues();
44    }
45
46    static std::string getEdgeDestLabel(const void *Node, unsigned i) {
47      return ((const SDNode *) Node)->getValueType(i).getMVTString();
48    }
49
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) {
55      return true;
56    }
57
58    /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
59    /// called to determine which outgoing edge of Node is the target of this
60    /// edge.
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());
66      return NI;
67    }
68
69    static std::string getGraphName(const SelectionDAG *G) {
70      return G->getMachineFunction().getFunction()->getName();
71    }
72
73    static bool renderGraphFromBottomUp() {
74      return true;
75    }
76
77    static bool hasNodeAddressLabel(const SDNode *Node,
78                                    const SelectionDAG *Graph) {
79      return true;
80    }
81
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();
88      if (VT == MVT::Flag)
89        return "color=red,style=bold";
90      else if (VT == MVT::Other)
91        return "color=blue,style=dashed";
92      return "";
93    }
94
95
96    static std::string getNodeLabel(const SDNode *Node,
97                                    const SelectionDAG *Graph);
98    static std::string getNodeAttributes(const SDNode *N,
99                                         const SelectionDAG *Graph) {
100#ifndef NDEBUG
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;
105        else
106          return Attrs;
107      }
108#endif
109      return "shape=Mrecord";
110    }
111
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");
118    }
119  };
120}
121
122std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
123                                                        const SelectionDAG *G) {
124  std::string Op = Node->getOperationName(G);
125
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()) {
134      if (Offset > 0)
135        Op += "+" + itostr(Offset);
136      else
137        Op += itostr(Offset);
138    }
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()) {
145      Op += '<';
146      {
147        raw_string_ostream OSS(Op);
148        OSS << *CP->getMachineCPVal();
149      }
150      Op += '>';
151    } else {
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()) + ">";
156      else {
157        Op += '<';
158        {
159          raw_string_ostream OSS(Op);
160          WriteAsOperand(OSS, CP->getConstVal(), false);
161        }
162        Op += '>';
163      }
164    }
165    Op += " A=" + itostr(1 << CP->getAlignment());
166  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
167    Op = "BB: ";
168    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
169    if (LBB)
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())) {
175      Op = Op + " " +
176        G->getTarget().getRegisterInfo()->getName(R->getReg());
177    } else {
178      Op += " #" + utostr(R->getReg());
179    }
180  } else if (const DbgStopPointSDNode *D = dyn_cast<DbgStopPointSDNode>(Node)) {
181    DICompileUnit CU(cast<GlobalVariable>(D->getCompileUnit()));
182    const char *FN = CU.getFilename();
183    Op += ": " + std::string(FN ? 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());
191    if (C->isVarArg())
192      Op += ", isVarArg";
193    if (C->isTailCall())
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)) {
199    if (M->getValue())
200      Op += "<" + M->getValue()->getName() + ">";
201    else
202      Op += "<null>";
203  } else if (const MemOperandSDNode *M = dyn_cast<MemOperandSDNode>(Node)) {
204    const Value *V = M->MO.getValue();
205    Op += '<';
206    if (!V) {
207      Op += "(unknown)";
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);
211      PSV->print(OSS);
212    } else {
213      Op += V->getName();
214    }
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)) {
221    bool doExt = true;
222    switch (LD->getExtensionType()) {
223    default: doExt = false; break;
224    case ISD::EXTLOAD:
225      Op = Op + "<anyext ";
226      break;
227    case ISD::SEXTLOAD:
228      Op = Op + " <sext ";
229      break;
230    case ISD::ZEXTLOAD:
231      Op = Op + " <zext ";
232      break;
233    }
234    if (doExt)
235      Op += LD->getMemoryVT().getMVTString() + ">";
236    if (LD->isVolatile())
237      Op += "<V>";
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())
245      Op += "<V>";
246    Op += ST->getIndexedModeName(ST->getAddressingMode());
247    if (ST->getAlignment() > 1)
248      Op += " A=" + utostr(ST->getAlignment());
249  }
250
251#if 0
252  Op += " Id=" + itostr(Node->getNodeId());
253#endif
254
255  return Op;
256}
257
258
259/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
260/// rendered using 'dot'.
261///
262void SelectionDAG::viewGraph(const std::string &Title) {
263// This code is only for debugging!
264#ifndef NDEBUG
265  ViewGraph(this, "dag." + getMachineFunction().getFunction()->getName(),
266            Title);
267#else
268  cerr << "SelectionDAG::viewGraph is only available in debug builds on "
269       << "systems with Graphviz or gv!\n";
270#endif  // NDEBUG
271}
272
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.
275void SelectionDAG::viewGraph() {
276  viewGraph("");
277}
278
279/// clearGraphAttrs - Clear all previously defined node graph attributes.
280/// Intended to be used from a debugging tool (eg. gdb).
281void SelectionDAG::clearGraphAttrs() {
282#ifndef NDEBUG
283  NodeGraphAttrs.clear();
284#else
285  cerr << "SelectionDAG::clearGraphAttrs is only available in debug builds"
286       << " on systems with Graphviz or gv!\n";
287#endif
288}
289
290
291/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
292///
293void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
294#ifndef NDEBUG
295  NodeGraphAttrs[N] = Attrs;
296#else
297  cerr << "SelectionDAG::setGraphAttrs is only available in debug builds"
298       << " on systems with Graphviz or gv!\n";
299#endif
300}
301
302
303/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
304/// Used from getNodeAttributes.
305const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
306#ifndef NDEBUG
307  std::map<const SDNode *, std::string>::const_iterator I =
308    NodeGraphAttrs.find(N);
309
310  if (I != NodeGraphAttrs.end())
311    return I->second;
312  else
313    return "";
314#else
315  cerr << "SelectionDAG::getGraphAttrs is only available in debug builds"
316       << " on systems with Graphviz or gv!\n";
317  return std::string("");
318#endif
319}
320
321/// setGraphColor - Convenience for setting node color attribute.
322///
323void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
324#ifndef NDEBUG
325  NodeGraphAttrs[N] = std::string("color=") + Color;
326#else
327  cerr << "SelectionDAG::setGraphColor is only available in debug builds"
328       << " on systems with Graphviz or gv!\n";
329#endif
330}
331
332/// setSubgraphColorHelper - Implement setSubgraphColor.  Return
333/// whether we truncated the search.
334///
335bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
336                                          int level, bool &printed) {
337  bool hit_limit = false;
338
339#ifndef NDEBUG
340  if (level >= 20) {
341    if (!printed) {
342      printed = true;
343      DOUT << "setSubgraphColor hit max level\n";
344    }
345    return true;
346  }
347
348  unsigned oldSize = visited.size();
349  visited.insert(N);
350  if (visited.size() != oldSize) {
351    setGraphColor(N, Color);
352    for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);
353        i != iend;
354        ++i) {
355      hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;
356    }
357  }
358#else
359  cerr << "SelectionDAG::setSubgraphColor is only available in debug builds"
360       << " on systems with Graphviz or gv!\n";
361#endif
362  return hit_limit;
363}
364
365/// setSubgraphColor - Convenience for setting subgraph color attribute.
366///
367void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
368#ifndef NDEBUG
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);
375    }
376    else if (strcmp(Color, "yellow") == 0) {
377      setSubgraphColorHelper(N, "green", visited, 0, printed);
378    }
379  }
380
381#else
382  cerr << "SelectionDAG::setSubgraphColor is only available in debug builds"
383       << " on systems with Graphviz or gv!\n";
384#endif
385}
386
387std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
388  std::string s;
389  raw_string_ostream O(s);
390  O << "SU(" << SU->NodeNum << "): ";
391  if (SU->getNode()) {
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())
399        O << "\n    ";
400    }
401  } else {
402    O << "CROSS RC COPY";
403  }
404  return O.str();
405}
406
407void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {
408  if (DAG) {
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");
415  }
416}
417