1cde4d5a6SJacques Pienaar //===- Pattern.cpp - Pattern wrapper class --------------------------------===//
2eb753f4aSLei Zhang //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eb753f4aSLei Zhang //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
8eb753f4aSLei Zhang //
9eb753f4aSLei Zhang // Pattern wrapper class to simplify using TableGen Record defining a MLIR
10eb753f4aSLei Zhang // Pattern.
11eb753f4aSLei Zhang //
12eb753f4aSLei Zhang //===----------------------------------------------------------------------===//
13eb753f4aSLei Zhang
141fc096afSMehdi Amini #include <utility>
151fc096afSMehdi Amini
16eb753f4aSLei Zhang #include "mlir/TableGen/Pattern.h"
17b12a7c88SMehdi Amini #include "llvm/ADT/StringExtras.h"
18eb753f4aSLei Zhang #include "llvm/ADT/Twine.h"
191358df19SLei Zhang #include "llvm/Support/Debug.h"
2004b6d2f3SLei Zhang #include "llvm/Support/FormatVariadic.h"
218f5fa566SLei Zhang #include "llvm/TableGen/Error.h"
22eb753f4aSLei Zhang #include "llvm/TableGen/Record.h"
23eb753f4aSLei Zhang
241358df19SLei Zhang #define DEBUG_TYPE "mlir-tblgen-pattern"
251358df19SLei Zhang
26eb753f4aSLei Zhang using namespace mlir;
2712d16de5SRahul Joshi using namespace tblgen;
28eb753f4aSLei Zhang
290ea6154bSJacques Pienaar using llvm::formatv;
30eb753f4aSLei Zhang
31ac68637bSLei Zhang //===----------------------------------------------------------------------===//
32ac68637bSLei Zhang // DagLeaf
33ac68637bSLei Zhang //===----------------------------------------------------------------------===//
34ac68637bSLei Zhang
isUnspecified() const3512d16de5SRahul Joshi bool DagLeaf::isUnspecified() const {
36*ae002f8bSKazu Hirata return isa_and_nonnull<llvm::UnsetInit>(def);
37e0774c00SLei Zhang }
38e0774c00SLei Zhang
isOperandMatcher() const3912d16de5SRahul Joshi bool DagLeaf::isOperandMatcher() const {
40e0774c00SLei Zhang // Operand matchers specify a type constraint.
41b9e38a79SLei Zhang return isSubClassOf("TypeConstraint");
42e0774c00SLei Zhang }
43e0774c00SLei Zhang
isAttrMatcher() const4412d16de5SRahul Joshi bool DagLeaf::isAttrMatcher() const {
45c52a8127SFeng Liu // Attribute matchers specify an attribute constraint.
46b9e38a79SLei Zhang return isSubClassOf("AttrConstraint");
47e0774c00SLei Zhang }
48e0774c00SLei Zhang
isNativeCodeCall() const4912d16de5SRahul Joshi bool DagLeaf::isNativeCodeCall() const {
50d0e2019dSLei Zhang return isSubClassOf("NativeCodeCall");
51e0774c00SLei Zhang }
52e0774c00SLei Zhang
isConstantAttr() const5312d16de5SRahul Joshi bool DagLeaf::isConstantAttr() const { return isSubClassOf("ConstantAttr"); }
54b9e38a79SLei Zhang
isEnumAttrCase() const5512d16de5SRahul Joshi bool DagLeaf::isEnumAttrCase() const {
569dd182e0SLei Zhang return isSubClassOf("EnumAttrCaseInfo");
57e0774c00SLei Zhang }
58e0774c00SLei Zhang
isStringAttr() const59cb8c30d3SMogball bool DagLeaf::isStringAttr() const { return isa<llvm::StringInit>(def); }
60d6b32e39SJacques Pienaar
getAsConstraint() const6112d16de5SRahul Joshi Constraint DagLeaf::getAsConstraint() const {
628f5fa566SLei Zhang assert((isOperandMatcher() || isAttrMatcher()) &&
638f5fa566SLei Zhang "the DAG leaf must be operand or attribute");
648f5fa566SLei Zhang return Constraint(cast<llvm::DefInit>(def)->getDef());
65e0774c00SLei Zhang }
66e0774c00SLei Zhang
getAsConstantAttr() const6712d16de5SRahul Joshi ConstantAttr DagLeaf::getAsConstantAttr() const {
68e0774c00SLei Zhang assert(isConstantAttr() && "the DAG leaf must be constant attribute");
69e0774c00SLei Zhang return ConstantAttr(cast<llvm::DefInit>(def));
70e0774c00SLei Zhang }
71e0774c00SLei Zhang
getAsEnumAttrCase() const7212d16de5SRahul Joshi EnumAttrCase DagLeaf::getAsEnumAttrCase() const {
73b9e38a79SLei Zhang assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case");
74b9e38a79SLei Zhang return EnumAttrCase(cast<llvm::DefInit>(def));
75b9e38a79SLei Zhang }
76b9e38a79SLei Zhang
getConditionTemplate() const7712d16de5SRahul Joshi std::string DagLeaf::getConditionTemplate() const {
788f5fa566SLei Zhang return getAsConstraint().getConditionTemplate();
79e0774c00SLei Zhang }
80e0774c00SLei Zhang
getNativeCodeTemplate() const8112d16de5SRahul Joshi llvm::StringRef DagLeaf::getNativeCodeTemplate() const {
82d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
83d0e2019dSLei Zhang return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression");
84eb753f4aSLei Zhang }
85eb753f4aSLei Zhang
getNumReturnsOfNativeCode() const86d7314b3cSChia-hung Duan int DagLeaf::getNumReturnsOfNativeCode() const {
87d7314b3cSChia-hung Duan assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
88d7314b3cSChia-hung Duan return cast<llvm::DefInit>(def)->getDef()->getValueAsInt("numReturns");
89d7314b3cSChia-hung Duan }
90d7314b3cSChia-hung Duan
getStringAttr() const9112d16de5SRahul Joshi std::string DagLeaf::getStringAttr() const {
92d6b32e39SJacques Pienaar assert(isStringAttr() && "the DAG leaf must be string attribute");
93d6b32e39SJacques Pienaar return def->getAsUnquotedString();
94d6b32e39SJacques Pienaar }
isSubClassOf(StringRef superclass) const9512d16de5SRahul Joshi bool DagLeaf::isSubClassOf(StringRef superclass) const {
96b9e38a79SLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def))
97b9e38a79SLei Zhang return defInit->getDef()->isSubClassOf(superclass);
98b9e38a79SLei Zhang return false;
99b9e38a79SLei Zhang }
100b9e38a79SLei Zhang
print(raw_ostream & os) const10112d16de5SRahul Joshi void DagLeaf::print(raw_ostream &os) const {
1021358df19SLei Zhang if (def)
1031358df19SLei Zhang def->print(os);
1041358df19SLei Zhang }
1051358df19SLei Zhang
106ac68637bSLei Zhang //===----------------------------------------------------------------------===//
107ac68637bSLei Zhang // DagNode
108ac68637bSLei Zhang //===----------------------------------------------------------------------===//
109ac68637bSLei Zhang
isNativeCodeCall() const11012d16de5SRahul Joshi bool DagNode::isNativeCodeCall() const {
111d0e2019dSLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator()))
112d0e2019dSLei Zhang return defInit->getDef()->isSubClassOf("NativeCodeCall");
113c52a8127SFeng Liu return false;
114c52a8127SFeng Liu }
115c52a8127SFeng Liu
isOperation() const11612d16de5SRahul Joshi bool DagNode::isOperation() const {
117cb8c30d3SMogball return !isNativeCodeCall() && !isReplaceWithValue() &&
1182d99c815SChia-hung Duan !isLocationDirective() && !isReturnTypeDirective() && !isEither();
119647f8cabSRiver Riddle }
120647f8cabSRiver Riddle
getNativeCodeTemplate() const12112d16de5SRahul Joshi llvm::StringRef DagNode::getNativeCodeTemplate() const {
122d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
123c52a8127SFeng Liu return cast<llvm::DefInit>(node->getOperator())
124c52a8127SFeng Liu ->getDef()
125d0e2019dSLei Zhang ->getValueAsString("expression");
126c52a8127SFeng Liu }
127c52a8127SFeng Liu
getNumReturnsOfNativeCode() const128d7314b3cSChia-hung Duan int DagNode::getNumReturnsOfNativeCode() const {
129d7314b3cSChia-hung Duan assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall");
130d7314b3cSChia-hung Duan return cast<llvm::DefInit>(node->getOperator())
131d7314b3cSChia-hung Duan ->getDef()
132d7314b3cSChia-hung Duan ->getValueAsInt("numReturns");
133d7314b3cSChia-hung Duan }
134d7314b3cSChia-hung Duan
getSymbol() const13512d16de5SRahul Joshi llvm::StringRef DagNode::getSymbol() const { return node->getNameStr(); }
136388fb375SJacques Pienaar
getDialectOp(RecordOperatorMap * mapper) const13712d16de5SRahul Joshi Operator &DagNode::getDialectOp(RecordOperatorMap *mapper) const {
138eb753f4aSLei Zhang llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
1392dc6d205SLei Zhang auto it = mapper->find(opDef);
1402dc6d205SLei Zhang if (it != mapper->end())
1412dc6d205SLei Zhang return *it->second;
14279f53b0cSJacques Pienaar return *mapper->try_emplace(opDef, std::make_unique<Operator>(opDef))
1432dc6d205SLei Zhang .first->second;
144eb753f4aSLei Zhang }
145eb753f4aSLei Zhang
getNumOps() const14612d16de5SRahul Joshi int DagNode::getNumOps() const {
1472d99c815SChia-hung Duan // We want to get number of operations recursively involved in the DAG tree.
1482d99c815SChia-hung Duan // All other directives should be excluded.
1492d99c815SChia-hung Duan int count = isOperation() ? 1 : 0;
1502fe8ae4fSJacques Pienaar for (int i = 0, e = getNumArgs(); i != e; ++i) {
151eb753f4aSLei Zhang if (auto child = getArgAsNestedDag(i))
152eb753f4aSLei Zhang count += child.getNumOps();
153eb753f4aSLei Zhang }
154eb753f4aSLei Zhang return count;
155eb753f4aSLei Zhang }
156eb753f4aSLei Zhang
getNumArgs() const15712d16de5SRahul Joshi int DagNode::getNumArgs() const { return node->getNumArgs(); }
158eb753f4aSLei Zhang
isNestedDagArg(unsigned index) const15912d16de5SRahul Joshi bool DagNode::isNestedDagArg(unsigned index) const {
160eb753f4aSLei Zhang return isa<llvm::DagInit>(node->getArg(index));
161eb753f4aSLei Zhang }
162eb753f4aSLei Zhang
getArgAsNestedDag(unsigned index) const16312d16de5SRahul Joshi DagNode DagNode::getArgAsNestedDag(unsigned index) const {
164eb753f4aSLei Zhang return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
165eb753f4aSLei Zhang }
166eb753f4aSLei Zhang
getArgAsLeaf(unsigned index) const16712d16de5SRahul Joshi DagLeaf DagNode::getArgAsLeaf(unsigned index) const {
168e0774c00SLei Zhang assert(!isNestedDagArg(index));
169e0774c00SLei Zhang return DagLeaf(node->getArg(index));
170eb753f4aSLei Zhang }
171eb753f4aSLei Zhang
getArgName(unsigned index) const17212d16de5SRahul Joshi StringRef DagNode::getArgName(unsigned index) const {
173eb753f4aSLei Zhang return node->getArgNameStr(index);
174eb753f4aSLei Zhang }
175eb753f4aSLei Zhang
isReplaceWithValue() const17612d16de5SRahul Joshi bool DagNode::isReplaceWithValue() const {
177eb753f4aSLei Zhang auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
178eb753f4aSLei Zhang return dagOpDef->getName() == "replaceWithValue";
179eb753f4aSLei Zhang }
180eb753f4aSLei Zhang
isLocationDirective() const18112d16de5SRahul Joshi bool DagNode::isLocationDirective() const {
1823f7439b2SJacques Pienaar auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
1833f7439b2SJacques Pienaar return dagOpDef->getName() == "location";
1843f7439b2SJacques Pienaar }
1853f7439b2SJacques Pienaar
isReturnTypeDirective() const186cb8c30d3SMogball bool DagNode::isReturnTypeDirective() const {
187cb8c30d3SMogball auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
188cb8c30d3SMogball return dagOpDef->getName() == "returnType";
189cb8c30d3SMogball }
190cb8c30d3SMogball
isEither() const1912d99c815SChia-hung Duan bool DagNode::isEither() const {
1922d99c815SChia-hung Duan auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
1932d99c815SChia-hung Duan return dagOpDef->getName() == "either";
1942d99c815SChia-hung Duan }
1952d99c815SChia-hung Duan
print(raw_ostream & os) const19612d16de5SRahul Joshi void DagNode::print(raw_ostream &os) const {
1971358df19SLei Zhang if (node)
1981358df19SLei Zhang node->print(os);
1991358df19SLei Zhang }
2001358df19SLei Zhang
201ac68637bSLei Zhang //===----------------------------------------------------------------------===//
202ac68637bSLei Zhang // SymbolInfoMap
203ac68637bSLei Zhang //===----------------------------------------------------------------------===//
204ac68637bSLei Zhang
getValuePackName(StringRef symbol,int * index)20512d16de5SRahul Joshi StringRef SymbolInfoMap::getValuePackName(StringRef symbol, int *index) {
206ac68637bSLei Zhang StringRef name, indexStr;
207ac68637bSLei Zhang int idx = -1;
208ac68637bSLei Zhang std::tie(name, indexStr) = symbol.rsplit("__");
209ac68637bSLei Zhang
210ac68637bSLei Zhang if (indexStr.consumeInteger(10, idx)) {
211ac68637bSLei Zhang // The second part is not an index; we return the whole symbol as-is.
212ac68637bSLei Zhang return symbol;
213eb753f4aSLei Zhang }
214ac68637bSLei Zhang if (index) {
215ac68637bSLei Zhang *index = idx;
216ac68637bSLei Zhang }
217ac68637bSLei Zhang return name;
218ac68637bSLei Zhang }
219ac68637bSLei Zhang
SymbolInfo(const Operator * op,SymbolInfo::Kind kind,Optional<DagAndConstant> dagAndConstant)22012d16de5SRahul Joshi SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op, SymbolInfo::Kind kind,
221d7314b3cSChia-hung Duan Optional<DagAndConstant> dagAndConstant)
2221fc096afSMehdi Amini : op(op), kind(kind), dagAndConstant(std::move(dagAndConstant)) {}
223ac68637bSLei Zhang
getStaticValueCount() const22412d16de5SRahul Joshi int SymbolInfoMap::SymbolInfo::getStaticValueCount() const {
225ac68637bSLei Zhang switch (kind) {
226ac68637bSLei Zhang case Kind::Attr:
227ac68637bSLei Zhang case Kind::Operand:
228ac68637bSLei Zhang case Kind::Value:
229ac68637bSLei Zhang return 1;
230ac68637bSLei Zhang case Kind::Result:
231ac68637bSLei Zhang return op->getNumResults();
232d7314b3cSChia-hung Duan case Kind::MultipleValues:
233d7314b3cSChia-hung Duan return getSize();
234ac68637bSLei Zhang }
23512ff145eSjpienaar llvm_unreachable("unknown kind");
236ac68637bSLei Zhang }
237ac68637bSLei Zhang
getVarName(StringRef name) const238008c0ea6Srdzhabarov std::string SymbolInfoMap::SymbolInfo::getVarName(StringRef name) const {
239064a08cdSKazu Hirata return alternativeName ? *alternativeName : name.str();
240008c0ea6Srdzhabarov }
241008c0ea6Srdzhabarov
getVarTypeStr(StringRef name) const242bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getVarTypeStr(StringRef name) const {
243bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getVarTypeStr for '" << name << "': ");
244ac68637bSLei Zhang switch (kind) {
245ac68637bSLei Zhang case Kind::Attr: {
246bb250606SChia-hung Duan if (op)
247bb250606SChia-hung Duan return op->getArg(getArgIndex())
248b4001ae8SChia-hung Duan .get<NamedAttribute *>()
249bb250606SChia-hung Duan ->attr.getStorageType()
250bb250606SChia-hung Duan .str();
2512bf423b0SRob Suderman // TODO(suderman): Use a more exact type when available.
2528652fc84SMarkus Böck return "::mlir::Attribute";
2532bf423b0SRob Suderman }
25431cfee60SLei Zhang case Kind::Operand: {
25531cfee60SLei Zhang // Use operand range for captured operands (to support potential variadic
25631cfee60SLei Zhang // operands).
257bb250606SChia-hung Duan return "::mlir::Operation::operand_range";
25831cfee60SLei Zhang }
259ac68637bSLei Zhang case Kind::Value: {
260bb250606SChia-hung Duan return "::mlir::Value";
261ac68637bSLei Zhang }
262d7314b3cSChia-hung Duan case Kind::MultipleValues: {
263bb250606SChia-hung Duan return "::mlir::ValueRange";
264d7314b3cSChia-hung Duan }
265ac68637bSLei Zhang case Kind::Result: {
26631cfee60SLei Zhang // Use the op itself for captured results.
267bb250606SChia-hung Duan return op->getQualCppClassName();
268ac68637bSLei Zhang }
269ac68637bSLei Zhang }
27012ff145eSjpienaar llvm_unreachable("unknown kind");
271ac68637bSLei Zhang }
272ac68637bSLei Zhang
getVarDecl(StringRef name) const273bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const {
274bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getVarDecl for '" << name << "': ");
275bb250606SChia-hung Duan std::string varInit = kind == Kind::Operand ? "(op0->getOperands())" : "";
276bb250606SChia-hung Duan return std::string(
277bb250606SChia-hung Duan formatv("{0} {1}{2};\n", getVarTypeStr(name), getVarName(name), varInit));
278bb250606SChia-hung Duan }
279bb250606SChia-hung Duan
getArgDecl(StringRef name) const280bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getArgDecl(StringRef name) const {
281bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getArgDecl for '" << name << "': ");
282bb250606SChia-hung Duan return std::string(
283bb250606SChia-hung Duan formatv("{0} &{1}", getVarTypeStr(name), getVarName(name)));
284bb250606SChia-hung Duan }
285bb250606SChia-hung Duan
getValueAndRangeUse(StringRef name,int index,const char * fmt,const char * separator) const28612d16de5SRahul Joshi std::string SymbolInfoMap::SymbolInfo::getValueAndRangeUse(
28731cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const {
2881358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getValueAndRangeUse for '" << name << "': ");
28931cfee60SLei Zhang switch (kind) {
29031cfee60SLei Zhang case Kind::Attr: {
29131cfee60SLei Zhang assert(index < 0);
2921358df19SLei Zhang auto repl = formatv(fmt, name);
2931358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Attr)\n");
294adcd0268SBenjamin Kramer return std::string(repl);
29531cfee60SLei Zhang }
29631cfee60SLei Zhang case Kind::Operand: {
29731cfee60SLei Zhang assert(index < 0);
298d7314b3cSChia-hung Duan auto *operand = op->getArg(getArgIndex()).get<NamedTypeConstraint *>();
29931cfee60SLei Zhang // If this operand is variadic, then return a range. Otherwise, return the
30031cfee60SLei Zhang // value itself.
301aba1acc8SRiver Riddle if (operand->isVariableLength()) {
3021358df19SLei Zhang auto repl = formatv(fmt, name);
3031358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicOperand)\n");
304adcd0268SBenjamin Kramer return std::string(repl);
30531cfee60SLei Zhang }
3061358df19SLei Zhang auto repl = formatv(fmt, formatv("(*{0}.begin())", name));
3071358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleOperand)\n");
308adcd0268SBenjamin Kramer return std::string(repl);
30931cfee60SLei Zhang }
31031cfee60SLei Zhang case Kind::Result: {
31131cfee60SLei Zhang // If `index` is greater than zero, then we are referencing a specific
31231cfee60SLei Zhang // result of a multi-result op. The result can still be variadic.
31331cfee60SLei Zhang if (index >= 0) {
314adcd0268SBenjamin Kramer std::string v =
315adcd0268SBenjamin Kramer std::string(formatv("{0}.getODSResults({1})", name, index));
31631cfee60SLei Zhang if (!op->getResult(index).isVariadic())
317adcd0268SBenjamin Kramer v = std::string(formatv("(*{0}.begin())", v));
3181358df19SLei Zhang auto repl = formatv(fmt, v);
3191358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n");
320adcd0268SBenjamin Kramer return std::string(repl);
32131cfee60SLei Zhang }
32231cfee60SLei Zhang
32323d21af6SLei Zhang // If this op has no result at all but still we bind a symbol to it, it
32423d21af6SLei Zhang // means we want to capture the op itself.
32523d21af6SLei Zhang if (op->getNumResults() == 0) {
32623d21af6SLei Zhang LLVM_DEBUG(llvm::dbgs() << name << " (Op)\n");
3277b196f1bSMarkus Böck return formatv(fmt, name);
32823d21af6SLei Zhang }
32923d21af6SLei Zhang
33031cfee60SLei Zhang // We are referencing all results of the multi-result op. A specific result
33131cfee60SLei Zhang // can either be a value or a range. Then join them with `separator`.
33231cfee60SLei Zhang SmallVector<std::string, 4> values;
33331cfee60SLei Zhang values.reserve(op->getNumResults());
33431cfee60SLei Zhang
33531cfee60SLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) {
336adcd0268SBenjamin Kramer std::string v = std::string(formatv("{0}.getODSResults({1})", name, i));
33731cfee60SLei Zhang if (!op->getResult(i).isVariadic()) {
338adcd0268SBenjamin Kramer v = std::string(formatv("(*{0}.begin())", v));
33931cfee60SLei Zhang }
340adcd0268SBenjamin Kramer values.push_back(std::string(formatv(fmt, v)));
34131cfee60SLei Zhang }
3421358df19SLei Zhang auto repl = llvm::join(values, separator);
3431358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n");
3441358df19SLei Zhang return repl;
34531cfee60SLei Zhang }
34631cfee60SLei Zhang case Kind::Value: {
34731cfee60SLei Zhang assert(index < 0);
34831cfee60SLei Zhang assert(op == nullptr);
3491358df19SLei Zhang auto repl = formatv(fmt, name);
3501358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n");
351adcd0268SBenjamin Kramer return std::string(repl);
35231cfee60SLei Zhang }
353d7314b3cSChia-hung Duan case Kind::MultipleValues: {
354d7314b3cSChia-hung Duan assert(op == nullptr);
355d7314b3cSChia-hung Duan assert(index < getSize());
356d7314b3cSChia-hung Duan if (index >= 0) {
357d7314b3cSChia-hung Duan std::string repl =
358d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}[{1}]", name, index)));
359d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n");
360d7314b3cSChia-hung Duan return repl;
361d7314b3cSChia-hung Duan }
362d7314b3cSChia-hung Duan // If it doesn't specify certain element, unpack them all.
363d7314b3cSChia-hung Duan auto repl =
364d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}.begin(), {0}.end()", name)));
365d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n");
366d7314b3cSChia-hung Duan return std::string(repl);
367d7314b3cSChia-hung Duan }
36831cfee60SLei Zhang }
36994298ceaSLei Zhang llvm_unreachable("unknown kind");
37031cfee60SLei Zhang }
37131cfee60SLei Zhang
getAllRangeUse(StringRef name,int index,const char * fmt,const char * separator) const37212d16de5SRahul Joshi std::string SymbolInfoMap::SymbolInfo::getAllRangeUse(
37331cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const {
3741358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getAllRangeUse for '" << name << "': ");
375ac68637bSLei Zhang switch (kind) {
376ac68637bSLei Zhang case Kind::Attr:
377ac68637bSLei Zhang case Kind::Operand: {
378ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result");
3791358df19SLei Zhang auto repl = formatv(fmt, name);
3801358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Operand/Attr)\n");
381adcd0268SBenjamin Kramer return std::string(repl);
382ac68637bSLei Zhang }
383ac68637bSLei Zhang case Kind::Result: {
384ac68637bSLei Zhang if (index >= 0) {
3851358df19SLei Zhang auto repl = formatv(fmt, formatv("{0}.getODSResults({1})", name, index));
3861358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n");
387adcd0268SBenjamin Kramer return std::string(repl);
388ac68637bSLei Zhang }
389ac68637bSLei Zhang
39031cfee60SLei Zhang // We are referencing all results of the multi-result op. Each result should
39131cfee60SLei Zhang // have a value range, and then join them with `separator`.
392ac68637bSLei Zhang SmallVector<std::string, 4> values;
39331cfee60SLei Zhang values.reserve(op->getNumResults());
39431cfee60SLei Zhang
395ac68637bSLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) {
396adcd0268SBenjamin Kramer values.push_back(std::string(
397adcd0268SBenjamin Kramer formatv(fmt, formatv("{0}.getODSResults({1})", name, i))));
398ac68637bSLei Zhang }
3991358df19SLei Zhang auto repl = llvm::join(values, separator);
4001358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n");
4011358df19SLei Zhang return repl;
402ac68637bSLei Zhang }
403ac68637bSLei Zhang case Kind::Value: {
404ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result");
405ac68637bSLei Zhang assert(op == nullptr);
40660f1d263SLei Zhang auto repl = formatv(fmt, formatv("{{{0}}", name));
4071358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n");
408adcd0268SBenjamin Kramer return std::string(repl);
409ac68637bSLei Zhang }
410d7314b3cSChia-hung Duan case Kind::MultipleValues: {
411d7314b3cSChia-hung Duan assert(op == nullptr);
412d7314b3cSChia-hung Duan assert(index < getSize());
413d7314b3cSChia-hung Duan if (index >= 0) {
414d7314b3cSChia-hung Duan std::string repl =
415d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}[{1}]", name, index)));
416d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n");
417d7314b3cSChia-hung Duan return repl;
418d7314b3cSChia-hung Duan }
419d7314b3cSChia-hung Duan auto repl =
420d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}.begin(), {0}.end()", name)));
421d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n");
422d7314b3cSChia-hung Duan return std::string(repl);
423d7314b3cSChia-hung Duan }
424ac68637bSLei Zhang }
42512ff145eSjpienaar llvm_unreachable("unknown kind");
426ac68637bSLei Zhang }
427ac68637bSLei Zhang
bindOpArgument(DagNode node,StringRef symbol,const Operator & op,int argIndex)428b4001ae8SChia-hung Duan bool SymbolInfoMap::bindOpArgument(DagNode node, StringRef symbol,
429b4001ae8SChia-hung Duan const Operator &op, int argIndex) {
430ac68637bSLei Zhang StringRef name = getValuePackName(symbol);
431ac68637bSLei Zhang if (name != symbol) {
432ac68637bSLei Zhang auto error = formatv(
433ac68637bSLei Zhang "symbol '{0}' with trailing index cannot bind to op argument", symbol);
434ac68637bSLei Zhang PrintFatalError(loc, error);
435ac68637bSLei Zhang }
436ac68637bSLei Zhang
437ac68637bSLei Zhang auto symInfo = op.getArg(argIndex).is<NamedAttribute *>()
438ac68637bSLei Zhang ? SymbolInfo::getAttr(&op, argIndex)
439b4001ae8SChia-hung Duan : SymbolInfo::getOperand(node, &op, argIndex);
440ac68637bSLei Zhang
441008c0ea6Srdzhabarov std::string key = symbol.str();
442008c0ea6Srdzhabarov if (symbolInfoMap.count(key)) {
443008c0ea6Srdzhabarov // Only non unique name for the operand is supported.
444008c0ea6Srdzhabarov if (symInfo.kind != SymbolInfo::Kind::Operand) {
445008c0ea6Srdzhabarov return false;
446008c0ea6Srdzhabarov }
447008c0ea6Srdzhabarov
448008c0ea6Srdzhabarov // Cannot add new operand if there is already non operand with the same
449008c0ea6Srdzhabarov // name.
450008c0ea6Srdzhabarov if (symbolInfoMap.find(key)->second.kind != SymbolInfo::Kind::Operand) {
451008c0ea6Srdzhabarov return false;
452008c0ea6Srdzhabarov }
453008c0ea6Srdzhabarov }
454008c0ea6Srdzhabarov
455008c0ea6Srdzhabarov symbolInfoMap.emplace(key, symInfo);
456008c0ea6Srdzhabarov return true;
457ac68637bSLei Zhang }
458ac68637bSLei Zhang
bindOpResult(StringRef symbol,const Operator & op)45912d16de5SRahul Joshi bool SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) {
460008c0ea6Srdzhabarov std::string name = getValuePackName(symbol).str();
461008c0ea6Srdzhabarov auto inserted = symbolInfoMap.emplace(name, SymbolInfo::getResult(&op));
462008c0ea6Srdzhabarov
463008c0ea6Srdzhabarov return symbolInfoMap.count(inserted->first) == 1;
464ac68637bSLei Zhang }
465ac68637bSLei Zhang
bindValues(StringRef symbol,int numValues)466d7314b3cSChia-hung Duan bool SymbolInfoMap::bindValues(StringRef symbol, int numValues) {
467d7314b3cSChia-hung Duan std::string name = getValuePackName(symbol).str();
468d7314b3cSChia-hung Duan if (numValues > 1)
469d7314b3cSChia-hung Duan return bindMultipleValues(name, numValues);
470d7314b3cSChia-hung Duan return bindValue(name);
471d7314b3cSChia-hung Duan }
472d7314b3cSChia-hung Duan
bindValue(StringRef symbol)47312d16de5SRahul Joshi bool SymbolInfoMap::bindValue(StringRef symbol) {
474008c0ea6Srdzhabarov auto inserted = symbolInfoMap.emplace(symbol.str(), SymbolInfo::getValue());
475008c0ea6Srdzhabarov return symbolInfoMap.count(inserted->first) == 1;
476ac68637bSLei Zhang }
477ac68637bSLei Zhang
bindMultipleValues(StringRef symbol,int numValues)478d7314b3cSChia-hung Duan bool SymbolInfoMap::bindMultipleValues(StringRef symbol, int numValues) {
479d7314b3cSChia-hung Duan std::string name = getValuePackName(symbol).str();
480d7314b3cSChia-hung Duan auto inserted =
481d7314b3cSChia-hung Duan symbolInfoMap.emplace(name, SymbolInfo::getMultipleValues(numValues));
482d7314b3cSChia-hung Duan return symbolInfoMap.count(inserted->first) == 1;
483d7314b3cSChia-hung Duan }
484d7314b3cSChia-hung Duan
bindAttr(StringRef symbol)4852bf423b0SRob Suderman bool SymbolInfoMap::bindAttr(StringRef symbol) {
486ad1fe396SRob Suderman auto inserted = symbolInfoMap.emplace(symbol.str(), SymbolInfo::getAttr());
4872bf423b0SRob Suderman return symbolInfoMap.count(inserted->first) == 1;
4882bf423b0SRob Suderman }
4892bf423b0SRob Suderman
contains(StringRef symbol) const49012d16de5SRahul Joshi bool SymbolInfoMap::contains(StringRef symbol) const {
491ac68637bSLei Zhang return find(symbol) != symbolInfoMap.end();
492ac68637bSLei Zhang }
493ac68637bSLei Zhang
find(StringRef key) const49412d16de5SRahul Joshi SymbolInfoMap::const_iterator SymbolInfoMap::find(StringRef key) const {
495008c0ea6Srdzhabarov std::string name = getValuePackName(key).str();
496008c0ea6Srdzhabarov
497ac68637bSLei Zhang return symbolInfoMap.find(name);
498ac68637bSLei Zhang }
499ac68637bSLei Zhang
500008c0ea6Srdzhabarov SymbolInfoMap::const_iterator
findBoundSymbol(StringRef key,DagNode node,const Operator & op,int argIndex) const501b4001ae8SChia-hung Duan SymbolInfoMap::findBoundSymbol(StringRef key, DagNode node, const Operator &op,
502008c0ea6Srdzhabarov int argIndex) const {
503bb250606SChia-hung Duan return findBoundSymbol(key, SymbolInfo::getOperand(node, &op, argIndex));
504bb250606SChia-hung Duan }
505bb250606SChia-hung Duan
506bb250606SChia-hung Duan SymbolInfoMap::const_iterator
findBoundSymbol(StringRef key,const SymbolInfo & symbolInfo) const5071fc096afSMehdi Amini SymbolInfoMap::findBoundSymbol(StringRef key,
5081fc096afSMehdi Amini const SymbolInfo &symbolInfo) const {
509008c0ea6Srdzhabarov std::string name = getValuePackName(key).str();
510008c0ea6Srdzhabarov auto range = symbolInfoMap.equal_range(name);
511008c0ea6Srdzhabarov
512d7314b3cSChia-hung Duan for (auto it = range.first; it != range.second; ++it)
513d7314b3cSChia-hung Duan if (it->second.dagAndConstant == symbolInfo.dagAndConstant)
514008c0ea6Srdzhabarov return it;
515008c0ea6Srdzhabarov
516008c0ea6Srdzhabarov return symbolInfoMap.end();
517008c0ea6Srdzhabarov }
518008c0ea6Srdzhabarov
519008c0ea6Srdzhabarov std::pair<SymbolInfoMap::iterator, SymbolInfoMap::iterator>
getRangeOfEqualElements(StringRef key)520008c0ea6Srdzhabarov SymbolInfoMap::getRangeOfEqualElements(StringRef key) {
521008c0ea6Srdzhabarov std::string name = getValuePackName(key).str();
522008c0ea6Srdzhabarov
523008c0ea6Srdzhabarov return symbolInfoMap.equal_range(name);
524008c0ea6Srdzhabarov }
525008c0ea6Srdzhabarov
count(StringRef key) const526008c0ea6Srdzhabarov int SymbolInfoMap::count(StringRef key) const {
527008c0ea6Srdzhabarov std::string name = getValuePackName(key).str();
528008c0ea6Srdzhabarov return symbolInfoMap.count(name);
529008c0ea6Srdzhabarov }
530008c0ea6Srdzhabarov
getStaticValueCount(StringRef symbol) const53112d16de5SRahul Joshi int SymbolInfoMap::getStaticValueCount(StringRef symbol) const {
532ac68637bSLei Zhang StringRef name = getValuePackName(symbol);
533ac68637bSLei Zhang if (name != symbol) {
534ac68637bSLei Zhang // If there is a trailing index inside symbol, it references just one
535ac68637bSLei Zhang // static value.
536ac68637bSLei Zhang return 1;
537ac68637bSLei Zhang }
538ac68637bSLei Zhang // Otherwise, find how many it represents by querying the symbol's info.
539008c0ea6Srdzhabarov return find(name)->second.getStaticValueCount();
540ac68637bSLei Zhang }
541ac68637bSLei Zhang
getValueAndRangeUse(StringRef symbol,const char * fmt,const char * separator) const54212d16de5SRahul Joshi std::string SymbolInfoMap::getValueAndRangeUse(StringRef symbol,
54312d16de5SRahul Joshi const char *fmt,
54431cfee60SLei Zhang const char *separator) const {
545ac68637bSLei Zhang int index = -1;
546ac68637bSLei Zhang StringRef name = getValuePackName(symbol, &index);
547ac68637bSLei Zhang
548008c0ea6Srdzhabarov auto it = symbolInfoMap.find(name.str());
549ac68637bSLei Zhang if (it == symbolInfoMap.end()) {
550ac68637bSLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol);
551ac68637bSLei Zhang PrintFatalError(loc, error);
552ac68637bSLei Zhang }
553ac68637bSLei Zhang
554008c0ea6Srdzhabarov return it->second.getValueAndRangeUse(name, index, fmt, separator);
55531cfee60SLei Zhang }
55631cfee60SLei Zhang
getAllRangeUse(StringRef symbol,const char * fmt,const char * separator) const55712d16de5SRahul Joshi std::string SymbolInfoMap::getAllRangeUse(StringRef symbol, const char *fmt,
55831cfee60SLei Zhang const char *separator) const {
55931cfee60SLei Zhang int index = -1;
56031cfee60SLei Zhang StringRef name = getValuePackName(symbol, &index);
56131cfee60SLei Zhang
562008c0ea6Srdzhabarov auto it = symbolInfoMap.find(name.str());
56331cfee60SLei Zhang if (it == symbolInfoMap.end()) {
56431cfee60SLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol);
56531cfee60SLei Zhang PrintFatalError(loc, error);
56631cfee60SLei Zhang }
56731cfee60SLei Zhang
568008c0ea6Srdzhabarov return it->second.getAllRangeUse(name, index, fmt, separator);
569008c0ea6Srdzhabarov }
570008c0ea6Srdzhabarov
assignUniqueAlternativeNames()571008c0ea6Srdzhabarov void SymbolInfoMap::assignUniqueAlternativeNames() {
572008c0ea6Srdzhabarov llvm::StringSet<> usedNames;
573008c0ea6Srdzhabarov
574008c0ea6Srdzhabarov for (auto symbolInfoIt = symbolInfoMap.begin();
575008c0ea6Srdzhabarov symbolInfoIt != symbolInfoMap.end();) {
576008c0ea6Srdzhabarov auto range = symbolInfoMap.equal_range(symbolInfoIt->first);
577008c0ea6Srdzhabarov auto startRange = range.first;
578008c0ea6Srdzhabarov auto endRange = range.second;
579008c0ea6Srdzhabarov
580008c0ea6Srdzhabarov auto operandName = symbolInfoIt->first;
581008c0ea6Srdzhabarov int startSearchIndex = 0;
582008c0ea6Srdzhabarov for (++startRange; startRange != endRange; ++startRange) {
583008c0ea6Srdzhabarov // Current operand name is not unique, find a unique one
584008c0ea6Srdzhabarov // and set the alternative name.
585008c0ea6Srdzhabarov for (int i = startSearchIndex;; ++i) {
586008c0ea6Srdzhabarov std::string alternativeName = operandName + std::to_string(i);
587008c0ea6Srdzhabarov if (!usedNames.contains(alternativeName) &&
588008c0ea6Srdzhabarov symbolInfoMap.count(alternativeName) == 0) {
589008c0ea6Srdzhabarov usedNames.insert(alternativeName);
590008c0ea6Srdzhabarov startRange->second.alternativeName = alternativeName;
591008c0ea6Srdzhabarov startSearchIndex = i + 1;
592008c0ea6Srdzhabarov
593008c0ea6Srdzhabarov break;
594008c0ea6Srdzhabarov }
595008c0ea6Srdzhabarov }
596008c0ea6Srdzhabarov }
597008c0ea6Srdzhabarov
598008c0ea6Srdzhabarov symbolInfoIt = endRange;
599008c0ea6Srdzhabarov }
600ac68637bSLei Zhang }
601ac68637bSLei Zhang
602ac68637bSLei Zhang //===----------------------------------------------------------------------===//
603ac68637bSLei Zhang // Pattern
604ac68637bSLei Zhang //==----------------------------------------------------------------------===//
605ac68637bSLei Zhang
Pattern(const llvm::Record * def,RecordOperatorMap * mapper)60612d16de5SRahul Joshi Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
607ac68637bSLei Zhang : def(*def), recordOpMap(mapper) {}
608eb753f4aSLei Zhang
getSourcePattern() const60912d16de5SRahul Joshi DagNode Pattern::getSourcePattern() const {
61012d16de5SRahul Joshi return DagNode(def.getValueAsDag("sourcePattern"));
611eb753f4aSLei Zhang }
612eb753f4aSLei Zhang
getNumResultPatterns() const61312d16de5SRahul Joshi int Pattern::getNumResultPatterns() const {
6148f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns");
615eb753f4aSLei Zhang return results->size();
616eb753f4aSLei Zhang }
617eb753f4aSLei Zhang
getResultPattern(unsigned index) const61812d16de5SRahul Joshi DagNode Pattern::getResultPattern(unsigned index) const {
6198f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns");
62012d16de5SRahul Joshi return DagNode(cast<llvm::DagInit>(results->getElement(index)));
621eb753f4aSLei Zhang }
622eb753f4aSLei Zhang
collectSourcePatternBoundSymbols(SymbolInfoMap & infoMap)62312d16de5SRahul Joshi void Pattern::collectSourcePatternBoundSymbols(SymbolInfoMap &infoMap) {
6241358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting source pattern bound symbols\n");
625ac68637bSLei Zhang collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true);
6261358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting source pattern bound symbols\n");
627008c0ea6Srdzhabarov
628008c0ea6Srdzhabarov LLVM_DEBUG(llvm::dbgs() << "start assigning alternative names for symbols\n");
629008c0ea6Srdzhabarov infoMap.assignUniqueAlternativeNames();
630008c0ea6Srdzhabarov LLVM_DEBUG(llvm::dbgs() << "done assigning alternative names for symbols\n");
631eb753f4aSLei Zhang }
632eb753f4aSLei Zhang
collectResultPatternBoundSymbols(SymbolInfoMap & infoMap)63312d16de5SRahul Joshi void Pattern::collectResultPatternBoundSymbols(SymbolInfoMap &infoMap) {
6341358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting result pattern bound symbols\n");
635ac68637bSLei Zhang for (int i = 0, e = getNumResultPatterns(); i < e; ++i) {
636ac68637bSLei Zhang auto pattern = getResultPattern(i);
637ac68637bSLei Zhang collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false);
638eb753f4aSLei Zhang }
6391358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting result pattern bound symbols\n");
640388fb375SJacques Pienaar }
641388fb375SJacques Pienaar
getSourceRootOp()64212d16de5SRahul Joshi const Operator &Pattern::getSourceRootOp() {
643eb753f4aSLei Zhang return getSourcePattern().getDialectOp(recordOpMap);
644eb753f4aSLei Zhang }
645eb753f4aSLei Zhang
getDialectOp(DagNode node)64612d16de5SRahul Joshi Operator &Pattern::getDialectOp(DagNode node) {
647eb753f4aSLei Zhang return node.getDialectOp(recordOpMap);
648eb753f4aSLei Zhang }
649388fb375SJacques Pienaar
getConstraints() const65012d16de5SRahul Joshi std::vector<AppliedConstraint> Pattern::getConstraints() const {
651388fb375SJacques Pienaar auto *listInit = def.getValueAsListInit("constraints");
65212d16de5SRahul Joshi std::vector<AppliedConstraint> ret;
653388fb375SJacques Pienaar ret.reserve(listInit->size());
6548f5fa566SLei Zhang
65502b6fb21SMehdi Amini for (auto *it : *listInit) {
6568f5fa566SLei Zhang auto *dagInit = dyn_cast<llvm::DagInit>(it);
6578f5fa566SLei Zhang if (!dagInit)
6582bf423b0SRob Suderman PrintFatalError(&def, "all elements in Pattern multi-entity "
6598f5fa566SLei Zhang "constraints should be DAG nodes");
6608f5fa566SLei Zhang
6618f5fa566SLei Zhang std::vector<std::string> entities;
6628f5fa566SLei Zhang entities.reserve(dagInit->arg_size());
663cb40e36dSLei Zhang for (auto *argName : dagInit->getArgNames()) {
664cb40e36dSLei Zhang if (!argName) {
665cb40e36dSLei Zhang PrintFatalError(
6662bf423b0SRob Suderman &def,
667cb40e36dSLei Zhang "operands to additional constraints can only be symbol references");
668cb40e36dSLei Zhang }
669e5639b3fSMehdi Amini entities.emplace_back(argName->getValue());
670cb40e36dSLei Zhang }
6718f5fa566SLei Zhang
6728f5fa566SLei Zhang ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
673c72d849eSLei Zhang dagInit->getNameStr(), std::move(entities));
674388fb375SJacques Pienaar }
675388fb375SJacques Pienaar return ret;
676388fb375SJacques Pienaar }
67753035874SFeng Liu
getBenefit() const67812d16de5SRahul Joshi int Pattern::getBenefit() const {
679a0606ca7SFeng Liu // The initial benefit value is a heuristic with number of ops in the source
68053035874SFeng Liu // pattern.
681a0606ca7SFeng Liu int initBenefit = getSourcePattern().getNumOps();
68253035874SFeng Liu llvm::DagInit *delta = def.getValueAsDag("benefitDelta");
683a0606ca7SFeng Liu if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) {
6842bf423b0SRob Suderman PrintFatalError(&def,
685a0606ca7SFeng Liu "The 'addBenefit' takes and only takes one integer value");
686a0606ca7SFeng Liu }
687a0606ca7SFeng Liu return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue();
68853035874SFeng Liu }
68904b6d2f3SLei Zhang
getLocation() const69012d16de5SRahul Joshi std::vector<Pattern::IdentifierLine> Pattern::getLocation() const {
6914165885aSJacques Pienaar std::vector<std::pair<StringRef, unsigned>> result;
6924165885aSJacques Pienaar result.reserve(def.getLoc().size());
6934165885aSJacques Pienaar for (auto loc : def.getLoc()) {
6944165885aSJacques Pienaar unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc);
6954165885aSJacques Pienaar assert(buf && "invalid source location");
6964165885aSJacques Pienaar result.emplace_back(
6974165885aSJacques Pienaar llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(),
6984165885aSJacques Pienaar llvm::SrcMgr.getLineAndColumn(loc, buf).first);
6994165885aSJacques Pienaar }
7004165885aSJacques Pienaar return result;
7014165885aSJacques Pienaar }
7024165885aSJacques Pienaar
verifyBind(bool result,StringRef symbolName)7032bf423b0SRob Suderman void Pattern::verifyBind(bool result, StringRef symbolName) {
7042bf423b0SRob Suderman if (!result) {
7052bf423b0SRob Suderman auto err = formatv("symbol '{0}' bound more than once", symbolName);
7062bf423b0SRob Suderman PrintFatalError(&def, err);
7072bf423b0SRob Suderman }
7082bf423b0SRob Suderman }
7092bf423b0SRob Suderman
collectBoundSymbols(DagNode tree,SymbolInfoMap & infoMap,bool isSrcPattern)71012d16de5SRahul Joshi void Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap,
711e032d0dcSLei Zhang bool isSrcPattern) {
712e032d0dcSLei Zhang auto treeName = tree.getSymbol();
7132bf423b0SRob Suderman auto numTreeArgs = tree.getNumArgs();
7142bf423b0SRob Suderman
7152bf423b0SRob Suderman if (tree.isNativeCodeCall()) {
716e032d0dcSLei Zhang if (!treeName.empty()) {
71734b5482bSChia-hung Duan if (!isSrcPattern) {
71834b5482bSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "found symbol bound to NativeCodeCall: "
71934b5482bSChia-hung Duan << treeName << '\n');
720d7314b3cSChia-hung Duan verifyBind(
721d7314b3cSChia-hung Duan infoMap.bindValues(treeName, tree.getNumReturnsOfNativeCode()),
722d7314b3cSChia-hung Duan treeName);
72334b5482bSChia-hung Duan } else {
72434b5482bSChia-hung Duan PrintFatalError(&def,
72534b5482bSChia-hung Duan formatv("binding symbol '{0}' to NativecodeCall in "
72634b5482bSChia-hung Duan "MatchPattern is not supported",
727e032d0dcSLei Zhang treeName));
728e032d0dcSLei Zhang }
72934b5482bSChia-hung Duan }
7302bf423b0SRob Suderman
7312bf423b0SRob Suderman for (int i = 0; i != numTreeArgs; ++i) {
7322bf423b0SRob Suderman if (auto treeArg = tree.getArgAsNestedDag(i)) {
7332bf423b0SRob Suderman // This DAG node argument is a DAG node itself. Go inside recursively.
7342bf423b0SRob Suderman collectBoundSymbols(treeArg, infoMap, isSrcPattern);
7352bf423b0SRob Suderman continue;
7362bf423b0SRob Suderman }
7372bf423b0SRob Suderman
7382bf423b0SRob Suderman if (!isSrcPattern)
7392bf423b0SRob Suderman continue;
7402bf423b0SRob Suderman
7412bf423b0SRob Suderman // We can only bind symbols to arguments in source pattern. Those
7422bf423b0SRob Suderman // symbols are referenced in result patterns.
7432bf423b0SRob Suderman auto treeArgName = tree.getArgName(i);
7442bf423b0SRob Suderman
7452bf423b0SRob Suderman // `$_` is a special symbol meaning ignore the current argument.
7462bf423b0SRob Suderman if (!treeArgName.empty() && treeArgName != "_") {
7472bf423b0SRob Suderman DagLeaf leaf = tree.getArgAsLeaf(i);
74834b5482bSChia-hung Duan
74934b5482bSChia-hung Duan // In (NativeCodeCall<"Foo($_self, $0, $1, $2)"> I8Attr:$a, I8:$b, $c),
75034b5482bSChia-hung Duan if (leaf.isUnspecified()) {
75134b5482bSChia-hung Duan // This is case of $c, a Value without any constraints.
75234b5482bSChia-hung Duan verifyBind(infoMap.bindValue(treeArgName), treeArgName);
75334b5482bSChia-hung Duan } else {
7542bf423b0SRob Suderman auto constraint = leaf.getAsConstraint();
7552bf423b0SRob Suderman bool isAttr = leaf.isAttrMatcher() || leaf.isEnumAttrCase() ||
7562bf423b0SRob Suderman leaf.isConstantAttr() ||
7572bf423b0SRob Suderman constraint.getKind() == Constraint::Kind::CK_Attr;
7582bf423b0SRob Suderman
7592bf423b0SRob Suderman if (isAttr) {
76034b5482bSChia-hung Duan // This is case of $a, a binding to a certain attribute.
7612bf423b0SRob Suderman verifyBind(infoMap.bindAttr(treeArgName), treeArgName);
7622bf423b0SRob Suderman continue;
7632bf423b0SRob Suderman }
7642bf423b0SRob Suderman
76534b5482bSChia-hung Duan // This is case of $b, a binding to a certain type.
7662bf423b0SRob Suderman verifyBind(infoMap.bindValue(treeArgName), treeArgName);
7672bf423b0SRob Suderman }
7682bf423b0SRob Suderman }
76934b5482bSChia-hung Duan }
7702bf423b0SRob Suderman
771e032d0dcSLei Zhang return;
772e032d0dcSLei Zhang }
773e032d0dcSLei Zhang
7742bf423b0SRob Suderman if (tree.isOperation()) {
77504b6d2f3SLei Zhang auto &op = getDialectOp(tree);
77604b6d2f3SLei Zhang auto numOpArgs = op.getNumArgs();
7772d99c815SChia-hung Duan int numEither = 0;
77804b6d2f3SLei Zhang
7792d99c815SChia-hung Duan // We need to exclude the trailing directives and `either` directive groups
7802d99c815SChia-hung Duan // two operands of the operation.
781cb8c30d3SMogball int numDirectives = 0;
782cb8c30d3SMogball for (int i = numTreeArgs - 1; i >= 0; --i) {
783cb8c30d3SMogball if (auto dagArg = tree.getArgAsNestedDag(i)) {
784cb8c30d3SMogball if (dagArg.isLocationDirective() || dagArg.isReturnTypeDirective())
785cb8c30d3SMogball ++numDirectives;
7862d99c815SChia-hung Duan else if (dagArg.isEither())
7872d99c815SChia-hung Duan ++numEither;
788cb8c30d3SMogball }
7893f7439b2SJacques Pienaar }
7903f7439b2SJacques Pienaar
7912d99c815SChia-hung Duan if (numOpArgs != numTreeArgs - numDirectives + numEither) {
7922d99c815SChia-hung Duan auto err =
7932d99c815SChia-hung Duan formatv("op '{0}' argument number mismatch: "
79404b6d2f3SLei Zhang "{1} in pattern vs. {2} in definition",
7952d99c815SChia-hung Duan op.getOperationName(), numTreeArgs + numEither, numOpArgs);
7962bf423b0SRob Suderman PrintFatalError(&def, err);
79704b6d2f3SLei Zhang }
79804b6d2f3SLei Zhang
79904b6d2f3SLei Zhang // The name attached to the DAG node's operator is for representing the
80004b6d2f3SLei Zhang // results generated from this op. It should be remembered as bound results.
801ac68637bSLei Zhang if (!treeName.empty()) {
8021358df19SLei Zhang LLVM_DEBUG(llvm::dbgs()
8031358df19SLei Zhang << "found symbol bound to op result: " << treeName << '\n');
8042bf423b0SRob Suderman verifyBind(infoMap.bindOpResult(treeName, op), treeName);
805ac68637bSLei Zhang }
80604b6d2f3SLei Zhang
8072d99c815SChia-hung Duan // The operand in `either` DAG should be bound to the operation in the
8082d99c815SChia-hung Duan // parent DagNode.
8092d99c815SChia-hung Duan auto collectSymbolInEither = [&](DagNode parent, DagNode tree,
8102d99c815SChia-hung Duan int &opArgIdx) {
8112d99c815SChia-hung Duan for (int i = 0; i < tree.getNumArgs(); ++i, ++opArgIdx) {
8122d99c815SChia-hung Duan if (DagNode subTree = tree.getArgAsNestedDag(i)) {
8132d99c815SChia-hung Duan collectBoundSymbols(subTree, infoMap, isSrcPattern);
8142d99c815SChia-hung Duan } else {
8152d99c815SChia-hung Duan auto argName = tree.getArgName(i);
8162d99c815SChia-hung Duan if (!argName.empty() && argName != "_")
8172d99c815SChia-hung Duan verifyBind(infoMap.bindOpArgument(parent, argName, op, opArgIdx),
8182d99c815SChia-hung Duan argName);
8192d99c815SChia-hung Duan }
8202d99c815SChia-hung Duan }
8212d99c815SChia-hung Duan };
8222d99c815SChia-hung Duan
8232d99c815SChia-hung Duan for (int i = 0, opArgIdx = 0; i != numTreeArgs; ++i, ++opArgIdx) {
82404b6d2f3SLei Zhang if (auto treeArg = tree.getArgAsNestedDag(i)) {
8252d99c815SChia-hung Duan if (treeArg.isEither()) {
8262d99c815SChia-hung Duan collectSymbolInEither(tree, treeArg, opArgIdx);
8272d99c815SChia-hung Duan } else {
82804b6d2f3SLei Zhang // This DAG node argument is a DAG node itself. Go inside recursively.
829ac68637bSLei Zhang collectBoundSymbols(treeArg, infoMap, isSrcPattern);
8302d99c815SChia-hung Duan }
8312bf423b0SRob Suderman continue;
8322bf423b0SRob Suderman }
8332bf423b0SRob Suderman
8342bf423b0SRob Suderman if (isSrcPattern) {
835e032d0dcSLei Zhang // We can only bind symbols to op arguments in source pattern. Those
836e032d0dcSLei Zhang // symbols are referenced in result patterns.
83704b6d2f3SLei Zhang auto treeArgName = tree.getArgName(i);
8384982eaf8SLei Zhang // `$_` is a special symbol meaning ignore the current argument.
8394982eaf8SLei Zhang if (!treeArgName.empty() && treeArgName != "_") {
8401358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "found symbol bound to op argument: "
8411358df19SLei Zhang << treeArgName << '\n');
8422d99c815SChia-hung Duan verifyBind(infoMap.bindOpArgument(tree, treeArgName, op, opArgIdx),
843b4001ae8SChia-hung Duan treeArgName);
844ac68637bSLei Zhang }
845ac68637bSLei Zhang }
84604b6d2f3SLei Zhang }
8472bf423b0SRob Suderman return;
84804b6d2f3SLei Zhang }
8492bf423b0SRob Suderman
8502bf423b0SRob Suderman if (!treeName.empty()) {
8512bf423b0SRob Suderman PrintFatalError(
8522bf423b0SRob Suderman &def, formatv("binding symbol '{0}' to non-operation/native code call "
8532bf423b0SRob Suderman "unsupported right now",
8542bf423b0SRob Suderman treeName));
8552bf423b0SRob Suderman }
85604b6d2f3SLei Zhang }
857