xref: /llvm-project/llvm/lib/Analysis/DDGPrinter.cpp (revision d86a206f06a51c12a9fcf2c20199f4e819751c0c)
16eff1278SBardia Mahjour //===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//
26eff1278SBardia Mahjour //
36eff1278SBardia Mahjour // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46eff1278SBardia Mahjour // See https://llvm.org/LICENSE.txt for license information.
56eff1278SBardia Mahjour // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66eff1278SBardia Mahjour //
76eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
86eff1278SBardia Mahjour 
96eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
106eff1278SBardia Mahjour //
116eff1278SBardia Mahjour // This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format
126eff1278SBardia Mahjour // in a file named `ddg.<graph-name>.dot` for each loop  in a function.
136eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
146eff1278SBardia Mahjour 
156eff1278SBardia Mahjour #include "llvm/Analysis/DDGPrinter.h"
166eff1278SBardia Mahjour #include "llvm/Support/CommandLine.h"
176eff1278SBardia Mahjour #include "llvm/Support/GraphWriter.h"
186eff1278SBardia Mahjour 
196eff1278SBardia Mahjour using namespace llvm;
206eff1278SBardia Mahjour 
21*d86a206fSFangrui Song static cl::opt<bool> DotOnly("dot-ddg-only", cl::Hidden,
22*d86a206fSFangrui Song                              cl::desc("simple ddg dot graph"));
236eff1278SBardia Mahjour static cl::opt<std::string> DDGDotFilenamePrefix(
246eff1278SBardia Mahjour     "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden,
256eff1278SBardia Mahjour     cl::desc("The prefix used for the DDG dot file names."));
266eff1278SBardia Mahjour 
276eff1278SBardia Mahjour static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false);
286eff1278SBardia Mahjour 
296eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
306eff1278SBardia Mahjour // Implementation of DDG DOT Printer for a loop
316eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater & U)326eff1278SBardia Mahjour PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
336eff1278SBardia Mahjour                                          LoopStandardAnalysisResults &AR,
346eff1278SBardia Mahjour                                          LPMUpdater &U) {
356eff1278SBardia Mahjour   writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly);
366eff1278SBardia Mahjour   return PreservedAnalyses::all();
376eff1278SBardia Mahjour }
386eff1278SBardia Mahjour 
writeDDGToDotFile(DataDependenceGraph & G,bool DOnly)396eff1278SBardia Mahjour static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) {
406eff1278SBardia Mahjour   std::string Filename =
416eff1278SBardia Mahjour       Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str();
426eff1278SBardia Mahjour   errs() << "Writing '" << Filename << "'...";
436eff1278SBardia Mahjour 
446eff1278SBardia Mahjour   std::error_code EC;
45518d955fSDuncan P. N. Exon Smith   raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
466eff1278SBardia Mahjour 
476eff1278SBardia Mahjour   if (!EC)
486eff1278SBardia Mahjour     // We only provide the constant verson of the DOTGraphTrait specialization,
496eff1278SBardia Mahjour     // hence the conversion to const pointer
506eff1278SBardia Mahjour     WriteGraph(File, (const DataDependenceGraph *)&G, DOnly);
516eff1278SBardia Mahjour   else
526eff1278SBardia Mahjour     errs() << "  error opening file for writing!";
536eff1278SBardia Mahjour   errs() << "\n";
546eff1278SBardia Mahjour }
556eff1278SBardia Mahjour 
566eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
576eff1278SBardia Mahjour // DDG DOT Printer Implementation
586eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
getNodeLabel(const DDGNode * Node,const DataDependenceGraph * Graph)596eff1278SBardia Mahjour std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node,
606eff1278SBardia Mahjour                                             const DataDependenceGraph *Graph) {
616eff1278SBardia Mahjour   if (isSimple())
626eff1278SBardia Mahjour     return getSimpleNodeLabel(Node, Graph);
636eff1278SBardia Mahjour   else
646eff1278SBardia Mahjour     return getVerboseNodeLabel(Node, Graph);
656eff1278SBardia Mahjour }
666eff1278SBardia Mahjour 
getEdgeAttributes(const DDGNode * Node,GraphTraits<const DDGNode * >::ChildIteratorType I,const DataDependenceGraph * G)676eff1278SBardia Mahjour std::string DDGDotGraphTraits::getEdgeAttributes(
686eff1278SBardia Mahjour     const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I,
696eff1278SBardia Mahjour     const DataDependenceGraph *G) {
706eff1278SBardia Mahjour   const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent());
716eff1278SBardia Mahjour   if (isSimple())
726eff1278SBardia Mahjour     return getSimpleEdgeAttributes(Node, E, G);
736eff1278SBardia Mahjour   else
746eff1278SBardia Mahjour     return getVerboseEdgeAttributes(Node, E, G);
756eff1278SBardia Mahjour }
766eff1278SBardia Mahjour 
isNodeHidden(const DDGNode * Node,const DataDependenceGraph * Graph)776eff1278SBardia Mahjour bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,
786eff1278SBardia Mahjour                                      const DataDependenceGraph *Graph) {
796eff1278SBardia Mahjour   if (isSimple() && isa<RootDDGNode>(Node))
806eff1278SBardia Mahjour     return true;
816eff1278SBardia Mahjour   assert(Graph && "expected a valid graph pointer");
826eff1278SBardia Mahjour   return Graph->getPiBlock(*Node) != nullptr;
836eff1278SBardia Mahjour }
846eff1278SBardia Mahjour 
856eff1278SBardia Mahjour std::string
getSimpleNodeLabel(const DDGNode * Node,const DataDependenceGraph * G)866eff1278SBardia Mahjour DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,
876eff1278SBardia Mahjour                                       const DataDependenceGraph *G) {
886eff1278SBardia Mahjour   std::string Str;
896eff1278SBardia Mahjour   raw_string_ostream OS(Str);
906eff1278SBardia Mahjour   if (isa<SimpleDDGNode>(Node))
916eff1278SBardia Mahjour     for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
926eff1278SBardia Mahjour       OS << *II << "\n";
936eff1278SBardia Mahjour   else if (isa<PiBlockDDGNode>(Node))
946eff1278SBardia Mahjour     OS << "pi-block\nwith\n"
956eff1278SBardia Mahjour        << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";
966eff1278SBardia Mahjour   else if (isa<RootDDGNode>(Node))
976eff1278SBardia Mahjour     OS << "root\n";
986eff1278SBardia Mahjour   else
996eff1278SBardia Mahjour     llvm_unreachable("Unimplemented type of node");
1006eff1278SBardia Mahjour   return OS.str();
1016eff1278SBardia Mahjour }
1026eff1278SBardia Mahjour 
1036eff1278SBardia Mahjour std::string
getVerboseNodeLabel(const DDGNode * Node,const DataDependenceGraph * G)1046eff1278SBardia Mahjour DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node,
1056eff1278SBardia Mahjour                                        const DataDependenceGraph *G) {
1066eff1278SBardia Mahjour   std::string Str;
1076eff1278SBardia Mahjour   raw_string_ostream OS(Str);
1086eff1278SBardia Mahjour   OS << "<kind:" << Node->getKind() << ">\n";
1096eff1278SBardia Mahjour   if (isa<SimpleDDGNode>(Node))
1106eff1278SBardia Mahjour     for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
1116eff1278SBardia Mahjour       OS << *II << "\n";
1126eff1278SBardia Mahjour   else if (isa<PiBlockDDGNode>(Node)) {
1136eff1278SBardia Mahjour     OS << "--- start of nodes in pi-block ---\n";
1146eff1278SBardia Mahjour     unsigned Count = 0;
1156eff1278SBardia Mahjour     const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes();
1166eff1278SBardia Mahjour     for (auto *PN : PNodes) {
1176eff1278SBardia Mahjour       OS << getVerboseNodeLabel(PN, G);
1186eff1278SBardia Mahjour       if (++Count != PNodes.size())
1196eff1278SBardia Mahjour         OS << "\n";
1206eff1278SBardia Mahjour     }
1216eff1278SBardia Mahjour     OS << "--- end of nodes in pi-block ---\n";
1226eff1278SBardia Mahjour   } else if (isa<RootDDGNode>(Node))
1236eff1278SBardia Mahjour     OS << "root\n";
1246eff1278SBardia Mahjour   else
1256eff1278SBardia Mahjour     llvm_unreachable("Unimplemented type of node");
1266eff1278SBardia Mahjour   return OS.str();
1276eff1278SBardia Mahjour }
1286eff1278SBardia Mahjour 
getSimpleEdgeAttributes(const DDGNode * Src,const DDGEdge * Edge,const DataDependenceGraph * G)1296eff1278SBardia Mahjour std::string DDGDotGraphTraits::getSimpleEdgeAttributes(
1306eff1278SBardia Mahjour     const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
1316eff1278SBardia Mahjour   std::string Str;
1326eff1278SBardia Mahjour   raw_string_ostream OS(Str);
1336eff1278SBardia Mahjour   DDGEdge::EdgeKind Kind = Edge->getKind();
1346eff1278SBardia Mahjour   OS << "label=\"[" << Kind << "]\"";
1356eff1278SBardia Mahjour   return OS.str();
1366eff1278SBardia Mahjour }
1376eff1278SBardia Mahjour 
getVerboseEdgeAttributes(const DDGNode * Src,const DDGEdge * Edge,const DataDependenceGraph * G)1386eff1278SBardia Mahjour std::string DDGDotGraphTraits::getVerboseEdgeAttributes(
1396eff1278SBardia Mahjour     const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
1406eff1278SBardia Mahjour   std::string Str;
1416eff1278SBardia Mahjour   raw_string_ostream OS(Str);
1426eff1278SBardia Mahjour   DDGEdge::EdgeKind Kind = Edge->getKind();
1436eff1278SBardia Mahjour   OS << "label=\"[";
1446eff1278SBardia Mahjour   if (Kind == DDGEdge::EdgeKind::MemoryDependence)
1456eff1278SBardia Mahjour     OS << G->getDependenceString(*Src, Edge->getTargetNode());
1466eff1278SBardia Mahjour   else
1476eff1278SBardia Mahjour     OS << Kind;
1486eff1278SBardia Mahjour   OS << "]\"";
1496eff1278SBardia Mahjour   return OS.str();
1506eff1278SBardia Mahjour }
151