1*da58b97aSjoerg //===- GIMatchDag.cpp - A DAG representation of a pattern to be matched ---===//
2*da58b97aSjoerg //
3*da58b97aSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*da58b97aSjoerg // See https://llvm.org/LICENSE.txt for license information.
5*da58b97aSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*da58b97aSjoerg //
7*da58b97aSjoerg //===----------------------------------------------------------------------===//
8*da58b97aSjoerg 
9*da58b97aSjoerg #include "GIMatchDag.h"
10*da58b97aSjoerg 
11*da58b97aSjoerg #include "llvm/Support/Format.h"
12*da58b97aSjoerg #include "llvm/TableGen/Record.h"
13*da58b97aSjoerg #include "../CodeGenInstruction.h"
14*da58b97aSjoerg 
15*da58b97aSjoerg using namespace llvm;
16*da58b97aSjoerg 
writeDOTGraph(raw_ostream & OS,StringRef ID) const17*da58b97aSjoerg void GIMatchDag::writeDOTGraph(raw_ostream &OS, StringRef ID) const {
18*da58b97aSjoerg   const auto writePorts = [&](StringRef Prefix,
19*da58b97aSjoerg                               const GIMatchDagOperandList &Operands) {
20*da58b97aSjoerg     StringRef Separator = "";
21*da58b97aSjoerg     OS << "{";
22*da58b97aSjoerg     for (const auto &Op : enumerate(Operands)) {
23*da58b97aSjoerg       OS << Separator << "<" << Prefix << format("%d", Op.index()) << ">"
24*da58b97aSjoerg          << "#" << Op.index() << " $" << Op.value().getName();
25*da58b97aSjoerg       Separator = "|";
26*da58b97aSjoerg     }
27*da58b97aSjoerg     OS << "}";
28*da58b97aSjoerg   };
29*da58b97aSjoerg 
30*da58b97aSjoerg   OS << "digraph \"" << ID << "\" {\n"
31*da58b97aSjoerg      << "  rankdir=\"BT\"\n";
32*da58b97aSjoerg   for (const auto &N : InstrNodes) {
33*da58b97aSjoerg     OS << "  " << format("Node%p", &*N) << " [shape=record,label=\"{";
34*da58b97aSjoerg     writePorts("s", N->getOperandInfo());
35*da58b97aSjoerg     OS << "|" << N->getName();
36*da58b97aSjoerg     if (N->getOpcodeAnnotation())
37*da58b97aSjoerg       OS << "|" << N->getOpcodeAnnotation()->TheDef->getName();
38*da58b97aSjoerg     if (N->isMatchRoot())
39*da58b97aSjoerg       OS << "|Match starts here";
40*da58b97aSjoerg     OS << "|";
41*da58b97aSjoerg     SmallVector<std::pair<unsigned, StringRef>, 8> ToPrint;
42*da58b97aSjoerg     for (const auto &Assignment : N->user_assigned_operand_names())
43*da58b97aSjoerg       ToPrint.emplace_back(Assignment.first, Assignment.second);
44*da58b97aSjoerg     llvm::sort(ToPrint);
45*da58b97aSjoerg     StringRef Separator = "";
46*da58b97aSjoerg     for (const auto &Assignment : ToPrint) {
47*da58b97aSjoerg       OS << Separator << "$" << Assignment.second << "=getOperand("
48*da58b97aSjoerg          << Assignment.first << ")";
49*da58b97aSjoerg       Separator = ", ";
50*da58b97aSjoerg     }
51*da58b97aSjoerg     OS << format("|%p|", &N);
52*da58b97aSjoerg     writePorts("d", N->getOperandInfo());
53*da58b97aSjoerg     OS << "}\"";
54*da58b97aSjoerg     if (N->isMatchRoot())
55*da58b97aSjoerg       OS << ",color=red";
56*da58b97aSjoerg     OS << "]\n";
57*da58b97aSjoerg   }
58*da58b97aSjoerg 
59*da58b97aSjoerg   for (const auto &E : Edges) {
60*da58b97aSjoerg     const char *FromFmt = "Node%p:s%d:n";
61*da58b97aSjoerg     const char *ToFmt = "Node%p:d%d:s";
62*da58b97aSjoerg     if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
63*da58b97aSjoerg       std::swap(FromFmt, ToFmt);
64*da58b97aSjoerg     auto From = format(FromFmt, E->getFromMI(), E->getFromMO()->getIdx());
65*da58b97aSjoerg     auto To = format(ToFmt, E->getToMI(), E->getToMO()->getIdx());
66*da58b97aSjoerg     if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
67*da58b97aSjoerg       std::swap(From, To);
68*da58b97aSjoerg 
69*da58b97aSjoerg     OS << "  " << From << " -> " << To << " [label=\"$" << E->getName();
70*da58b97aSjoerg     if (E->getFromMO()->isDef() == E->getToMO()->isDef())
71*da58b97aSjoerg       OS << " INVALID EDGE!";
72*da58b97aSjoerg     OS << "\"";
73*da58b97aSjoerg     if (E->getFromMO()->isDef() == E->getToMO()->isDef())
74*da58b97aSjoerg       OS << ",color=red";
75*da58b97aSjoerg     else if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
76*da58b97aSjoerg       OS << ",dir=back,arrowtail=crow";
77*da58b97aSjoerg     OS << "]\n";
78*da58b97aSjoerg   }
79*da58b97aSjoerg 
80*da58b97aSjoerg   for (const auto &N : PredicateNodes) {
81*da58b97aSjoerg     OS << "  " << format("Pred%p", &*N) << " [shape=record,label=\"{";
82*da58b97aSjoerg     writePorts("s", N->getOperandInfo());
83*da58b97aSjoerg     OS << "|" << N->getName() << "|";
84*da58b97aSjoerg     N->printDescription(OS);
85*da58b97aSjoerg     OS << format("|%p|", &N);
86*da58b97aSjoerg     writePorts("d", N->getOperandInfo());
87*da58b97aSjoerg     OS << "}\",style=dotted]\n";
88*da58b97aSjoerg   }
89*da58b97aSjoerg 
90*da58b97aSjoerg   for (const auto &E : PredicateDependencies) {
91*da58b97aSjoerg     const char *FromMIFmt = "Node%p:e";
92*da58b97aSjoerg     const char *FromMOFmt = "Node%p:s%d:n";
93*da58b97aSjoerg     const char *ToFmt = "Pred%p:d%d:s";
94*da58b97aSjoerg     auto To = format(ToFmt, E->getPredicate(), E->getPredicateOp()->getIdx());
95*da58b97aSjoerg     auto Style = "[style=dotted]";
96*da58b97aSjoerg     if (E->getRequiredMO()) {
97*da58b97aSjoerg       auto From =
98*da58b97aSjoerg           format(FromMOFmt, E->getRequiredMI(), E->getRequiredMO()->getIdx());
99*da58b97aSjoerg       OS << "  " << From << " -> " << To << " " << Style << "\n";
100*da58b97aSjoerg       continue;
101*da58b97aSjoerg     }
102*da58b97aSjoerg     auto From = format(FromMIFmt, E->getRequiredMI());
103*da58b97aSjoerg     OS << "  " << From << " -> " << To << " " << Style << "\n";
104*da58b97aSjoerg   }
105*da58b97aSjoerg 
106*da58b97aSjoerg   OS << "}\n";
107*da58b97aSjoerg }
108*da58b97aSjoerg 
print(raw_ostream & OS) const109*da58b97aSjoerg LLVM_DUMP_METHOD void GIMatchDag::print(raw_ostream &OS) const {
110*da58b97aSjoerg   OS << "matchdag {\n";
111*da58b97aSjoerg   for (const auto &N : InstrNodes) {
112*da58b97aSjoerg     OS << "  ";
113*da58b97aSjoerg     N->print(OS);
114*da58b97aSjoerg     OS << "\n";
115*da58b97aSjoerg   }
116*da58b97aSjoerg   for (const auto &E : Edges) {
117*da58b97aSjoerg     OS << "  ";
118*da58b97aSjoerg     E->print(OS);
119*da58b97aSjoerg     OS << "\n";
120*da58b97aSjoerg   }
121*da58b97aSjoerg 
122*da58b97aSjoerg   for (const auto &P : PredicateNodes) {
123*da58b97aSjoerg     OS << "  ";
124*da58b97aSjoerg     P->print(OS);
125*da58b97aSjoerg     OS << "\n";
126*da58b97aSjoerg   }
127*da58b97aSjoerg   for (const auto &D : PredicateDependencies) {
128*da58b97aSjoerg     OS << "  ";
129*da58b97aSjoerg     D->print(OS);
130*da58b97aSjoerg     OS << "\n";
131*da58b97aSjoerg   }
132*da58b97aSjoerg   OS << "}\n";
133*da58b97aSjoerg }
134*da58b97aSjoerg 
operator <<(raw_ostream & OS,const GIMatchDag & G)135*da58b97aSjoerg raw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) {
136*da58b97aSjoerg   G.print(OS);
137*da58b97aSjoerg   return OS;
138*da58b97aSjoerg }
139