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"
2504b6d2f3SLei Zhang #include "llvm/Support/FormatVariadic.h"
268f5fa566SLei Zhang #include "llvm/TableGen/Error.h"
27eb753f4aSLei Zhang #include "llvm/TableGen/Record.h"
28eb753f4aSLei Zhang 
29eb753f4aSLei Zhang using namespace mlir;
30eb753f4aSLei Zhang 
310ea6154bSJacques Pienaar using llvm::formatv;
32eb753f4aSLei Zhang using mlir::tblgen::Operator;
33eb753f4aSLei Zhang 
34ac68637bSLei Zhang //===----------------------------------------------------------------------===//
35ac68637bSLei Zhang // DagLeaf
36ac68637bSLei Zhang //===----------------------------------------------------------------------===//
37ac68637bSLei Zhang 
38e0774c00SLei Zhang bool tblgen::DagLeaf::isUnspecified() const {
39b9e38a79SLei Zhang   return dyn_cast_or_null<llvm::UnsetInit>(def);
40e0774c00SLei Zhang }
41e0774c00SLei Zhang 
42e0774c00SLei Zhang bool tblgen::DagLeaf::isOperandMatcher() const {
43e0774c00SLei Zhang   // Operand matchers specify a type constraint.
44b9e38a79SLei Zhang   return isSubClassOf("TypeConstraint");
45e0774c00SLei Zhang }
46e0774c00SLei Zhang 
47e0774c00SLei Zhang bool tblgen::DagLeaf::isAttrMatcher() const {
48c52a8127SFeng Liu   // Attribute matchers specify an attribute constraint.
49b9e38a79SLei Zhang   return isSubClassOf("AttrConstraint");
50e0774c00SLei Zhang }
51e0774c00SLei Zhang 
52d0e2019dSLei Zhang bool tblgen::DagLeaf::isNativeCodeCall() const {
53d0e2019dSLei Zhang   return isSubClassOf("NativeCodeCall");
54e0774c00SLei Zhang }
55e0774c00SLei Zhang 
56e0774c00SLei Zhang bool tblgen::DagLeaf::isConstantAttr() const {
57b9e38a79SLei Zhang   return isSubClassOf("ConstantAttr");
58b9e38a79SLei Zhang }
59b9e38a79SLei Zhang 
60b9e38a79SLei Zhang bool tblgen::DagLeaf::isEnumAttrCase() const {
619dd182e0SLei Zhang   return isSubClassOf("EnumAttrCaseInfo");
62e0774c00SLei Zhang }
63e0774c00SLei Zhang 
648f5fa566SLei Zhang tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const {
658f5fa566SLei Zhang   assert((isOperandMatcher() || isAttrMatcher()) &&
668f5fa566SLei Zhang          "the DAG leaf must be operand or attribute");
678f5fa566SLei Zhang   return Constraint(cast<llvm::DefInit>(def)->getDef());
68e0774c00SLei Zhang }
69e0774c00SLei Zhang 
70e0774c00SLei Zhang tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const {
71e0774c00SLei Zhang   assert(isConstantAttr() && "the DAG leaf must be constant attribute");
72e0774c00SLei Zhang   return ConstantAttr(cast<llvm::DefInit>(def));
73e0774c00SLei Zhang }
74e0774c00SLei Zhang 
75b9e38a79SLei Zhang tblgen::EnumAttrCase tblgen::DagLeaf::getAsEnumAttrCase() const {
76b9e38a79SLei Zhang   assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case");
77b9e38a79SLei Zhang   return EnumAttrCase(cast<llvm::DefInit>(def));
78b9e38a79SLei Zhang }
79b9e38a79SLei Zhang 
80e0774c00SLei Zhang std::string tblgen::DagLeaf::getConditionTemplate() const {
818f5fa566SLei Zhang   return getAsConstraint().getConditionTemplate();
82e0774c00SLei Zhang }
83e0774c00SLei Zhang 
84d0e2019dSLei Zhang llvm::StringRef tblgen::DagLeaf::getNativeCodeTemplate() const {
85d0e2019dSLei Zhang   assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
86d0e2019dSLei Zhang   return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression");
87eb753f4aSLei Zhang }
88eb753f4aSLei Zhang 
89b9e38a79SLei Zhang bool tblgen::DagLeaf::isSubClassOf(StringRef superclass) const {
90b9e38a79SLei Zhang   if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def))
91b9e38a79SLei Zhang     return defInit->getDef()->isSubClassOf(superclass);
92b9e38a79SLei Zhang   return false;
93b9e38a79SLei Zhang }
94b9e38a79SLei Zhang 
95ac68637bSLei Zhang //===----------------------------------------------------------------------===//
96ac68637bSLei Zhang // DagNode
97ac68637bSLei Zhang //===----------------------------------------------------------------------===//
98ac68637bSLei Zhang 
99d0e2019dSLei Zhang bool tblgen::DagNode::isNativeCodeCall() const {
100d0e2019dSLei Zhang   if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator()))
101d0e2019dSLei Zhang     return defInit->getDef()->isSubClassOf("NativeCodeCall");
102c52a8127SFeng Liu   return false;
103c52a8127SFeng Liu }
104c52a8127SFeng Liu 
105647f8cabSRiver Riddle bool tblgen::DagNode::isOperation() const {
106c72d849eSLei Zhang   return !(isNativeCodeCall() || isReplaceWithValue());
107647f8cabSRiver Riddle }
108647f8cabSRiver Riddle 
109d0e2019dSLei Zhang llvm::StringRef tblgen::DagNode::getNativeCodeTemplate() const {
110d0e2019dSLei Zhang   assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
111c52a8127SFeng Liu   return cast<llvm::DefInit>(node->getOperator())
112c52a8127SFeng Liu       ->getDef()
113d0e2019dSLei Zhang       ->getValueAsString("expression");
114c52a8127SFeng Liu }
115c52a8127SFeng Liu 
116e032d0dcSLei Zhang llvm::StringRef tblgen::DagNode::getSymbol() const {
117388fb375SJacques Pienaar   return node->getNameStr();
118388fb375SJacques Pienaar }
119388fb375SJacques Pienaar 
120eb753f4aSLei Zhang Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
121eb753f4aSLei Zhang   llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
1222dc6d205SLei Zhang   auto it = mapper->find(opDef);
1232dc6d205SLei Zhang   if (it != mapper->end())
1242dc6d205SLei Zhang     return *it->second;
1252dc6d205SLei Zhang   return *mapper->try_emplace(opDef, llvm::make_unique<Operator>(opDef))
1262dc6d205SLei Zhang               .first->second;
127eb753f4aSLei Zhang }
128eb753f4aSLei Zhang 
1292fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumOps() const {
1302fe8ae4fSJacques Pienaar   int count = isReplaceWithValue() ? 0 : 1;
1312fe8ae4fSJacques Pienaar   for (int i = 0, e = getNumArgs(); i != e; ++i) {
132eb753f4aSLei Zhang     if (auto child = getArgAsNestedDag(i))
133eb753f4aSLei Zhang       count += child.getNumOps();
134eb753f4aSLei Zhang   }
135eb753f4aSLei Zhang   return count;
136eb753f4aSLei Zhang }
137eb753f4aSLei Zhang 
1382fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); }
139eb753f4aSLei Zhang 
140eb753f4aSLei Zhang bool tblgen::DagNode::isNestedDagArg(unsigned index) const {
141eb753f4aSLei Zhang   return isa<llvm::DagInit>(node->getArg(index));
142eb753f4aSLei Zhang }
143eb753f4aSLei Zhang 
144eb753f4aSLei Zhang tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const {
145eb753f4aSLei Zhang   return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
146eb753f4aSLei Zhang }
147eb753f4aSLei Zhang 
148e0774c00SLei Zhang tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const {
149e0774c00SLei Zhang   assert(!isNestedDagArg(index));
150e0774c00SLei Zhang   return DagLeaf(node->getArg(index));
151eb753f4aSLei Zhang }
152eb753f4aSLei Zhang 
153eb753f4aSLei Zhang StringRef tblgen::DagNode::getArgName(unsigned index) const {
154eb753f4aSLei Zhang   return node->getArgNameStr(index);
155eb753f4aSLei Zhang }
156eb753f4aSLei Zhang 
157eb753f4aSLei Zhang bool tblgen::DagNode::isReplaceWithValue() const {
158eb753f4aSLei Zhang   auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
159eb753f4aSLei Zhang   return dagOpDef->getName() == "replaceWithValue";
160eb753f4aSLei Zhang }
161eb753f4aSLei Zhang 
162ac68637bSLei Zhang //===----------------------------------------------------------------------===//
163ac68637bSLei Zhang // SymbolInfoMap
164ac68637bSLei Zhang //===----------------------------------------------------------------------===//
165ac68637bSLei Zhang 
166ac68637bSLei Zhang StringRef tblgen::SymbolInfoMap::getValuePackName(StringRef symbol,
167ac68637bSLei Zhang                                                   int *index) {
168ac68637bSLei Zhang   StringRef name, indexStr;
169ac68637bSLei Zhang   int idx = -1;
170ac68637bSLei Zhang   std::tie(name, indexStr) = symbol.rsplit("__");
171ac68637bSLei Zhang 
172ac68637bSLei Zhang   if (indexStr.consumeInteger(10, idx)) {
173ac68637bSLei Zhang     // The second part is not an index; we return the whole symbol as-is.
174ac68637bSLei Zhang     return symbol;
175eb753f4aSLei Zhang   }
176ac68637bSLei Zhang   if (index) {
177ac68637bSLei Zhang     *index = idx;
178ac68637bSLei Zhang   }
179ac68637bSLei Zhang   return name;
180ac68637bSLei Zhang }
181ac68637bSLei Zhang 
182ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op,
183ac68637bSLei Zhang                                               SymbolInfo::Kind kind,
184ac68637bSLei Zhang                                               Optional<int> index)
185ac68637bSLei Zhang     : op(op), kind(kind), argIndex(index) {}
186ac68637bSLei Zhang 
187ac68637bSLei Zhang int tblgen::SymbolInfoMap::SymbolInfo::getStaticValueCount() const {
188ac68637bSLei Zhang   switch (kind) {
189ac68637bSLei Zhang   case Kind::Attr:
190ac68637bSLei Zhang   case Kind::Operand:
191ac68637bSLei Zhang   case Kind::Value:
192ac68637bSLei Zhang     return 1;
193ac68637bSLei Zhang   case Kind::Result:
194ac68637bSLei Zhang     return op->getNumResults();
195ac68637bSLei Zhang   }
196*12ff145eSjpienaar   llvm_unreachable("unknown kind");
197ac68637bSLei Zhang }
198ac68637bSLei Zhang 
199ac68637bSLei Zhang std::string
200ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const {
201ac68637bSLei Zhang   switch (kind) {
202ac68637bSLei Zhang   case Kind::Attr: {
203ac68637bSLei Zhang     auto type =
204ac68637bSLei Zhang         op->getArg(*argIndex).get<NamedAttribute *>()->attr.getStorageType();
205ac68637bSLei Zhang     return formatv("{0} {1};\n", type, name);
206ac68637bSLei Zhang   }
207ac68637bSLei Zhang   case Kind::Operand:
208ac68637bSLei Zhang   case Kind::Value: {
209ac68637bSLei Zhang     return formatv("Value *{0};\n", name);
210ac68637bSLei Zhang   }
211ac68637bSLei Zhang   case Kind::Result: {
212ac68637bSLei Zhang     // Use the op itself for the results.
213ac68637bSLei Zhang     return formatv("{0} {1};\n", op->getQualCppClassName(), name);
214ac68637bSLei Zhang   }
215ac68637bSLei Zhang   }
216*12ff145eSjpienaar   llvm_unreachable("unknown kind");
217ac68637bSLei Zhang }
218ac68637bSLei Zhang 
219ac68637bSLei Zhang std::string
220ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::getValueAndRangeUse(StringRef name,
221ac68637bSLei Zhang                                                        int index) const {
222ac68637bSLei Zhang   switch (kind) {
223ac68637bSLei Zhang   case Kind::Attr:
224ac68637bSLei Zhang   case Kind::Operand: {
225ac68637bSLei Zhang     assert(index < 0 && "only allowed for symbol bound to result");
226ac68637bSLei Zhang     return name;
227ac68637bSLei Zhang   }
228ac68637bSLei Zhang   case Kind::Result: {
229ac68637bSLei Zhang     // TODO(b/133341698): The following is incorrect for variadic results. We
230ac68637bSLei Zhang     // should use getODSResults().
231ac68637bSLei Zhang     if (index >= 0) {
232ac68637bSLei Zhang       return formatv("{0}.getOperation()->getResult({1})", name, index);
233ac68637bSLei Zhang     }
234ac68637bSLei Zhang 
235ac68637bSLei Zhang     // If referencing multiple results, compose a comma-separated list.
236ac68637bSLei Zhang     SmallVector<std::string, 4> values;
237ac68637bSLei Zhang     for (int i = 0, e = op->getNumResults(); i < e; ++i) {
238ac68637bSLei Zhang       values.push_back(formatv("{0}.getOperation()->getResult({1})", name, i));
239ac68637bSLei Zhang     }
240ac68637bSLei Zhang     return llvm::join(values, ", ");
241ac68637bSLei Zhang   }
242ac68637bSLei Zhang   case Kind::Value: {
243ac68637bSLei Zhang     assert(index < 0 && "only allowed for symbol bound to result");
244ac68637bSLei Zhang     assert(op == nullptr);
245ac68637bSLei Zhang     return name;
246ac68637bSLei Zhang   }
247ac68637bSLei Zhang   }
248*12ff145eSjpienaar   llvm_unreachable("unknown kind");
249ac68637bSLei Zhang }
250ac68637bSLei Zhang 
251ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpArgument(StringRef symbol, const Operator &op,
252ac68637bSLei Zhang                                            int argIndex) {
253ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
254ac68637bSLei Zhang   if (name != symbol) {
255ac68637bSLei Zhang     auto error = formatv(
256ac68637bSLei Zhang         "symbol '{0}' with trailing index cannot bind to op argument", symbol);
257ac68637bSLei Zhang     PrintFatalError(loc, error);
258ac68637bSLei Zhang   }
259ac68637bSLei Zhang 
260ac68637bSLei Zhang   auto symInfo = op.getArg(argIndex).is<NamedAttribute *>()
261ac68637bSLei Zhang                      ? SymbolInfo::getAttr(&op, argIndex)
262ac68637bSLei Zhang                      : SymbolInfo::getOperand(&op, argIndex);
263ac68637bSLei Zhang 
264ac68637bSLei Zhang   return symbolInfoMap.insert({symbol, symInfo}).second;
265ac68637bSLei Zhang }
266ac68637bSLei Zhang 
267ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) {
268ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
269ac68637bSLei Zhang   return symbolInfoMap.insert({name, SymbolInfo::getResult(&op)}).second;
270ac68637bSLei Zhang }
271ac68637bSLei Zhang 
272ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindValue(StringRef symbol) {
273ac68637bSLei Zhang   return symbolInfoMap.insert({symbol, SymbolInfo::getValue()}).second;
274ac68637bSLei Zhang }
275ac68637bSLei Zhang 
276ac68637bSLei Zhang bool tblgen::SymbolInfoMap::contains(StringRef symbol) const {
277ac68637bSLei Zhang   return find(symbol) != symbolInfoMap.end();
278ac68637bSLei Zhang }
279ac68637bSLei Zhang 
280ac68637bSLei Zhang tblgen::SymbolInfoMap::const_iterator
281ac68637bSLei Zhang tblgen::SymbolInfoMap::find(StringRef key) const {
282ac68637bSLei Zhang   StringRef name = getValuePackName(key);
283ac68637bSLei Zhang   return symbolInfoMap.find(name);
284ac68637bSLei Zhang }
285ac68637bSLei Zhang 
286ac68637bSLei Zhang int tblgen::SymbolInfoMap::getStaticValueCount(StringRef symbol) const {
287ac68637bSLei Zhang   StringRef name = getValuePackName(symbol);
288ac68637bSLei Zhang   if (name != symbol) {
289ac68637bSLei Zhang     // If there is a trailing index inside symbol, it references just one
290ac68637bSLei Zhang     // static value.
291ac68637bSLei Zhang     return 1;
292ac68637bSLei Zhang   }
293ac68637bSLei Zhang   // Otherwise, find how many it represents by querying the symbol's info.
294ac68637bSLei Zhang   return find(name)->getValue().getStaticValueCount();
295ac68637bSLei Zhang }
296ac68637bSLei Zhang 
297ac68637bSLei Zhang std::string tblgen::SymbolInfoMap::getValueAndRangeUse(StringRef symbol) const {
298ac68637bSLei Zhang   int index = -1;
299ac68637bSLei Zhang   StringRef name = getValuePackName(symbol, &index);
300ac68637bSLei Zhang 
301ac68637bSLei Zhang   auto it = symbolInfoMap.find(name);
302ac68637bSLei Zhang   if (it == symbolInfoMap.end()) {
303ac68637bSLei Zhang     auto error = formatv("referencing unbound symbol '{0}'", symbol);
304ac68637bSLei Zhang     PrintFatalError(loc, error);
305ac68637bSLei Zhang   }
306ac68637bSLei Zhang 
307ac68637bSLei Zhang   return it->getValue().getValueAndRangeUse(name, index);
308ac68637bSLei Zhang }
309ac68637bSLei Zhang 
310ac68637bSLei Zhang //===----------------------------------------------------------------------===//
311ac68637bSLei Zhang // Pattern
312ac68637bSLei Zhang //==----------------------------------------------------------------------===//
313ac68637bSLei Zhang 
314ac68637bSLei Zhang tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
315ac68637bSLei Zhang     : def(*def), recordOpMap(mapper) {}
316eb753f4aSLei Zhang 
317eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getSourcePattern() const {
3188f5fa566SLei Zhang   return tblgen::DagNode(def.getValueAsDag("sourcePattern"));
319eb753f4aSLei Zhang }
320eb753f4aSLei Zhang 
321e032d0dcSLei Zhang int tblgen::Pattern::getNumResultPatterns() const {
3228f5fa566SLei Zhang   auto *results = def.getValueAsListInit("resultPatterns");
323eb753f4aSLei Zhang   return results->size();
324eb753f4aSLei Zhang }
325eb753f4aSLei Zhang 
326eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const {
3278f5fa566SLei Zhang   auto *results = def.getValueAsListInit("resultPatterns");
328eb753f4aSLei Zhang   return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index)));
329eb753f4aSLei Zhang }
330eb753f4aSLei Zhang 
331ac68637bSLei Zhang void tblgen::Pattern::collectSourcePatternBoundSymbols(
332ac68637bSLei Zhang     tblgen::SymbolInfoMap &infoMap) {
333ac68637bSLei Zhang   collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true);
334eb753f4aSLei Zhang }
335eb753f4aSLei Zhang 
336ac68637bSLei Zhang void tblgen::Pattern::collectResultPatternBoundSymbols(
337ac68637bSLei Zhang     tblgen::SymbolInfoMap &infoMap) {
338ac68637bSLei Zhang   for (int i = 0, e = getNumResultPatterns(); i < e; ++i) {
339ac68637bSLei Zhang     auto pattern = getResultPattern(i);
340ac68637bSLei Zhang     collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false);
341eb753f4aSLei Zhang   }
342388fb375SJacques Pienaar }
343388fb375SJacques Pienaar 
344eb753f4aSLei Zhang const tblgen::Operator &tblgen::Pattern::getSourceRootOp() {
345eb753f4aSLei Zhang   return getSourcePattern().getDialectOp(recordOpMap);
346eb753f4aSLei Zhang }
347eb753f4aSLei Zhang 
348eb753f4aSLei Zhang tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) {
349eb753f4aSLei Zhang   return node.getDialectOp(recordOpMap);
350eb753f4aSLei Zhang }
351388fb375SJacques Pienaar 
3528f5fa566SLei Zhang std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const {
353388fb375SJacques Pienaar   auto *listInit = def.getValueAsListInit("constraints");
3548f5fa566SLei Zhang   std::vector<tblgen::AppliedConstraint> ret;
355388fb375SJacques Pienaar   ret.reserve(listInit->size());
3568f5fa566SLei Zhang 
357388fb375SJacques Pienaar   for (auto it : *listInit) {
3588f5fa566SLei Zhang     auto *dagInit = dyn_cast<llvm::DagInit>(it);
3598f5fa566SLei Zhang     if (!dagInit)
3608f5fa566SLei Zhang       PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity "
3618f5fa566SLei Zhang                                     "constraints should be DAG nodes");
3628f5fa566SLei Zhang 
3638f5fa566SLei Zhang     std::vector<std::string> entities;
3648f5fa566SLei Zhang     entities.reserve(dagInit->arg_size());
3658f5fa566SLei Zhang     for (auto *argName : dagInit->getArgNames())
3668f5fa566SLei Zhang       entities.push_back(argName->getValue());
3678f5fa566SLei Zhang 
3688f5fa566SLei Zhang     ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
369c72d849eSLei Zhang                      dagInit->getNameStr(), std::move(entities));
370388fb375SJacques Pienaar   }
371388fb375SJacques Pienaar   return ret;
372388fb375SJacques Pienaar }
37353035874SFeng Liu 
37453035874SFeng Liu int tblgen::Pattern::getBenefit() const {
375a0606ca7SFeng Liu   // The initial benefit value is a heuristic with number of ops in the source
37653035874SFeng Liu   // pattern.
377a0606ca7SFeng Liu   int initBenefit = getSourcePattern().getNumOps();
37853035874SFeng Liu   llvm::DagInit *delta = def.getValueAsDag("benefitDelta");
379a0606ca7SFeng Liu   if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) {
380a0606ca7SFeng Liu     PrintFatalError(def.getLoc(),
381a0606ca7SFeng Liu                     "The 'addBenefit' takes and only takes one integer value");
382a0606ca7SFeng Liu   }
383a0606ca7SFeng Liu   return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue();
38453035874SFeng Liu }
38504b6d2f3SLei Zhang 
3864165885aSJacques Pienaar std::vector<tblgen::Pattern::IdentifierLine>
3874165885aSJacques Pienaar tblgen::Pattern::getLocation() const {
3884165885aSJacques Pienaar   std::vector<std::pair<StringRef, unsigned>> result;
3894165885aSJacques Pienaar   result.reserve(def.getLoc().size());
3904165885aSJacques Pienaar   for (auto loc : def.getLoc()) {
3914165885aSJacques Pienaar     unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc);
3924165885aSJacques Pienaar     assert(buf && "invalid source location");
3934165885aSJacques Pienaar     result.emplace_back(
3944165885aSJacques Pienaar         llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(),
3954165885aSJacques Pienaar         llvm::SrcMgr.getLineAndColumn(loc, buf).first);
3964165885aSJacques Pienaar   }
3974165885aSJacques Pienaar   return result;
3984165885aSJacques Pienaar }
3994165885aSJacques Pienaar 
400ac68637bSLei Zhang void tblgen::Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap,
401e032d0dcSLei Zhang                                           bool isSrcPattern) {
402e032d0dcSLei Zhang   auto treeName = tree.getSymbol();
403e032d0dcSLei Zhang   if (!tree.isOperation()) {
404e032d0dcSLei Zhang     if (!treeName.empty()) {
405e032d0dcSLei Zhang       PrintFatalError(
406e032d0dcSLei Zhang           def.getLoc(),
407e032d0dcSLei Zhang           formatv("binding symbol '{0}' to non-operation unsupported right now",
408e032d0dcSLei Zhang                   treeName));
409e032d0dcSLei Zhang     }
410e032d0dcSLei Zhang     return;
411e032d0dcSLei Zhang   }
412e032d0dcSLei Zhang 
41304b6d2f3SLei Zhang   auto &op = getDialectOp(tree);
41404b6d2f3SLei Zhang   auto numOpArgs = op.getNumArgs();
41504b6d2f3SLei Zhang   auto numTreeArgs = tree.getNumArgs();
41604b6d2f3SLei Zhang 
41704b6d2f3SLei Zhang   if (numOpArgs != numTreeArgs) {
418ac68637bSLei Zhang     auto err = formatv("op '{0}' argument number mismatch: "
41904b6d2f3SLei Zhang                        "{1} in pattern vs. {2} in definition",
420ac68637bSLei Zhang                        op.getOperationName(), numTreeArgs, numOpArgs);
421ac68637bSLei Zhang     PrintFatalError(def.getLoc(), err);
42204b6d2f3SLei Zhang   }
42304b6d2f3SLei Zhang 
42404b6d2f3SLei Zhang   // The name attached to the DAG node's operator is for representing the
42504b6d2f3SLei Zhang   // results generated from this op. It should be remembered as bound results.
426ac68637bSLei Zhang   if (!treeName.empty()) {
427ac68637bSLei Zhang     if (!infoMap.bindOpResult(treeName, op))
428ac68637bSLei Zhang       PrintFatalError(def.getLoc(),
429ac68637bSLei Zhang                       formatv("symbol '{0}' bound more than once", treeName));
430ac68637bSLei Zhang   }
43104b6d2f3SLei Zhang 
4322fe8ae4fSJacques Pienaar   for (int i = 0; i != numTreeArgs; ++i) {
43304b6d2f3SLei Zhang     if (auto treeArg = tree.getArgAsNestedDag(i)) {
43404b6d2f3SLei Zhang       // This DAG node argument is a DAG node itself. Go inside recursively.
435ac68637bSLei Zhang       collectBoundSymbols(treeArg, infoMap, isSrcPattern);
436e032d0dcSLei Zhang     } else if (isSrcPattern) {
437e032d0dcSLei Zhang       // We can only bind symbols to op arguments in source pattern. Those
438e032d0dcSLei Zhang       // symbols are referenced in result patterns.
43904b6d2f3SLei Zhang       auto treeArgName = tree.getArgName(i);
440ac68637bSLei Zhang       if (!treeArgName.empty()) {
441ac68637bSLei Zhang         if (!infoMap.bindOpArgument(treeArgName, op, i)) {
442ac68637bSLei Zhang           auto err = formatv("symbol '{0}' bound more than once", treeArgName);
443ac68637bSLei Zhang           PrintFatalError(def.getLoc(), err);
444ac68637bSLei Zhang         }
445ac68637bSLei Zhang       }
44604b6d2f3SLei Zhang     }
44704b6d2f3SLei Zhang   }
44804b6d2f3SLei Zhang }
449