1cde4d5a6SJacques Pienaar //===- Pattern.cpp - Pattern wrapper class --------------------------------===//
2eb753f4aSLei Zhang //
3eb753f4aSLei Zhang // Copyright 2019 The MLIR Authors.
4eb753f4aSLei Zhang //
5eb753f4aSLei Zhang // Licensed under the Apache License, Version 2.0 (the "License");
6eb753f4aSLei Zhang // you may not use this file except in compliance with the License.
7eb753f4aSLei Zhang // You may obtain a copy of the License at
8eb753f4aSLei Zhang //
9eb753f4aSLei Zhang //   http://www.apache.org/licenses/LICENSE-2.0
10eb753f4aSLei Zhang //
11eb753f4aSLei Zhang // Unless required by applicable law or agreed to in writing, software
12eb753f4aSLei Zhang // distributed under the License is distributed on an "AS IS" BASIS,
13eb753f4aSLei Zhang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14eb753f4aSLei Zhang // See the License for the specific language governing permissions and
15eb753f4aSLei Zhang // limitations under the License.
16eb753f4aSLei Zhang // =============================================================================
17eb753f4aSLei Zhang //
18eb753f4aSLei Zhang // Pattern wrapper class to simplify using TableGen Record defining a MLIR
19eb753f4aSLei Zhang // Pattern.
20eb753f4aSLei Zhang //
21eb753f4aSLei Zhang //===----------------------------------------------------------------------===//
22eb753f4aSLei Zhang 
23eb753f4aSLei Zhang #include "mlir/TableGen/Pattern.h"
24eb753f4aSLei Zhang #include "llvm/ADT/Twine.h"
25*1358df19SLei Zhang #include "llvm/Support/Debug.h"
2604b6d2f3SLei Zhang #include "llvm/Support/FormatVariadic.h"
278f5fa566SLei Zhang #include "llvm/TableGen/Error.h"
28eb753f4aSLei Zhang #include "llvm/TableGen/Record.h"
29eb753f4aSLei Zhang 
30*1358df19SLei Zhang #define DEBUG_TYPE "mlir-tblgen-pattern"
31*1358df19SLei Zhang 
32eb753f4aSLei Zhang using namespace mlir;
33eb753f4aSLei Zhang 
340ea6154bSJacques Pienaar using llvm::formatv;
35eb753f4aSLei Zhang using mlir::tblgen::Operator;
36eb753f4aSLei Zhang 
37ac68637bSLei Zhang //===----------------------------------------------------------------------===//
38ac68637bSLei Zhang // DagLeaf
39ac68637bSLei Zhang //===----------------------------------------------------------------------===//
40ac68637bSLei Zhang 
41e0774c00SLei Zhang bool tblgen::DagLeaf::isUnspecified() const {
42b9e38a79SLei Zhang   return dyn_cast_or_null<llvm::UnsetInit>(def);
43e0774c00SLei Zhang }
44e0774c00SLei Zhang 
45e0774c00SLei Zhang bool tblgen::DagLeaf::isOperandMatcher() const {
46e0774c00SLei Zhang   // Operand matchers specify a type constraint.
47b9e38a79SLei Zhang   return isSubClassOf("TypeConstraint");
48e0774c00SLei Zhang }
49e0774c00SLei Zhang 
50e0774c00SLei Zhang bool tblgen::DagLeaf::isAttrMatcher() const {
51c52a8127SFeng Liu   // Attribute matchers specify an attribute constraint.
52b9e38a79SLei Zhang   return isSubClassOf("AttrConstraint");
53e0774c00SLei Zhang }
54e0774c00SLei Zhang 
55d0e2019dSLei Zhang bool tblgen::DagLeaf::isNativeCodeCall() const {
56d0e2019dSLei Zhang   return isSubClassOf("NativeCodeCall");
57e0774c00SLei Zhang }
58e0774c00SLei Zhang 
59e0774c00SLei Zhang bool tblgen::DagLeaf::isConstantAttr() const {
60b9e38a79SLei Zhang   return isSubClassOf("ConstantAttr");
61b9e38a79SLei Zhang }
62b9e38a79SLei Zhang 
63b9e38a79SLei Zhang bool tblgen::DagLeaf::isEnumAttrCase() const {
649dd182e0SLei Zhang   return isSubClassOf("EnumAttrCaseInfo");
65e0774c00SLei Zhang }
66e0774c00SLei Zhang 
678f5fa566SLei Zhang tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const {
688f5fa566SLei Zhang   assert((isOperandMatcher() || isAttrMatcher()) &&
698f5fa566SLei Zhang          "the DAG leaf must be operand or attribute");
708f5fa566SLei Zhang   return Constraint(cast<llvm::DefInit>(def)->getDef());
71e0774c00SLei Zhang }
72e0774c00SLei Zhang 
73e0774c00SLei Zhang tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const {
74e0774c00SLei Zhang   assert(isConstantAttr() && "the DAG leaf must be constant attribute");
75e0774c00SLei Zhang   return ConstantAttr(cast<llvm::DefInit>(def));
76e0774c00SLei Zhang }
77e0774c00SLei Zhang 
78b9e38a79SLei Zhang tblgen::EnumAttrCase tblgen::DagLeaf::getAsEnumAttrCase() const {
79b9e38a79SLei Zhang   assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case");
80b9e38a79SLei Zhang   return EnumAttrCase(cast<llvm::DefInit>(def));
81b9e38a79SLei Zhang }
82b9e38a79SLei Zhang 
83e0774c00SLei Zhang std::string tblgen::DagLeaf::getConditionTemplate() const {
848f5fa566SLei Zhang   return getAsConstraint().getConditionTemplate();
85e0774c00SLei Zhang }
86e0774c00SLei Zhang 
87d0e2019dSLei Zhang llvm::StringRef tblgen::DagLeaf::getNativeCodeTemplate() const {
88d0e2019dSLei Zhang   assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
89d0e2019dSLei Zhang   return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression");
90eb753f4aSLei Zhang }
91eb753f4aSLei Zhang 
92b9e38a79SLei Zhang bool tblgen::DagLeaf::isSubClassOf(StringRef superclass) const {
93b9e38a79SLei Zhang   if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def))
94b9e38a79SLei Zhang     return defInit->getDef()->isSubClassOf(superclass);
95b9e38a79SLei Zhang   return false;
96b9e38a79SLei Zhang }
97b9e38a79SLei Zhang 
98*1358df19SLei Zhang void tblgen::DagLeaf::print(raw_ostream &os) const {
99*1358df19SLei Zhang   if (def)
100*1358df19SLei Zhang     def->print(os);
101*1358df19SLei Zhang }
102*1358df19SLei Zhang 
103ac68637bSLei Zhang //===----------------------------------------------------------------------===//
104ac68637bSLei Zhang // DagNode
105ac68637bSLei Zhang //===----------------------------------------------------------------------===//
106ac68637bSLei Zhang 
107d0e2019dSLei Zhang bool tblgen::DagNode::isNativeCodeCall() const {
108d0e2019dSLei Zhang   if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator()))
109d0e2019dSLei Zhang     return defInit->getDef()->isSubClassOf("NativeCodeCall");
110c52a8127SFeng Liu   return false;
111c52a8127SFeng Liu }
112c52a8127SFeng Liu 
113647f8cabSRiver Riddle bool tblgen::DagNode::isOperation() const {
114c72d849eSLei Zhang   return !(isNativeCodeCall() || isReplaceWithValue());
115647f8cabSRiver Riddle }
116647f8cabSRiver Riddle 
117d0e2019dSLei Zhang llvm::StringRef tblgen::DagNode::getNativeCodeTemplate() const {
118d0e2019dSLei Zhang   assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
119c52a8127SFeng Liu   return cast<llvm::DefInit>(node->getOperator())
120c52a8127SFeng Liu       ->getDef()
121d0e2019dSLei Zhang       ->getValueAsString("expression");
122c52a8127SFeng Liu }
123c52a8127SFeng Liu 
124e032d0dcSLei Zhang llvm::StringRef tblgen::DagNode::getSymbol() const {
125388fb375SJacques Pienaar   return node->getNameStr();
126388fb375SJacques Pienaar }
127388fb375SJacques Pienaar 
128eb753f4aSLei Zhang Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
129eb753f4aSLei Zhang   llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
1302dc6d205SLei Zhang   auto it = mapper->find(opDef);
1312dc6d205SLei Zhang   if (it != mapper->end())
1322dc6d205SLei Zhang     return *it->second;
13379f53b0cSJacques Pienaar   return *mapper->try_emplace(opDef, std::make_unique<Operator>(opDef))
1342dc6d205SLei Zhang               .first->second;
135eb753f4aSLei Zhang }
136eb753f4aSLei Zhang 
1372fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumOps() const {
1382fe8ae4fSJacques Pienaar   int count = isReplaceWithValue() ? 0 : 1;
1392fe8ae4fSJacques Pienaar   for (int i = 0, e = getNumArgs(); i != e; ++i) {
140eb753f4aSLei Zhang     if (auto child = getArgAsNestedDag(i))
141eb753f4aSLei Zhang       count += child.getNumOps();
142eb753f4aSLei Zhang   }
143eb753f4aSLei Zhang   return count;
144eb753f4aSLei Zhang }
145eb753f4aSLei Zhang 
1462fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); }
147eb753f4aSLei Zhang 
148eb753f4aSLei Zhang bool tblgen::DagNode::isNestedDagArg(unsigned index) const {
149eb753f4aSLei Zhang   return isa<llvm::DagInit>(node->getArg(index));
150eb753f4aSLei Zhang }
151eb753f4aSLei Zhang 
152eb753f4aSLei Zhang tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const {
153eb753f4aSLei Zhang   return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
154eb753f4aSLei Zhang }
155eb753f4aSLei Zhang 
156e0774c00SLei Zhang tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const {
157e0774c00SLei Zhang   assert(!isNestedDagArg(index));
158e0774c00SLei Zhang   return DagLeaf(node->getArg(index));
159eb753f4aSLei Zhang }
160eb753f4aSLei Zhang 
161eb753f4aSLei Zhang StringRef tblgen::DagNode::getArgName(unsigned index) const {
162eb753f4aSLei Zhang   return node->getArgNameStr(index);
163eb753f4aSLei Zhang }
164eb753f4aSLei Zhang 
165eb753f4aSLei Zhang bool tblgen::DagNode::isReplaceWithValue() const {
166eb753f4aSLei Zhang   auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
167eb753f4aSLei Zhang   return dagOpDef->getName() == "replaceWithValue";
168eb753f4aSLei Zhang }
169eb753f4aSLei Zhang 
170*1358df19SLei Zhang void tblgen::DagNode::print(raw_ostream &os) const {
171*1358df19SLei Zhang   if (node)
172*1358df19SLei Zhang     node->print(os);
173*1358df19SLei Zhang }
174*1358df19SLei Zhang 
175ac68637bSLei Zhang //===----------------------------------------------------------------------===//
176ac68637bSLei Zhang // SymbolInfoMap
177ac68637bSLei Zhang //===----------------------------------------------------------------------===//
178ac68637bSLei Zhang 
179ac68637bSLei Zhang StringRef tblgen::SymbolInfoMap::getValuePackName(StringRef symbol,
180ac68637bSLei Zhang                                                   int *index) {
181ac68637bSLei Zhang   StringRef name, indexStr;
182ac68637bSLei Zhang   int idx = -1;
183ac68637bSLei Zhang   std::tie(name, indexStr) = symbol.rsplit("__");
184ac68637bSLei Zhang 
185ac68637bSLei Zhang   if (indexStr.consumeInteger(10, idx)) {
186ac68637bSLei Zhang     // The second part is not an index; we return the whole symbol as-is.
187ac68637bSLei Zhang     return symbol;
188eb753f4aSLei Zhang   }
189ac68637bSLei Zhang   if (index) {
190ac68637bSLei Zhang     *index = idx;
191ac68637bSLei Zhang   }
192ac68637bSLei Zhang   return name;
193ac68637bSLei Zhang }
194ac68637bSLei Zhang 
195ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op,
196ac68637bSLei Zhang                                               SymbolInfo::Kind kind,
197ac68637bSLei Zhang                                               Optional<int> index)
198ac68637bSLei Zhang     : op(op), kind(kind), argIndex(index) {}
199ac68637bSLei Zhang 
200ac68637bSLei Zhang int tblgen::SymbolInfoMap::SymbolInfo::getStaticValueCount() const {
201ac68637bSLei Zhang   switch (kind) {
202ac68637bSLei Zhang   case Kind::Attr:
203ac68637bSLei Zhang   case Kind::Operand:
204ac68637bSLei Zhang   case Kind::Value:
205ac68637bSLei Zhang     return 1;
206ac68637bSLei Zhang   case Kind::Result:
207ac68637bSLei Zhang     return op->getNumResults();
208ac68637bSLei Zhang   }
20912ff145eSjpienaar   llvm_unreachable("unknown kind");
210ac68637bSLei Zhang }
211ac68637bSLei Zhang 
212ac68637bSLei Zhang std::string
213ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const {
214ac68637bSLei Zhang   switch (kind) {
215ac68637bSLei Zhang   case Kind::Attr: {
216ac68637bSLei Zhang     auto type =
217ac68637bSLei Zhang         op->getArg(*argIndex).get<NamedAttribute *>()->attr.getStorageType();
218ac68637bSLei Zhang     return formatv("{0} {1};\n", type, name);
219ac68637bSLei Zhang   }
22031cfee60SLei Zhang   case Kind::Operand: {
22131cfee60SLei Zhang     // Use operand range for captured operands (to support potential variadic
22231cfee60SLei Zhang     // operands).
22331cfee60SLei Zhang     return formatv("Operation::operand_range {0}(op0->getOperands());\n", name);
22431cfee60SLei Zhang   }
225ac68637bSLei Zhang   case Kind::Value: {
22631cfee60SLei Zhang     return formatv("ArrayRef<Value *> {0};\n", name);
227ac68637bSLei Zhang   }
228ac68637bSLei Zhang   case Kind::Result: {
22931cfee60SLei Zhang     // Use the op itself for captured results.
230ac68637bSLei Zhang     return formatv("{0} {1};\n", op->getQualCppClassName(), name);
231ac68637bSLei Zhang   }
232ac68637bSLei Zhang   }
23312ff145eSjpienaar   llvm_unreachable("unknown kind");
234ac68637bSLei Zhang }
235ac68637bSLei Zhang 
23631cfee60SLei Zhang std::string tblgen::SymbolInfoMap::SymbolInfo::getValueAndRangeUse(
23731cfee60SLei Zhang     StringRef name, int index, const char *fmt, const char *separator) const {
238*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "getValueAndRangeUse for '" << name << "': ");
23931cfee60SLei Zhang   switch (kind) {
24031cfee60SLei Zhang   case Kind::Attr: {
24131cfee60SLei Zhang     assert(index < 0);
242*1358df19SLei Zhang     auto repl = formatv(fmt, name);
243*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (Attr)\n");
244*1358df19SLei Zhang     return repl;
24531cfee60SLei Zhang   }
24631cfee60SLei Zhang   case Kind::Operand: {
24731cfee60SLei Zhang     assert(index < 0);
24831cfee60SLei Zhang     auto *operand = op->getArg(*argIndex).get<NamedTypeConstraint *>();
24931cfee60SLei Zhang     // If this operand is variadic, then return a range. Otherwise, return the
25031cfee60SLei Zhang     // value itself.
25131cfee60SLei Zhang     if (operand->isVariadic()) {
252*1358df19SLei Zhang       auto repl = formatv(fmt, name);
253*1358df19SLei Zhang       LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicOperand)\n");
254*1358df19SLei Zhang       return repl;
25531cfee60SLei Zhang     }
256*1358df19SLei Zhang     auto repl = formatv(fmt, formatv("(*{0}.begin())", name));
257*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (SingleOperand)\n");
258*1358df19SLei Zhang     return repl;
25931cfee60SLei Zhang   }
26031cfee60SLei Zhang   case Kind::Result: {
26131cfee60SLei Zhang     // If `index` is greater than zero, then we are referencing a specific
26231cfee60SLei Zhang     // result of a multi-result op. The result can still be variadic.
26331cfee60SLei Zhang     if (index >= 0) {
26431cfee60SLei Zhang       std::string v = formatv("{0}.getODSResults({1})", name, index);
26531cfee60SLei Zhang       if (!op->getResult(index).isVariadic())
26631cfee60SLei Zhang         v = formatv("(*{0}.begin())", v);
267*1358df19SLei Zhang       auto repl = formatv(fmt, v);
268*1358df19SLei Zhang       LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n");
269*1358df19SLei Zhang       return repl;
27031cfee60SLei Zhang     }
27131cfee60SLei Zhang 
27231cfee60SLei Zhang     // We are referencing all results of the multi-result op. A specific result
27331cfee60SLei Zhang     // can either be a value or a range. Then join them with `separator`.
27431cfee60SLei Zhang     SmallVector<std::string, 4> values;
27531cfee60SLei Zhang     values.reserve(op->getNumResults());
27631cfee60SLei Zhang 
27731cfee60SLei Zhang     for (int i = 0, e = op->getNumResults(); i < e; ++i) {
27831cfee60SLei Zhang       std::string v = formatv("{0}.getODSResults({1})", name, i);
27931cfee60SLei Zhang       if (!op->getResult(i).isVariadic()) {
28031cfee60SLei Zhang         v = formatv("(*{0}.begin())", v);
28131cfee60SLei Zhang       }
28231cfee60SLei Zhang       values.push_back(formatv(fmt, v));
28331cfee60SLei Zhang     }
284*1358df19SLei Zhang     auto repl = llvm::join(values, separator);
285*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n");
286*1358df19SLei Zhang     return repl;
28731cfee60SLei Zhang   }
28831cfee60SLei Zhang   case Kind::Value: {
28931cfee60SLei Zhang     assert(index < 0);
29031cfee60SLei Zhang     assert(op == nullptr);
291*1358df19SLei Zhang     auto repl = formatv(fmt, name);
292*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n");
293*1358df19SLei Zhang     return repl;
29431cfee60SLei Zhang   }
29531cfee60SLei Zhang   }
29694298ceaSLei Zhang   llvm_unreachable("unknown kind");
29731cfee60SLei Zhang }
29831cfee60SLei Zhang 
29931cfee60SLei Zhang std::string tblgen::SymbolInfoMap::SymbolInfo::getAllRangeUse(
30031cfee60SLei Zhang     StringRef name, int index, const char *fmt, const char *separator) const {
301*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "getAllRangeUse for '" << name << "': ");
302ac68637bSLei Zhang   switch (kind) {
303ac68637bSLei Zhang   case Kind::Attr:
304ac68637bSLei Zhang   case Kind::Operand: {
305ac68637bSLei Zhang     assert(index < 0 && "only allowed for symbol bound to result");
306*1358df19SLei Zhang     auto repl = formatv(fmt, name);
307*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (Operand/Attr)\n");
308*1358df19SLei Zhang     return repl;
309ac68637bSLei Zhang   }
310ac68637bSLei Zhang   case Kind::Result: {
311ac68637bSLei Zhang     if (index >= 0) {
312*1358df19SLei Zhang       auto repl = formatv(fmt, formatv("{0}.getODSResults({1})", name, index));
313*1358df19SLei Zhang       LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n");
314*1358df19SLei Zhang       return repl;
315ac68637bSLei Zhang     }
316ac68637bSLei Zhang 
31731cfee60SLei Zhang     // We are referencing all results of the multi-result op. Each result should
31831cfee60SLei Zhang     // have a value range, and then join them with `separator`.
319ac68637bSLei Zhang     SmallVector<std::string, 4> values;
32031cfee60SLei Zhang     values.reserve(op->getNumResults());
32131cfee60SLei Zhang 
322ac68637bSLei Zhang     for (int i = 0, e = op->getNumResults(); i < e; ++i) {
32331cfee60SLei Zhang       values.push_back(
32431cfee60SLei Zhang           formatv(fmt, formatv("{0}.getODSResults({1})", name, i)));
325ac68637bSLei Zhang     }
326*1358df19SLei Zhang     auto repl = llvm::join(values, separator);
327*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n");
328*1358df19SLei Zhang     return repl;
329ac68637bSLei Zhang   }
330ac68637bSLei Zhang   case Kind::Value: {
331ac68637bSLei Zhang     assert(index < 0 && "only allowed for symbol bound to result");
332ac68637bSLei Zhang     assert(op == nullptr);
333*1358df19SLei Zhang     auto repl = formatv(fmt, formatv("{{{0}}", name));
334*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n");
335*1358df19SLei Zhang     return repl;
336ac68637bSLei Zhang   }
337ac68637bSLei Zhang   }
33812ff145eSjpienaar   llvm_unreachable("unknown kind");
339ac68637bSLei Zhang }
340ac68637bSLei Zhang 
341ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpArgument(StringRef symbol, const Operator &op,
342ac68637bSLei Zhang                                            int argIndex) {
343ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
344ac68637bSLei Zhang   if (name != symbol) {
345ac68637bSLei Zhang     auto error = formatv(
346ac68637bSLei Zhang         "symbol '{0}' with trailing index cannot bind to op argument", symbol);
347ac68637bSLei Zhang     PrintFatalError(loc, error);
348ac68637bSLei Zhang   }
349ac68637bSLei Zhang 
350ac68637bSLei Zhang   auto symInfo = op.getArg(argIndex).is<NamedAttribute *>()
351ac68637bSLei Zhang                      ? SymbolInfo::getAttr(&op, argIndex)
352ac68637bSLei Zhang                      : SymbolInfo::getOperand(&op, argIndex);
353ac68637bSLei Zhang 
354ac68637bSLei Zhang   return symbolInfoMap.insert({symbol, symInfo}).second;
355ac68637bSLei Zhang }
356ac68637bSLei Zhang 
357ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) {
358ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
359ac68637bSLei Zhang   return symbolInfoMap.insert({name, SymbolInfo::getResult(&op)}).second;
360ac68637bSLei Zhang }
361ac68637bSLei Zhang 
362ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindValue(StringRef symbol) {
363ac68637bSLei Zhang   return symbolInfoMap.insert({symbol, SymbolInfo::getValue()}).second;
364ac68637bSLei Zhang }
365ac68637bSLei Zhang 
366ac68637bSLei Zhang bool tblgen::SymbolInfoMap::contains(StringRef symbol) const {
367ac68637bSLei Zhang   return find(symbol) != symbolInfoMap.end();
368ac68637bSLei Zhang }
369ac68637bSLei Zhang 
370ac68637bSLei Zhang tblgen::SymbolInfoMap::const_iterator
371ac68637bSLei Zhang tblgen::SymbolInfoMap::find(StringRef key) const {
372ac68637bSLei Zhang   StringRef name = getValuePackName(key);
373ac68637bSLei Zhang   return symbolInfoMap.find(name);
374ac68637bSLei Zhang }
375ac68637bSLei Zhang 
376ac68637bSLei Zhang int tblgen::SymbolInfoMap::getStaticValueCount(StringRef symbol) const {
377ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
378ac68637bSLei Zhang   if (name != symbol) {
379ac68637bSLei Zhang     // If there is a trailing index inside symbol, it references just one
380ac68637bSLei Zhang     // static value.
381ac68637bSLei Zhang     return 1;
382ac68637bSLei Zhang   }
383ac68637bSLei Zhang   // Otherwise, find how many it represents by querying the symbol's info.
384ac68637bSLei Zhang   return find(name)->getValue().getStaticValueCount();
385ac68637bSLei Zhang }
386ac68637bSLei Zhang 
38731cfee60SLei Zhang std::string
38831cfee60SLei Zhang tblgen::SymbolInfoMap::getValueAndRangeUse(StringRef symbol, const char *fmt,
38931cfee60SLei Zhang                                            const char *separator) const {
390ac68637bSLei Zhang   int index = -1;
391ac68637bSLei Zhang   StringRef name = getValuePackName(symbol, &index);
392ac68637bSLei Zhang 
393ac68637bSLei Zhang   auto it = symbolInfoMap.find(name);
394ac68637bSLei Zhang   if (it == symbolInfoMap.end()) {
395ac68637bSLei Zhang     auto error = formatv("referencing unbound symbol '{0}'", symbol);
396ac68637bSLei Zhang     PrintFatalError(loc, error);
397ac68637bSLei Zhang   }
398ac68637bSLei Zhang 
39931cfee60SLei Zhang   return it->getValue().getValueAndRangeUse(name, index, fmt, separator);
40031cfee60SLei Zhang }
40131cfee60SLei Zhang 
40231cfee60SLei Zhang std::string tblgen::SymbolInfoMap::getAllRangeUse(StringRef symbol,
40331cfee60SLei Zhang                                                   const char *fmt,
40431cfee60SLei Zhang                                                   const char *separator) const {
40531cfee60SLei Zhang   int index = -1;
40631cfee60SLei Zhang   StringRef name = getValuePackName(symbol, &index);
40731cfee60SLei Zhang 
40831cfee60SLei Zhang   auto it = symbolInfoMap.find(name);
40931cfee60SLei Zhang   if (it == symbolInfoMap.end()) {
41031cfee60SLei Zhang     auto error = formatv("referencing unbound symbol '{0}'", symbol);
41131cfee60SLei Zhang     PrintFatalError(loc, error);
41231cfee60SLei Zhang   }
41331cfee60SLei Zhang 
41431cfee60SLei Zhang   return it->getValue().getAllRangeUse(name, index, fmt, separator);
415ac68637bSLei Zhang }
416ac68637bSLei Zhang 
417ac68637bSLei Zhang //===----------------------------------------------------------------------===//
418ac68637bSLei Zhang // Pattern
419ac68637bSLei Zhang //==----------------------------------------------------------------------===//
420ac68637bSLei Zhang 
421ac68637bSLei Zhang tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
422ac68637bSLei Zhang     : def(*def), recordOpMap(mapper) {}
423eb753f4aSLei Zhang 
424eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getSourcePattern() const {
4258f5fa566SLei Zhang   return tblgen::DagNode(def.getValueAsDag("sourcePattern"));
426eb753f4aSLei Zhang }
427eb753f4aSLei Zhang 
428e032d0dcSLei Zhang int tblgen::Pattern::getNumResultPatterns() const {
4298f5fa566SLei Zhang   auto *results = def.getValueAsListInit("resultPatterns");
430eb753f4aSLei Zhang   return results->size();
431eb753f4aSLei Zhang }
432eb753f4aSLei Zhang 
433eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const {
4348f5fa566SLei Zhang   auto *results = def.getValueAsListInit("resultPatterns");
435eb753f4aSLei Zhang   return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index)));
436eb753f4aSLei Zhang }
437eb753f4aSLei Zhang 
438ac68637bSLei Zhang void tblgen::Pattern::collectSourcePatternBoundSymbols(
439ac68637bSLei Zhang     tblgen::SymbolInfoMap &infoMap) {
440*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "start collecting source pattern bound symbols\n");
441ac68637bSLei Zhang   collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true);
442*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "done collecting source pattern bound symbols\n");
443eb753f4aSLei Zhang }
444eb753f4aSLei Zhang 
445ac68637bSLei Zhang void tblgen::Pattern::collectResultPatternBoundSymbols(
446ac68637bSLei Zhang     tblgen::SymbolInfoMap &infoMap) {
447*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "start collecting result pattern bound symbols\n");
448ac68637bSLei Zhang   for (int i = 0, e = getNumResultPatterns(); i < e; ++i) {
449ac68637bSLei Zhang     auto pattern = getResultPattern(i);
450ac68637bSLei Zhang     collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false);
451eb753f4aSLei Zhang   }
452*1358df19SLei Zhang   LLVM_DEBUG(llvm::dbgs() << "done collecting result pattern bound symbols\n");
453388fb375SJacques Pienaar }
454388fb375SJacques Pienaar 
455eb753f4aSLei Zhang const tblgen::Operator &tblgen::Pattern::getSourceRootOp() {
456eb753f4aSLei Zhang   return getSourcePattern().getDialectOp(recordOpMap);
457eb753f4aSLei Zhang }
458eb753f4aSLei Zhang 
459eb753f4aSLei Zhang tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) {
460eb753f4aSLei Zhang   return node.getDialectOp(recordOpMap);
461eb753f4aSLei Zhang }
462388fb375SJacques Pienaar 
4638f5fa566SLei Zhang std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const {
464388fb375SJacques Pienaar   auto *listInit = def.getValueAsListInit("constraints");
4658f5fa566SLei Zhang   std::vector<tblgen::AppliedConstraint> ret;
466388fb375SJacques Pienaar   ret.reserve(listInit->size());
4678f5fa566SLei Zhang 
468388fb375SJacques Pienaar   for (auto it : *listInit) {
4698f5fa566SLei Zhang     auto *dagInit = dyn_cast<llvm::DagInit>(it);
4708f5fa566SLei Zhang     if (!dagInit)
4718f5fa566SLei Zhang       PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity "
4728f5fa566SLei Zhang                                     "constraints should be DAG nodes");
4738f5fa566SLei Zhang 
4748f5fa566SLei Zhang     std::vector<std::string> entities;
4758f5fa566SLei Zhang     entities.reserve(dagInit->arg_size());
4768f5fa566SLei Zhang     for (auto *argName : dagInit->getArgNames())
4778f5fa566SLei Zhang       entities.push_back(argName->getValue());
4788f5fa566SLei Zhang 
4798f5fa566SLei Zhang     ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
480c72d849eSLei Zhang                      dagInit->getNameStr(), std::move(entities));
481388fb375SJacques Pienaar   }
482388fb375SJacques Pienaar   return ret;
483388fb375SJacques Pienaar }
48453035874SFeng Liu 
48553035874SFeng Liu int tblgen::Pattern::getBenefit() const {
486a0606ca7SFeng Liu   // The initial benefit value is a heuristic with number of ops in the source
48753035874SFeng Liu   // pattern.
488a0606ca7SFeng Liu   int initBenefit = getSourcePattern().getNumOps();
48953035874SFeng Liu   llvm::DagInit *delta = def.getValueAsDag("benefitDelta");
490a0606ca7SFeng Liu   if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) {
491a0606ca7SFeng Liu     PrintFatalError(def.getLoc(),
492a0606ca7SFeng Liu                     "The 'addBenefit' takes and only takes one integer value");
493a0606ca7SFeng Liu   }
494a0606ca7SFeng Liu   return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue();
49553035874SFeng Liu }
49604b6d2f3SLei Zhang 
4974165885aSJacques Pienaar std::vector<tblgen::Pattern::IdentifierLine>
4984165885aSJacques Pienaar tblgen::Pattern::getLocation() const {
4994165885aSJacques Pienaar   std::vector<std::pair<StringRef, unsigned>> result;
5004165885aSJacques Pienaar   result.reserve(def.getLoc().size());
5014165885aSJacques Pienaar   for (auto loc : def.getLoc()) {
5024165885aSJacques Pienaar     unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc);
5034165885aSJacques Pienaar     assert(buf && "invalid source location");
5044165885aSJacques Pienaar     result.emplace_back(
5054165885aSJacques Pienaar         llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(),
5064165885aSJacques Pienaar         llvm::SrcMgr.getLineAndColumn(loc, buf).first);
5074165885aSJacques Pienaar   }
5084165885aSJacques Pienaar   return result;
5094165885aSJacques Pienaar }
5104165885aSJacques Pienaar 
511ac68637bSLei Zhang void tblgen::Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap,
512e032d0dcSLei Zhang                                           bool isSrcPattern) {
513e032d0dcSLei Zhang   auto treeName = tree.getSymbol();
514e032d0dcSLei Zhang   if (!tree.isOperation()) {
515e032d0dcSLei Zhang     if (!treeName.empty()) {
516e032d0dcSLei Zhang       PrintFatalError(
517e032d0dcSLei Zhang           def.getLoc(),
518e032d0dcSLei Zhang           formatv("binding symbol '{0}' to non-operation unsupported right now",
519e032d0dcSLei Zhang                   treeName));
520e032d0dcSLei Zhang     }
521e032d0dcSLei Zhang     return;
522e032d0dcSLei Zhang   }
523e032d0dcSLei Zhang 
52404b6d2f3SLei Zhang   auto &op = getDialectOp(tree);
52504b6d2f3SLei Zhang   auto numOpArgs = op.getNumArgs();
52604b6d2f3SLei Zhang   auto numTreeArgs = tree.getNumArgs();
52704b6d2f3SLei Zhang 
52804b6d2f3SLei Zhang   if (numOpArgs != numTreeArgs) {
529ac68637bSLei Zhang     auto err = formatv("op '{0}' argument number mismatch: "
53004b6d2f3SLei Zhang                        "{1} in pattern vs. {2} in definition",
531ac68637bSLei Zhang                        op.getOperationName(), numTreeArgs, numOpArgs);
532ac68637bSLei Zhang     PrintFatalError(def.getLoc(), err);
53304b6d2f3SLei Zhang   }
53404b6d2f3SLei Zhang 
53504b6d2f3SLei Zhang   // The name attached to the DAG node's operator is for representing the
53604b6d2f3SLei Zhang   // results generated from this op. It should be remembered as bound results.
537ac68637bSLei Zhang   if (!treeName.empty()) {
538*1358df19SLei Zhang     LLVM_DEBUG(llvm::dbgs()
539*1358df19SLei Zhang                << "found symbol bound to op result: " << treeName << '\n');
540ac68637bSLei Zhang     if (!infoMap.bindOpResult(treeName, op))
541ac68637bSLei Zhang       PrintFatalError(def.getLoc(),
542ac68637bSLei Zhang                       formatv("symbol '{0}' bound more than once", treeName));
543ac68637bSLei Zhang   }
54404b6d2f3SLei Zhang 
5452fe8ae4fSJacques Pienaar   for (int i = 0; i != numTreeArgs; ++i) {
54604b6d2f3SLei Zhang     if (auto treeArg = tree.getArgAsNestedDag(i)) {
54704b6d2f3SLei Zhang       // This DAG node argument is a DAG node itself. Go inside recursively.
548ac68637bSLei Zhang       collectBoundSymbols(treeArg, infoMap, isSrcPattern);
549e032d0dcSLei Zhang     } else if (isSrcPattern) {
550e032d0dcSLei Zhang       // We can only bind symbols to op arguments in source pattern. Those
551e032d0dcSLei Zhang       // symbols are referenced in result patterns.
55204b6d2f3SLei Zhang       auto treeArgName = tree.getArgName(i);
553ac68637bSLei Zhang       if (!treeArgName.empty()) {
554*1358df19SLei Zhang         LLVM_DEBUG(llvm::dbgs() << "found symbol bound to op argument: "
555*1358df19SLei Zhang                                 << treeArgName << '\n');
556ac68637bSLei Zhang         if (!infoMap.bindOpArgument(treeArgName, op, i)) {
557ac68637bSLei Zhang           auto err = formatv("symbol '{0}' bound more than once", treeArgName);
558ac68637bSLei Zhang           PrintFatalError(def.getLoc(), err);
559ac68637bSLei Zhang         }
560ac68637bSLei Zhang       }
56104b6d2f3SLei Zhang     }
56204b6d2f3SLei Zhang   }
56304b6d2f3SLei Zhang }
564