-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[mlir][tblgen] Fix bug when mixing props and InferTypes #157367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
c7654ab
to
7dfa2d4
Compare
@llvm/pr-subscribers-mlir Author: Fabian Mora (fabianmcg) ChangesThis patch fixes a bug occurring when properties are mixed with any of the InferType traits, causing tblgen to crash. A simple reproducer is:
The issue occurs because of the call:
To understand better the issue, consider:
In this case, The fix is to change Full diff: https://github.com/llvm/llvm-project/pull/157367.diff 4 Files Affected:
diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h
index 9e570373d9cd3..f0514d8e61748 100644
--- a/mlir/include/mlir/TableGen/Operator.h
+++ b/mlir/include/mlir/TableGen/Operator.h
@@ -323,21 +323,22 @@ class Operator {
/// Requires: all result types are known.
const InferredResultType &getInferredResultType(int index) const;
- /// Pair consisting kind of argument and index into operands or attributes.
- struct OperandOrAttribute {
- enum class Kind { Operand, Attribute };
- OperandOrAttribute(Kind kind, int index) {
- packed = (index << 1) | (kind == Kind::Attribute);
+ /// Pair consisting kind of argument and index into operands, attributes, or
+ /// properties.
+ struct OperandAttrOrProp {
+ enum class Kind { Operand = 0x0, Attribute = 0x1, Property = 0x2 };
+ OperandAttrOrProp(Kind kind, int index) {
+ packed = (index << 2) | static_cast<int>(kind);
}
- int operandOrAttributeIndex() const { return (packed >> 1); }
- Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; }
+ int operandOrAttributeIndex() const { return (packed >> 2); }
+ Kind kind() const { return static_cast<Kind>(packed & 0x3); }
private:
int packed;
};
- /// Returns the OperandOrAttribute corresponding to the index.
- OperandOrAttribute getArgToOperandOrAttribute(int index) const;
+ /// Returns the OperandAttrOrProp corresponding to the index.
+ OperandAttrOrProp getArgToOperandAttrOrProp(int index) const;
/// Returns the builders of this operation.
ArrayRef<Builder> getBuilders() const { return builders; }
@@ -405,8 +406,8 @@ class Operator {
/// The argument with the same type as the result.
SmallVector<InferredResultType> resultTypeMapping;
- /// Map from argument to attribute or operand number.
- SmallVector<OperandOrAttribute, 4> attrOrOperandMapping;
+ /// Map from argument to attribute, property, or operand number.
+ SmallVector<OperandAttrOrProp, 4> attrPropOrOperandMapping;
/// The builders of this operator.
SmallVector<Builder> builders;
diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp
index da86b00ebc300..926ffd0e363a0 100644
--- a/mlir/lib/TableGen/Operator.cpp
+++ b/mlir/lib/TableGen/Operator.cpp
@@ -385,7 +385,8 @@ void Operator::populateTypeInferenceInfo(
if (getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
// Check for a non-variable length operand to use as the type anchor.
auto *operandI = llvm::find_if(arguments, [](const Argument &arg) {
- NamedTypeConstraint *operand = llvm::dyn_cast_if_present<NamedTypeConstraint *>(arg);
+ NamedTypeConstraint *operand =
+ llvm::dyn_cast_if_present<NamedTypeConstraint *>(arg);
return operand && !operand->isVariableLength();
});
if (operandI == arguments.end())
@@ -663,15 +664,17 @@ void Operator::populateOpStructure() {
argDef = argDef->getValueAsDef("constraint");
if (argDef->isSubClassOf(typeConstraintClass)) {
- attrOrOperandMapping.push_back(
- {OperandOrAttribute::Kind::Operand, operandIndex});
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Operand, operandIndex});
arguments.emplace_back(&operands[operandIndex++]);
} else if (argDef->isSubClassOf(attrClass)) {
- attrOrOperandMapping.push_back(
- {OperandOrAttribute::Kind::Attribute, attrIndex});
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Attribute, attrIndex});
arguments.emplace_back(&attributes[attrIndex++]);
} else {
assert(argDef->isSubClassOf(propertyClass));
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Property, propIndex});
arguments.emplace_back(&properties[propIndex++]);
}
}
@@ -867,9 +870,8 @@ auto Operator::VariableDecoratorIterator::unwrap(const Init *init)
return VariableDecorator(cast<DefInit>(init)->getDef());
}
-auto Operator::getArgToOperandOrAttribute(int index) const
- -> OperandOrAttribute {
- return attrOrOperandMapping[index];
+auto Operator::getArgToOperandAttrOrProp(int index) const -> OperandAttrOrProp {
+ return attrPropOrOperandMapping[index];
}
std::string Operator::getGetterName(StringRef name) const {
diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td
index f213f50ae2f39..87b41f9dea995 100644
--- a/mlir/test/mlir-tblgen/op-decl-and-defs.td
+++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td
@@ -543,3 +543,12 @@ def _BOp : NS_Op<"_op_with_leading_underscore_and_no_namespace", []>;
// REDUCE_EXC-NOT: NS::AOp declarations
// REDUCE_EXC-LABEL: NS::BOp declarations
+
+// CHECK-LABEL: _TypeInferredPropOp declarations
+def _TypeInferredPropOp : NS_Op<"type_inferred_prop_op_with_properties", [
+ AllTypesMatch<["value", "result"]>
+ ]> {
+ let arguments = (ins Property<"unsigned">:$prop, AnyType:$value);
+ let results = (outs AnyType:$result);
+ let hasCustomAssemblyFormat = 1;
+}
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 8ea4eb7b3eeca..270522380eb59 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -3849,9 +3849,9 @@ void OpEmitter::genTypeInterfaceMethods() {
const InferredResultType &infer = op.getInferredResultType(i);
if (!infer.isArg())
continue;
- Operator::OperandOrAttribute arg =
- op.getArgToOperandOrAttribute(infer.getIndex());
- if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand) {
+ Operator::OperandAttrOrProp arg =
+ op.getArgToOperandAttrOrProp(infer.getIndex());
+ if (arg.kind() == Operator::OperandAttrOrProp::Kind::Operand) {
maxAccessedIndex =
std::max(maxAccessedIndex, arg.operandOrAttributeIndex());
}
@@ -3877,17 +3877,16 @@ void OpEmitter::genTypeInterfaceMethods() {
if (infer.isArg()) {
// If this is an operand, just index into operand list to access the
// type.
- Operator::OperandOrAttribute arg =
- op.getArgToOperandOrAttribute(infer.getIndex());
- if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand) {
+ Operator::OperandAttrOrProp arg =
+ op.getArgToOperandAttrOrProp(infer.getIndex());
+ if (arg.kind() == Operator::OperandAttrOrProp::Kind::Operand) {
typeStr = ("operands[" + Twine(arg.operandOrAttributeIndex()) +
"].getType()")
.str();
// If this is an attribute, index into the attribute dictionary.
- } else {
- auto *attr =
- cast<NamedAttribute *>(op.getArg(arg.operandOrAttributeIndex()));
+ } else if (auto *attr = dyn_cast<NamedAttribute *>(
+ op.getArg(arg.operandOrAttributeIndex()))) {
body << " ::mlir::TypedAttr odsInferredTypeAttr" << inferredTypeIdx
<< " = ";
if (op.getDialect().usePropertiesForAttributes()) {
@@ -3907,6 +3906,8 @@ void OpEmitter::genTypeInterfaceMethods() {
typeStr =
("odsInferredTypeAttr" + Twine(inferredTypeIdx) + ".getType()")
.str();
+ } else {
+ llvm_unreachable("Properties cannot be used for type inference");
}
} else if (std::optional<StringRef> builder =
op.getResult(infer.getResultIndex())
|
@llvm/pr-subscribers-mlir-core Author: Fabian Mora (fabianmcg) ChangesThis patch fixes a bug occurring when properties are mixed with any of the InferType traits, causing tblgen to crash. A simple reproducer is:
The issue occurs because of the call:
To understand better the issue, consider:
In this case, The fix is to change Full diff: https://github.com/llvm/llvm-project/pull/157367.diff 4 Files Affected:
diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h
index 9e570373d9cd3..f0514d8e61748 100644
--- a/mlir/include/mlir/TableGen/Operator.h
+++ b/mlir/include/mlir/TableGen/Operator.h
@@ -323,21 +323,22 @@ class Operator {
/// Requires: all result types are known.
const InferredResultType &getInferredResultType(int index) const;
- /// Pair consisting kind of argument and index into operands or attributes.
- struct OperandOrAttribute {
- enum class Kind { Operand, Attribute };
- OperandOrAttribute(Kind kind, int index) {
- packed = (index << 1) | (kind == Kind::Attribute);
+ /// Pair consisting kind of argument and index into operands, attributes, or
+ /// properties.
+ struct OperandAttrOrProp {
+ enum class Kind { Operand = 0x0, Attribute = 0x1, Property = 0x2 };
+ OperandAttrOrProp(Kind kind, int index) {
+ packed = (index << 2) | static_cast<int>(kind);
}
- int operandOrAttributeIndex() const { return (packed >> 1); }
- Kind kind() { return (packed & 0x1) ? Kind::Attribute : Kind::Operand; }
+ int operandOrAttributeIndex() const { return (packed >> 2); }
+ Kind kind() const { return static_cast<Kind>(packed & 0x3); }
private:
int packed;
};
- /// Returns the OperandOrAttribute corresponding to the index.
- OperandOrAttribute getArgToOperandOrAttribute(int index) const;
+ /// Returns the OperandAttrOrProp corresponding to the index.
+ OperandAttrOrProp getArgToOperandAttrOrProp(int index) const;
/// Returns the builders of this operation.
ArrayRef<Builder> getBuilders() const { return builders; }
@@ -405,8 +406,8 @@ class Operator {
/// The argument with the same type as the result.
SmallVector<InferredResultType> resultTypeMapping;
- /// Map from argument to attribute or operand number.
- SmallVector<OperandOrAttribute, 4> attrOrOperandMapping;
+ /// Map from argument to attribute, property, or operand number.
+ SmallVector<OperandAttrOrProp, 4> attrPropOrOperandMapping;
/// The builders of this operator.
SmallVector<Builder> builders;
diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp
index da86b00ebc300..926ffd0e363a0 100644
--- a/mlir/lib/TableGen/Operator.cpp
+++ b/mlir/lib/TableGen/Operator.cpp
@@ -385,7 +385,8 @@ void Operator::populateTypeInferenceInfo(
if (getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
// Check for a non-variable length operand to use as the type anchor.
auto *operandI = llvm::find_if(arguments, [](const Argument &arg) {
- NamedTypeConstraint *operand = llvm::dyn_cast_if_present<NamedTypeConstraint *>(arg);
+ NamedTypeConstraint *operand =
+ llvm::dyn_cast_if_present<NamedTypeConstraint *>(arg);
return operand && !operand->isVariableLength();
});
if (operandI == arguments.end())
@@ -663,15 +664,17 @@ void Operator::populateOpStructure() {
argDef = argDef->getValueAsDef("constraint");
if (argDef->isSubClassOf(typeConstraintClass)) {
- attrOrOperandMapping.push_back(
- {OperandOrAttribute::Kind::Operand, operandIndex});
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Operand, operandIndex});
arguments.emplace_back(&operands[operandIndex++]);
} else if (argDef->isSubClassOf(attrClass)) {
- attrOrOperandMapping.push_back(
- {OperandOrAttribute::Kind::Attribute, attrIndex});
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Attribute, attrIndex});
arguments.emplace_back(&attributes[attrIndex++]);
} else {
assert(argDef->isSubClassOf(propertyClass));
+ attrPropOrOperandMapping.push_back(
+ {OperandAttrOrProp::Kind::Property, propIndex});
arguments.emplace_back(&properties[propIndex++]);
}
}
@@ -867,9 +870,8 @@ auto Operator::VariableDecoratorIterator::unwrap(const Init *init)
return VariableDecorator(cast<DefInit>(init)->getDef());
}
-auto Operator::getArgToOperandOrAttribute(int index) const
- -> OperandOrAttribute {
- return attrOrOperandMapping[index];
+auto Operator::getArgToOperandAttrOrProp(int index) const -> OperandAttrOrProp {
+ return attrPropOrOperandMapping[index];
}
std::string Operator::getGetterName(StringRef name) const {
diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td
index f213f50ae2f39..87b41f9dea995 100644
--- a/mlir/test/mlir-tblgen/op-decl-and-defs.td
+++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td
@@ -543,3 +543,12 @@ def _BOp : NS_Op<"_op_with_leading_underscore_and_no_namespace", []>;
// REDUCE_EXC-NOT: NS::AOp declarations
// REDUCE_EXC-LABEL: NS::BOp declarations
+
+// CHECK-LABEL: _TypeInferredPropOp declarations
+def _TypeInferredPropOp : NS_Op<"type_inferred_prop_op_with_properties", [
+ AllTypesMatch<["value", "result"]>
+ ]> {
+ let arguments = (ins Property<"unsigned">:$prop, AnyType:$value);
+ let results = (outs AnyType:$result);
+ let hasCustomAssemblyFormat = 1;
+}
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 8ea4eb7b3eeca..270522380eb59 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -3849,9 +3849,9 @@ void OpEmitter::genTypeInterfaceMethods() {
const InferredResultType &infer = op.getInferredResultType(i);
if (!infer.isArg())
continue;
- Operator::OperandOrAttribute arg =
- op.getArgToOperandOrAttribute(infer.getIndex());
- if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand) {
+ Operator::OperandAttrOrProp arg =
+ op.getArgToOperandAttrOrProp(infer.getIndex());
+ if (arg.kind() == Operator::OperandAttrOrProp::Kind::Operand) {
maxAccessedIndex =
std::max(maxAccessedIndex, arg.operandOrAttributeIndex());
}
@@ -3877,17 +3877,16 @@ void OpEmitter::genTypeInterfaceMethods() {
if (infer.isArg()) {
// If this is an operand, just index into operand list to access the
// type.
- Operator::OperandOrAttribute arg =
- op.getArgToOperandOrAttribute(infer.getIndex());
- if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand) {
+ Operator::OperandAttrOrProp arg =
+ op.getArgToOperandAttrOrProp(infer.getIndex());
+ if (arg.kind() == Operator::OperandAttrOrProp::Kind::Operand) {
typeStr = ("operands[" + Twine(arg.operandOrAttributeIndex()) +
"].getType()")
.str();
// If this is an attribute, index into the attribute dictionary.
- } else {
- auto *attr =
- cast<NamedAttribute *>(op.getArg(arg.operandOrAttributeIndex()));
+ } else if (auto *attr = dyn_cast<NamedAttribute *>(
+ op.getArg(arg.operandOrAttributeIndex()))) {
body << " ::mlir::TypedAttr odsInferredTypeAttr" << inferredTypeIdx
<< " = ";
if (op.getDialect().usePropertiesForAttributes()) {
@@ -3907,6 +3906,8 @@ void OpEmitter::genTypeInterfaceMethods() {
typeStr =
("odsInferredTypeAttr" + Twine(inferredTypeIdx) + ".getType()")
.str();
+ } else {
+ llvm_unreachable("Properties cannot be used for type inference");
}
} else if (std::optional<StringRef> builder =
op.getResult(infer.getResultIndex())
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a crash in mlir-tblgen when mixing properties with InferType traits. The issue occurred because the argument-to-operand/attribute mapping didn't account for properties, causing index mismatches during type inference.
Key changes:
- Expand the argument mapping to include properties alongside operands and attributes
- Update the enum and data structures to handle three kinds of arguments instead of two
- Add proper error handling for unsupported property-based type inference
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
File | Description |
---|---|
mlir/include/mlir/TableGen/Operator.h | Updates data structures and enums to support properties in argument mapping |
mlir/lib/TableGen/Operator.cpp | Implements the expanded mapping logic and updates method signatures |
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | Updates type inference code to use new mapping and adds error handling |
mlir/test/mlir-tblgen/op-decl-and-defs.td | Adds test case for the previously crashing scenario |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look good to me overall! Just one comment regarding error handling
This patch fixes a bug occurring when properties are mixed with any of the InferType traits, causing tblgen to crash. A simple reproducer is:
The issue occurs because of the call:
To understand better the issue, consider:
In this case,
infer.getIndex()
will return1
forOperand0
, butgetArgToOperandOrAttribute
expects0
, causing the discrepancy that causes the crash.The fix is to change
attrOrOperandMapping
to also include props.