From cbb2ee9062f2d9a66769688e67f79ae02ffa1ed6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 28 Aug 2007 20:32:58 +0000 Subject: [PATCH] Add an option, -view-sunit-dags, for viewing the actual SUnit DAGs used by scheduling. llvm-svn: 41556 --- include/llvm/CodeGen/ScheduleDAG.h | 68 ++++++++++++++++++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 8 ++- .../SelectionDAG/SelectionDAGPrinter.cpp | 70 +++++++++++++++++++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index d52936abab6..fdae9273e78 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -17,6 +17,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallSet.h" namespace llvm { @@ -191,6 +192,11 @@ namespace llvm { virtual ~ScheduleDAG() {} + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered + /// using 'dot'. + /// + void viewGraph(); + /// Run - perform scheduling. /// MachineBasicBlock *Run(); @@ -315,6 +321,68 @@ namespace llvm { ScheduleDAG* createDefaultScheduler(SelectionDAGISel *IS, SelectionDAG *DAG, MachineBasicBlock *BB); + + class SUnitIterator : public forward_iterator { + SUnit *Node; + unsigned Operand; + + SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {} + public: + bool operator==(const SUnitIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SUnitIterator& x) const { return !operator==(x); } + + const SUnitIterator &operator=(const SUnitIterator &I) { + assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->Preds[Operand].first; + } + pointer operator->() const { return operator*(); } + + SUnitIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SUnitIterator operator++(int) { // Postincrement + SUnitIterator tmp = *this; ++*this; return tmp; + } + + static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); } + static SUnitIterator end (SUnit *N) { + return SUnitIterator(N, N->Preds.size()); + } + + unsigned getOperand() const { return Operand; } + const SUnit *getNode() const { return Node; } + bool isChain() const { return Node->Preds[Operand].second; } + }; + + template <> struct GraphTraits { + typedef SUnit NodeType; + typedef SUnitIterator ChildIteratorType; + static inline NodeType *getEntryNode(SUnit *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SUnitIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SUnitIterator::end(N); + } + }; + + template <> struct GraphTraits : public GraphTraits { + typedef std::vector::iterator nodes_iterator; + static nodes_iterator nodes_begin(ScheduleDAG *G) { + return G->SUnits.begin(); + } + static nodes_iterator nodes_end(ScheduleDAG *G) { + return G->SUnits.end(); + } + }; } #endif diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 92e34bbc48f..60a9cd1def4 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -54,8 +54,11 @@ ViewISelDAGs("view-isel-dags", cl::Hidden, static cl::opt ViewSchedDAGs("view-sched-dags", cl::Hidden, cl::desc("Pop up a window to show sched dags as they are processed")); +static cl::opt +ViewSUnitDAGs("view-sunit-dags", cl::Hidden, + cl::desc("Pop up a window to show SUnit dags after they are processed")); #else -static const bool ViewISelDAGs = 0, ViewSchedDAGs = 0; +static const bool ViewISelDAGs = 0, ViewSchedDAGs = 0, ViewSUnitDAGs = 0; #endif //===---------------------------------------------------------------------===// @@ -4842,6 +4845,9 @@ void SelectionDAGISel::ScheduleAndEmitDAG(SelectionDAG &DAG) { ScheduleDAG *SL = Ctor(this, &DAG, BB); BB = SL->Run(); + + if (ViewSUnitDAGs) SL->viewGraph(); + delete SL; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp index 12b56826248..0ce46fdf041 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -15,6 +15,7 @@ #include "llvm/Function.h" #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Target/MRegisterInfo.h" @@ -243,3 +244,72 @@ void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) { #endif } +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(const ScheduleDAG *G) { + return DOTGraphTraits::getGraphName(&G->DAG); + } + + static bool renderGraphFromBottomUp() { + return true; + } + + static bool hasNodeAddressLabel(const SUnit *Node, + const ScheduleDAG *Graph) { + return true; + } + + /// If you want to override the dot attributes printed for a particular + /// edge, override this method. + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + if (EI.isChain()) + return "color=blue,style=dashed"; + return ""; + } + + + static std::string getNodeLabel(const SUnit *Node, + const ScheduleDAG *Graph); + static std::string getNodeAttributes(const SUnit *N, + const ScheduleDAG *Graph) { + return "shape=Mrecord"; + } + + static void addCustomGraphFeatures(ScheduleDAG *G, + GraphWriter &GW) { + GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); + if (G->DAG.getRoot().Val) + GW.emitEdge(0, -1, G->SUnitMap[G->DAG.getRoot().Val], -1, ""); + } + }; +} + +std::string DOTGraphTraits::getNodeLabel(const SUnit *SU, + const ScheduleDAG *G) { + std::string Op; + + for (unsigned i = 0; i < SU->FlaggedNodes.size(); ++i) { + Op += DOTGraphTraits::getNodeLabel(SU->FlaggedNodes[i], + &G->DAG) + "\n"; + } + + Op += DOTGraphTraits::getNodeLabel(SU->Node, &G->DAG); + + return Op; +} + + +/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG +/// rendered using 'dot'. +/// +void ScheduleDAG::viewGraph() { +// This code is only for debugging! +#ifndef NDEBUG + ViewGraph(this, "dag." + DAG.getMachineFunction().getFunction()->getName()); +#else + cerr << "ScheduleDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +}