diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -1796,6 +1796,13 @@ // TODO: Remove this class in favor of using Trait. class OpTrait; +// Define a nested OpTrait, this allows for specifying a list of traits as as +// trait. Avoids needing to do `[Traits, ...] # ListOfTraits # [Others, ...]` +// while still allowing providing convenient groupings. +class NestedOpTraits props> : OpTrait { + list traits = props; +} + // These classes are used to define operation specific traits. class NativeOpTrait : NativeTrait, OpTrait; class ParamNativeOpTrait diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp --- a/mlir/lib/TableGen/Operator.cpp +++ b/mlir/lib/TableGen/Operator.cpp @@ -489,11 +489,21 @@ // This is uniquing based on pointers of the trait. SmallPtrSet traitSet; traits.reserve(traitSet.size()); - for (auto *traitInit : *traitList) { - // Keep traits in the same order while skipping over duplicates. - if (traitSet.insert(traitInit).second) - traits.push_back(Trait::create(traitInit)); - } + + std::function insert; + insert = [&](llvm::ListInit *traitList) { + for (auto *traitInit : *traitList) { + auto *def = cast(traitInit)->getDef(); + if (def->isSubClassOf("NestedOpTraits")) { + insert(def->getValueAsListInit("traits")); + continue; + } + // Keep traits in the same order while skipping over duplicates. + if (traitSet.insert(traitInit).second) + traits.push_back(Trait::create(traitInit)); + } + }; + insert(traitList); } populateTypeInferenceInfo(argumentsAndResultsIndex); diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td --- a/mlir/test/mlir-tblgen/op-decl-and-defs.td +++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td @@ -261,6 +261,16 @@ // CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); // CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); +// IsolatedFromAbove trait is included multipe times to ensure it gets uniqued +// during emission. +def NS_KOp : NS_Op<"k_op", [IsolatedFromAbove, + NestedOpTraits<[DeclareOpInterfaceMethods]>]> { + let arguments = (ins AnyType:$a, AnyType:$b); +} + +// CHECK: class KOp : public ::mlir::Op