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