Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DDG] Data Dependence Graph - DOT printer
This patch implements a DDG printer pass that generates a graph in the DOT description language, providing a more visually appealing representation of the DDG. Similar to the CFG DOT printer, this functionality is provided under an option called -dot-ddg and can be generated in a less verbose mode under -dot-ddg-only option. Differential Revision: https://reviews.llvm.org/D90159
- Loading branch information
Showing
14 changed files
with
284 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//===- llvm/Analysis/DDGPrinter.h -------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file defines the DOT printer for the Data-Dependence Graph (DDG). | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_ANALYSIS_DDGPRINTER_H | ||
#define LLVM_ANALYSIS_DDGPRINTER_H | ||
|
||
#include "llvm/Analysis/DDG.h" | ||
#include "llvm/Pass.h" | ||
#include "llvm/Support/DOTGraphTraits.h" | ||
|
||
namespace llvm { | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Implementation of DDG DOT Printer for a loop. | ||
//===--------------------------------------------------------------------===// | ||
class DDGDotPrinterPass : public PassInfoMixin<DDGDotPrinterPass> { | ||
public: | ||
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, | ||
LoopStandardAnalysisResults &AR, LPMUpdater &U); | ||
}; | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Specialization of DOTGraphTraits. | ||
//===--------------------------------------------------------------------===// | ||
template <> | ||
struct DOTGraphTraits<const DataDependenceGraph *> | ||
: public DefaultDOTGraphTraits { | ||
|
||
DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {} | ||
|
||
/// Generate a title for the graph in DOT format | ||
std::string getGraphName(const DataDependenceGraph *G) { | ||
assert(G && "expected a valid pointer to the graph."); | ||
return "DDG for '" + std::string(G->getName()) + "'"; | ||
} | ||
|
||
/// Print a DDG node either in concise form (-ddg-dot-only) or | ||
/// verbose mode (-ddg-dot). | ||
std::string getNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *Graph); | ||
|
||
/// Print attributes of an edge in the DDG graph. If the edge | ||
/// is a MemoryDependence edge, then detailed dependence info | ||
/// available from DependenceAnalysis is displayed. | ||
std::string | ||
getEdgeAttributes(const DDGNode *Node, | ||
GraphTraits<const DDGNode *>::ChildIteratorType I, | ||
const DataDependenceGraph *G); | ||
|
||
/// Do not print nodes that are part of a pi-block separately. They | ||
/// will be printed when their containing pi-block is being printed. | ||
bool isNodeHidden(const DDGNode *Node, const DataDependenceGraph *G); | ||
|
||
private: | ||
/// Print a DDG node in concise form. | ||
static std::string getSimpleNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *G); | ||
|
||
/// Print a DDG node with more information including containing instructions | ||
/// and detailed information about the dependence edges. | ||
static std::string getVerboseNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *G); | ||
|
||
/// Print a DDG edge in concise form. | ||
static std::string getSimpleEdgeAttributes(const DDGNode *Src, | ||
const DDGEdge *Edge, | ||
const DataDependenceGraph *G); | ||
|
||
/// Print a DDG edge with more information including detailed information | ||
/// about the dependence edges. | ||
static std::string getVerboseEdgeAttributes(const DDGNode *Src, | ||
const DDGEdge *Edge, | ||
const DataDependenceGraph *G); | ||
}; | ||
|
||
using DDGDotGraphTraits = struct DOTGraphTraits<const DataDependenceGraph *>; | ||
|
||
} // namespace llvm | ||
|
||
#endif // LLVM_ANALYSIS_DDGPRINTER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
//===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format | ||
// in a file named `ddg.<graph-name>.dot` for each loop in a function. | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/Analysis/DDGPrinter.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/Support/GraphWriter.h" | ||
|
||
using namespace llvm; | ||
|
||
static cl::opt<bool> DotOnly("dot-ddg-only", cl::init(false), cl::Hidden, | ||
cl::ZeroOrMore, cl::desc("simple ddg dot graph")); | ||
static cl::opt<std::string> DDGDotFilenamePrefix( | ||
"dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden, | ||
cl::desc("The prefix used for the DDG dot file names.")); | ||
|
||
static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false); | ||
|
||
//===--------------------------------------------------------------------===// | ||
// Implementation of DDG DOT Printer for a loop | ||
//===--------------------------------------------------------------------===// | ||
PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM, | ||
LoopStandardAnalysisResults &AR, | ||
LPMUpdater &U) { | ||
writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly); | ||
return PreservedAnalyses::all(); | ||
} | ||
|
||
static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) { | ||
std::string Filename = | ||
Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str(); | ||
errs() << "Writing '" << Filename << "'..."; | ||
|
||
std::error_code EC; | ||
raw_fd_ostream File(Filename, EC, sys::fs::F_Text); | ||
|
||
if (!EC) | ||
// We only provide the constant verson of the DOTGraphTrait specialization, | ||
// hence the conversion to const pointer | ||
WriteGraph(File, (const DataDependenceGraph *)&G, DOnly); | ||
else | ||
errs() << " error opening file for writing!"; | ||
errs() << "\n"; | ||
} | ||
|
||
//===--------------------------------------------------------------------===// | ||
// DDG DOT Printer Implementation | ||
//===--------------------------------------------------------------------===// | ||
std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *Graph) { | ||
if (isSimple()) | ||
return getSimpleNodeLabel(Node, Graph); | ||
else | ||
return getVerboseNodeLabel(Node, Graph); | ||
} | ||
|
||
std::string DDGDotGraphTraits::getEdgeAttributes( | ||
const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I, | ||
const DataDependenceGraph *G) { | ||
const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent()); | ||
if (isSimple()) | ||
return getSimpleEdgeAttributes(Node, E, G); | ||
else | ||
return getVerboseEdgeAttributes(Node, E, G); | ||
} | ||
|
||
bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node, | ||
const DataDependenceGraph *Graph) { | ||
if (isSimple() && isa<RootDDGNode>(Node)) | ||
return true; | ||
assert(Graph && "expected a valid graph pointer"); | ||
return Graph->getPiBlock(*Node) != nullptr; | ||
} | ||
|
||
std::string | ||
DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *G) { | ||
std::string Str; | ||
raw_string_ostream OS(Str); | ||
if (isa<SimpleDDGNode>(Node)) | ||
for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions()) | ||
OS << *II << "\n"; | ||
else if (isa<PiBlockDDGNode>(Node)) | ||
OS << "pi-block\nwith\n" | ||
<< cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n"; | ||
else if (isa<RootDDGNode>(Node)) | ||
OS << "root\n"; | ||
else | ||
llvm_unreachable("Unimplemented type of node"); | ||
return OS.str(); | ||
} | ||
|
||
std::string | ||
DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node, | ||
const DataDependenceGraph *G) { | ||
std::string Str; | ||
raw_string_ostream OS(Str); | ||
OS << "<kind:" << Node->getKind() << ">\n"; | ||
if (isa<SimpleDDGNode>(Node)) | ||
for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions()) | ||
OS << *II << "\n"; | ||
else if (isa<PiBlockDDGNode>(Node)) { | ||
OS << "--- start of nodes in pi-block ---\n"; | ||
unsigned Count = 0; | ||
const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes(); | ||
for (auto *PN : PNodes) { | ||
OS << getVerboseNodeLabel(PN, G); | ||
if (++Count != PNodes.size()) | ||
OS << "\n"; | ||
} | ||
OS << "--- end of nodes in pi-block ---\n"; | ||
} else if (isa<RootDDGNode>(Node)) | ||
OS << "root\n"; | ||
else | ||
llvm_unreachable("Unimplemented type of node"); | ||
return OS.str(); | ||
} | ||
|
||
std::string DDGDotGraphTraits::getSimpleEdgeAttributes( | ||
const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) { | ||
std::string Str; | ||
raw_string_ostream OS(Str); | ||
DDGEdge::EdgeKind Kind = Edge->getKind(); | ||
OS << "label=\"[" << Kind << "]\""; | ||
return OS.str(); | ||
} | ||
|
||
std::string DDGDotGraphTraits::getVerboseEdgeAttributes( | ||
const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) { | ||
std::string Str; | ||
raw_string_ostream OS(Str); | ||
DDGEdge::EdgeKind Kind = Edge->getKind(); | ||
OS << "label=\"["; | ||
if (Kind == DDGEdge::EdgeKind::MemoryDependence) | ||
OS << G->getDependenceString(*Src, Edge->getTargetNode()); | ||
else | ||
OS << Kind; | ||
OS << "]\""; | ||
return OS.str(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.