2019-01-29 06:04:40 +08:00
|
|
|
//===- Pattern.cpp - Pattern wrapper class ----------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
// Pattern wrapper class to simplify using TableGen Record defining a MLIR
|
|
|
|
// Pattern.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "mlir/TableGen/Pattern.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
#include "llvm/TableGen/Error.h"
|
2019-01-29 06:04:40 +08:00
|
|
|
#include "llvm/TableGen/Record.h"
|
|
|
|
|
|
|
|
using namespace mlir;
|
|
|
|
|
|
|
|
using mlir::tblgen::Operator;
|
|
|
|
|
2019-02-02 07:40:22 +08:00
|
|
|
bool tblgen::DagLeaf::isUnspecified() const {
|
|
|
|
return !def || isa<llvm::UnsetInit>(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tblgen::DagLeaf::isOperandMatcher() const {
|
|
|
|
if (!def || !isa<llvm::DefInit>(def))
|
|
|
|
return false;
|
|
|
|
// Operand matchers specify a type constraint.
|
|
|
|
return cast<llvm::DefInit>(def)->getDef()->isSubClassOf("TypeConstraint");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tblgen::DagLeaf::isAttrMatcher() const {
|
|
|
|
if (!def || !isa<llvm::DefInit>(def))
|
|
|
|
return false;
|
2019-03-13 04:55:50 +08:00
|
|
|
// Attribute matchers specify an attribute constraint.
|
2019-02-02 07:40:22 +08:00
|
|
|
return cast<llvm::DefInit>(def)->getDef()->isSubClassOf("AttrConstraint");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tblgen::DagLeaf::isAttrTransformer() const {
|
|
|
|
if (!def || !isa<llvm::DefInit>(def))
|
|
|
|
return false;
|
|
|
|
return cast<llvm::DefInit>(def)->getDef()->isSubClassOf("tAttr");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tblgen::DagLeaf::isConstantAttr() const {
|
|
|
|
if (!def || !isa<llvm::DefInit>(def))
|
|
|
|
return false;
|
|
|
|
return cast<llvm::DefInit>(def)->getDef()->isSubClassOf("ConstantAttr");
|
|
|
|
}
|
|
|
|
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const {
|
|
|
|
assert((isOperandMatcher() || isAttrMatcher()) &&
|
|
|
|
"the DAG leaf must be operand or attribute");
|
|
|
|
return Constraint(cast<llvm::DefInit>(def)->getDef());
|
2019-02-02 07:40:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const {
|
|
|
|
assert(isConstantAttr() && "the DAG leaf must be constant attribute");
|
|
|
|
return ConstantAttr(cast<llvm::DefInit>(def));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string tblgen::DagLeaf::getConditionTemplate() const {
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
return getAsConstraint().getConditionTemplate();
|
2019-02-02 07:40:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string tblgen::DagLeaf::getTransformationTemplate() const {
|
|
|
|
assert(isAttrTransformer() && "the DAG leaf must be attribute transformer");
|
|
|
|
return cast<llvm::DefInit>(def)
|
|
|
|
->getDef()
|
|
|
|
->getValueAsString("attrTransform")
|
|
|
|
.str();
|
2019-01-29 06:04:40 +08:00
|
|
|
}
|
|
|
|
|
2019-03-13 04:55:50 +08:00
|
|
|
bool tblgen::DagNode::isAttrTransformer() const {
|
|
|
|
auto op = node->getOperator();
|
|
|
|
if (!op || !isa<llvm::DefInit>(op))
|
|
|
|
return false;
|
|
|
|
return cast<llvm::DefInit>(op)->getDef()->isSubClassOf("tAttr");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string tblgen::DagNode::getTransformationTemplate() const {
|
|
|
|
assert(isAttrTransformer() && "the DAG leaf must be attribute transformer");
|
|
|
|
return cast<llvm::DefInit>(node->getOperator())
|
|
|
|
->getDef()
|
|
|
|
->getValueAsString("attrTransform")
|
|
|
|
.str();
|
|
|
|
}
|
|
|
|
|
2019-02-14 06:30:40 +08:00
|
|
|
llvm::StringRef tblgen::DagNode::getOpName() const {
|
|
|
|
return node->getNameStr();
|
|
|
|
}
|
|
|
|
|
2019-01-29 06:04:40 +08:00
|
|
|
Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const {
|
|
|
|
llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef();
|
|
|
|
return mapper->try_emplace(opDef, opDef).first->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned tblgen::DagNode::getNumOps() const {
|
|
|
|
unsigned count = isReplaceWithValue() ? 0 : 1;
|
|
|
|
for (unsigned i = 0, e = getNumArgs(); i != e; ++i) {
|
|
|
|
if (auto child = getArgAsNestedDag(i))
|
|
|
|
count += child.getNumOps();
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); }
|
|
|
|
|
|
|
|
bool tblgen::DagNode::isNestedDagArg(unsigned index) const {
|
|
|
|
return isa<llvm::DagInit>(node->getArg(index));
|
|
|
|
}
|
|
|
|
|
|
|
|
tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const {
|
|
|
|
return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index)));
|
|
|
|
}
|
|
|
|
|
2019-02-02 07:40:22 +08:00
|
|
|
tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const {
|
|
|
|
assert(!isNestedDagArg(index));
|
|
|
|
return DagLeaf(node->getArg(index));
|
2019-01-29 06:04:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
StringRef tblgen::DagNode::getArgName(unsigned index) const {
|
|
|
|
return node->getArgNameStr(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void collectBoundArguments(const llvm::DagInit *tree,
|
|
|
|
tblgen::Pattern *pattern) {
|
|
|
|
auto &op = pattern->getDialectOp(tblgen::DagNode(tree));
|
2019-02-14 06:30:40 +08:00
|
|
|
if (llvm::StringInit *si = tree->getName()) {
|
|
|
|
auto name = si->getAsUnquotedString();
|
|
|
|
if (!name.empty())
|
|
|
|
pattern->getSourcePatternBoundResults().insert(name);
|
|
|
|
}
|
2019-01-29 06:04:40 +08:00
|
|
|
|
|
|
|
// TODO(jpienaar): Expand to multiple matches.
|
|
|
|
for (unsigned i = 0, e = tree->getNumArgs(); i != e; ++i) {
|
|
|
|
auto *arg = tree->getArg(i);
|
|
|
|
|
|
|
|
if (auto *argTree = dyn_cast<llvm::DagInit>(arg)) {
|
|
|
|
collectBoundArguments(argTree, pattern);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef name = tree->getArgNameStr(i);
|
|
|
|
if (name.empty())
|
|
|
|
continue;
|
|
|
|
|
2019-02-02 07:40:22 +08:00
|
|
|
pattern->getSourcePatternBoundArgs().try_emplace(name, op.getArg(i));
|
2019-01-29 06:04:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tblgen::DagNode::collectBoundArguments(tblgen::Pattern *pattern) const {
|
|
|
|
::collectBoundArguments(node, pattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool tblgen::DagNode::isReplaceWithValue() const {
|
|
|
|
auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
|
|
|
|
return dagOpDef->getName() == "replaceWithValue";
|
|
|
|
}
|
|
|
|
|
2019-03-09 05:56:53 +08:00
|
|
|
bool tblgen::DagNode::isVerifyUnusedValue() const {
|
|
|
|
auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
|
|
|
|
return dagOpDef->getName() == "verifyUnusedValue";
|
|
|
|
}
|
|
|
|
|
2019-02-01 09:57:06 +08:00
|
|
|
bool tblgen::DagNode::isNativeCodeBuilder() const {
|
|
|
|
auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
|
|
|
|
return dagOpDef->isSubClassOf("cOp");
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::StringRef tblgen::DagNode::getNativeCodeBuilder() const {
|
|
|
|
assert(isNativeCodeBuilder());
|
|
|
|
auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef();
|
|
|
|
return dagOpDef->getValueAsString("function");
|
|
|
|
}
|
|
|
|
|
2019-01-29 06:04:40 +08:00
|
|
|
tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper)
|
|
|
|
: def(*def), recordOpMap(mapper) {
|
|
|
|
getSourcePattern().collectBoundArguments(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
tblgen::DagNode tblgen::Pattern::getSourcePattern() const {
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
return tblgen::DagNode(def.getValueAsDag("sourcePattern"));
|
2019-01-29 06:04:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned tblgen::Pattern::getNumResults() const {
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
auto *results = def.getValueAsListInit("resultPatterns");
|
2019-01-29 06:04:40 +08:00
|
|
|
return results->size();
|
|
|
|
}
|
|
|
|
|
|
|
|
tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const {
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
auto *results = def.getValueAsListInit("resultPatterns");
|
2019-01-29 06:04:40 +08:00
|
|
|
return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index)));
|
|
|
|
}
|
|
|
|
|
2019-02-09 22:36:23 +08:00
|
|
|
bool tblgen::Pattern::isArgBoundInSourcePattern(llvm::StringRef name) const {
|
|
|
|
return boundArguments.find(name) != boundArguments.end();
|
|
|
|
}
|
|
|
|
|
2019-02-14 06:30:40 +08:00
|
|
|
bool tblgen::Pattern::isResultBoundInSourcePattern(llvm::StringRef name) const {
|
|
|
|
return boundResults.count(name);
|
|
|
|
}
|
|
|
|
|
2019-01-29 06:04:40 +08:00
|
|
|
void tblgen::Pattern::ensureArgBoundInSourcePattern(
|
|
|
|
llvm::StringRef name) const {
|
2019-02-09 22:36:23 +08:00
|
|
|
if (!isArgBoundInSourcePattern(name))
|
2019-01-29 06:04:40 +08:00
|
|
|
PrintFatalError(def.getLoc(),
|
|
|
|
Twine("referencing unbound variable '") + name + "'");
|
|
|
|
}
|
|
|
|
|
2019-02-02 07:40:22 +08:00
|
|
|
llvm::StringMap<tblgen::Argument> &
|
|
|
|
tblgen::Pattern::getSourcePatternBoundArgs() {
|
2019-01-29 06:04:40 +08:00
|
|
|
return boundArguments;
|
|
|
|
}
|
|
|
|
|
2019-02-14 06:30:40 +08:00
|
|
|
llvm::StringSet<> &tblgen::Pattern::getSourcePatternBoundResults() {
|
|
|
|
return boundResults;
|
|
|
|
}
|
|
|
|
|
2019-01-29 06:04:40 +08:00
|
|
|
const tblgen::Operator &tblgen::Pattern::getSourceRootOp() {
|
|
|
|
return getSourcePattern().getDialectOp(recordOpMap);
|
|
|
|
}
|
|
|
|
|
|
|
|
tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) {
|
|
|
|
return node.getDialectOp(recordOpMap);
|
|
|
|
}
|
2019-02-14 06:30:40 +08:00
|
|
|
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const {
|
2019-02-14 06:30:40 +08:00
|
|
|
auto *listInit = def.getValueAsListInit("constraints");
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
std::vector<tblgen::AppliedConstraint> ret;
|
2019-02-14 06:30:40 +08:00
|
|
|
ret.reserve(listInit->size());
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
|
2019-02-14 06:30:40 +08:00
|
|
|
for (auto it : *listInit) {
|
[TableGen] Consolidate constraint related concepts
Previously we have multiple mechanisms to specify op definition and match constraints:
TypeConstraint, AttributeConstraint, Type, Attr, mAttr, mAttrAnyOf, mPat. These variants
are not added because there are so many distinct cases we need to model; essentially,
they are all carrying a predicate. It's just an artifact of implementation.
It's quite confusing for users to grasp these variants and choose among them. Instead,
as the OpBase TableGen file, we need to strike to provide an unified mechanism. Each
dialect has the flexibility to define its own aliases if wanted.
This CL removes mAttr, mAttrAnyOf, mPat. A new base class, Constraint, is added. Now
TypeConstraint and AttrConstraint derive from Constraint. Type and Attr further derive
from TypeConstraint and AttrConstraint, respectively.
Comments are revised and examples are added to make it clear how to use constraints.
PiperOrigin-RevId: 240125076
2019-03-25 21:09:26 +08:00
|
|
|
auto *dagInit = dyn_cast<llvm::DagInit>(it);
|
|
|
|
if (!dagInit)
|
|
|
|
PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity "
|
|
|
|
"constraints should be DAG nodes");
|
|
|
|
|
|
|
|
std::vector<std::string> entities;
|
|
|
|
entities.reserve(dagInit->arg_size());
|
|
|
|
for (auto *argName : dagInit->getArgNames())
|
|
|
|
entities.push_back(argName->getValue());
|
|
|
|
|
|
|
|
ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(),
|
|
|
|
std::move(entities));
|
2019-02-14 06:30:40 +08:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|