diff --git a/mlir/include/mlir/Dialect/DLTI/DLTI.h b/mlir/include/mlir/Dialect/DLTI/DLTI.h index 6e2623e084be52..a97eb523cb0631 100644 --- a/mlir/include/mlir/Dialect/DLTI/DLTI.h +++ b/mlir/include/mlir/Dialect/DLTI/DLTI.h @@ -24,15 +24,10 @@ class DataLayoutEntryAttrStorage; } // namespace mlir namespace mlir { namespace dlti { -/// Find the first DataLayoutSpec associated to `op`, via either the -/// DataLayoutOpInterface, a method on ModuleOp, or an attribute implementing -/// the interface, on `op` and else on `op`'s ancestors in turn. -DataLayoutSpecInterface getDataLayoutSpec(Operation *op); - -/// Find the first TargetSystemSpec associated to `op`, via either the -/// DataLayoutOpInterface, a method on ModuleOp, or an attribute implementing -/// the interface, on `op` and else on `op`'s ancestors in turn. -TargetSystemSpecInterface getTargetSystemSpec(Operation *op); +/// Perform a DLTI-query at `op`, recursively querying each key of `keys` on +/// query interface-implementing attrs, starting from attr obtained from `op`. +FailureOr query(Operation *op, ArrayRef keys, + bool emitError = false); } // namespace dlti } // namespace mlir diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td index 443e3128b4acb3..53d38407608bed 100644 --- a/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td +++ b/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td @@ -10,6 +10,7 @@ #define MLIR_DIALECT_DLTI_DLTIATTRS_TD include "mlir/Dialect/DLTI/DLTI.td" +include "mlir/Interfaces/DataLayoutInterfaces.td" include "mlir/IR/AttrTypeBase.td" class DLTIAttr traits = [], @@ -20,13 +21,8 @@ class DLTIAttr traits = [], // DataLayoutEntryAttr //===----------------------------------------------------------------------===// -def DataLayoutEntryTrait - : NativeAttrTrait<"DataLayoutEntryInterface::Trait"> { - let cppNamespace = "::mlir"; -} - def DLTI_DataLayoutEntryAttr : - DLTIAttr<"DataLayoutEntry", [DataLayoutEntryTrait]> { + DLTIAttr<"DataLayoutEntry", [DataLayoutEntryInterface]> { let summary = "An attribute to represent an entry of a data layout specification."; let description = [{ A data layout entry attribute is a key-value pair where the key is a type or @@ -53,13 +49,9 @@ def DLTI_DataLayoutEntryAttr : //===----------------------------------------------------------------------===// // DataLayoutSpecAttr //===----------------------------------------------------------------------===// -def DataLayoutSpecTrait - : NativeAttrTrait<"DataLayoutSpecInterface::Trait"> { - let cppNamespace = "::mlir"; -} def DLTI_DataLayoutSpecAttr : - DLTIAttr<"DataLayoutSpec", [DataLayoutSpecTrait]> { + DLTIAttr<"DataLayoutSpec", [DataLayoutSpecInterface]> { let summary = "An attribute to represent a data layout specification."; let description = [{ A data layout specification is a list of entries that specify (partial) data @@ -78,7 +70,7 @@ def DLTI_DataLayoutSpecAttr : /// same key as the newer entries if the entries are compatible. Returns null /// if the specifications are not compatible. DataLayoutSpecAttr combineWith(ArrayRef specs) const; - + /// Returns the endiannes identifier. StringAttr getEndiannessIdentifier(MLIRContext *context) const; @@ -93,6 +85,69 @@ def DLTI_DataLayoutSpecAttr : /// Returns the stack alignment identifier. StringAttr getStackAlignmentIdentifier(MLIRContext *context) const; + + /// Returns the attribute associated with the key. + FailureOr query(DataLayoutEntryKey key) { + return llvm::cast(*this).queryHelper(key); + } + }]; +} + +def DLTI_MapAttr : DLTIAttr<"Map", [DLTIQueryInterface]> { + let summary = "A mapping of DLTI-information by way of key-value pairs"; + let description = [{ + A Data Layout and Target Information map is a list of entries effectively + encoding a dictionary, mapping DLTI-related keys to DLTI-related values. + + This attribute's main purpose is to facilate querying IR for arbitrary + key-value associations that encode DLTI. Facility functions exist to perform + recursive lookups on nested DLTI-map/query interface-implementing + attributes. + + Consider the following flat encoding of a single-key dictionary + ``` + #dlti.map<#dlti.dl_entry<"CPU::cache::L1::size_in_bytes", 65536 : i32>> + ``` + versus nested maps, which make it possible to obtain sub-dictionaries of + related information (with the following example making use of other + attributes that also implement the `DLTIQueryInterface`): + ``` + #dlti.target_system_spec<"CPU": + #dlti.target_device_spec<#dlti.dl_entry<"cache", + #dlti.map<#dlti.dl_entry<"L1", + #dlti.map<#dlti.dl_entry<"size_in_bytes", 65536 : i32>>>, + #dlti.dl_entry<"L1d", + #dlti.map<#dlti.dl_entry<"size_in_bytes", 32768 : i32>>> >>>> + ``` + + With the flat encoding, the implied structure of the key is ignored, that is + the only successful query (as expressed in the Transform Dialect) is: + `transform.dlti.query ["CPU::cache::L1::size_in_bytes"] at %op`, + where `%op` is a handle to an operation which associates the flat-encoding + `#dlti.map` attribute. + + For querying nested dictionaries, the relevant keys need to be separately + provided. That is, if `%op` is an handle to an op which has the nesting + `#dlti.target_system_spec`-attribute from above attached, then + `transform.dlti.query ["CPU","cache","L1","size_in_bytes"] at %op` gives + back the first leaf value contained. To access the other leaf, we need to do + `transform.dlti.query ["CPU","cache","L1d","size_in_bytes"] at %op`. + ``` + }]; + let parameters = (ins + ArrayRefParameter<"DataLayoutEntryInterface", "">:$entries + ); + let mnemonic = "map"; + let genVerifyDecl = 1; + let assemblyFormat = "`<` $entries `>`"; + let extraClassDeclaration = [{ + /// Returns the attribute associated with the key. + FailureOr query(DataLayoutEntryKey key) { + for (DataLayoutEntryInterface entry : getEntries()) + if (entry.getKey() == key) + return entry.getValue(); + return ::mlir::failure(); + } }]; } @@ -100,13 +155,8 @@ def DLTI_DataLayoutSpecAttr : // TargetSystemSpecAttr //===----------------------------------------------------------------------===// -def TargetSystemSpecTrait - : NativeAttrTrait<"TargetSystemSpecInterface::Trait"> { - let cppNamespace = "::mlir"; -} - def DLTI_TargetSystemSpecAttr : - DLTIAttr<"TargetSystemSpec", [TargetSystemSpecTrait]> { + DLTIAttr<"TargetSystemSpec", [TargetSystemSpecInterface]> { let summary = "An attribute to represent target system specification."; let description = [{ A system specification describes the overall system containing @@ -136,6 +186,11 @@ def DLTI_TargetSystemSpecAttr : std::optional getDeviceSpecForDeviceID( TargetSystemSpecInterface::DeviceID deviceID); + + /// Returns the attribute associated with the key. + FailureOr query(DataLayoutEntryKey key) const { + return llvm::cast(*this).queryHelper(key); + } }]; let extraClassDefinition = [{ std::optional @@ -154,13 +209,8 @@ def DLTI_TargetSystemSpecAttr : // TargetDeviceSpecAttr //===----------------------------------------------------------------------===// -def TargetDeviceSpecTrait - : NativeAttrTrait<"TargetDeviceSpecInterface::Trait"> { - let cppNamespace = "::mlir"; -} - def DLTI_TargetDeviceSpecAttr : - DLTIAttr<"TargetDeviceSpec", [TargetDeviceSpecTrait]> { + DLTIAttr<"TargetDeviceSpec", [TargetDeviceSpecInterface]> { let summary = "An attribute to represent target device specification."; let description = [{ Each device specification describes a single device and its @@ -179,6 +229,13 @@ def DLTI_TargetDeviceSpecAttr : let mnemonic = "target_device_spec"; let genVerifyDecl = 1; let assemblyFormat = "`<` $entries `>`"; + + let extraClassDeclaration = [{ + /// Returns the attribute associated with the key. + FailureOr query(DataLayoutEntryKey key) const { + return llvm::cast(*this).queryHelper(key); + } + }]; } #endif // MLIR_DIALECT_DLTI_DLTIATTRS_TD diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td index e26fbdb146645c..f84149c43e0fcd 100644 --- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td +++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td @@ -23,14 +23,19 @@ def DLTI_Dialect : Dialect { }]; let extraClassDeclaration = [{ - // Top level attribute name. + // Top-level attribute name for arbitrary description. + constexpr const static ::llvm::StringLiteral + kMapAttrName = "dlti.map"; + + // Top-level attribute name for data layout description. constexpr const static ::llvm::StringLiteral kDataLayoutAttrName = "dlti.dl_spec"; - // Top level attribute name for target system description + // Top-level attribute name for target system description. constexpr const static ::llvm::StringLiteral kTargetSystemDescAttrName = "dlti.target_system_spec"; + // Top-level attribute name for target device description. constexpr const static ::llvm::StringLiteral kTargetDeviceDescAttrName = "dlti.target_device_spec"; diff --git a/mlir/include/mlir/Dialect/DLTI/TransformOps/DLTITransformOps.td b/mlir/include/mlir/Dialect/DLTI/TransformOps/DLTITransformOps.td index 69aacac986ad73..1b1bebfaab4e38 100644 --- a/mlir/include/mlir/Dialect/DLTI/TransformOps/DLTITransformOps.td +++ b/mlir/include/mlir/Dialect/DLTI/TransformOps/DLTITransformOps.td @@ -22,32 +22,40 @@ def QueryOp : Op>>} { + func.func private @f() + } + ``` + and we have that `%func` is a Tranform handle to op `@f`, then + `transform.dlti.query ["A", "B"] at %func` returns 42 as a param and + `transform.dlti.query ["A"] at %func` returns the `#dlti.map` attribute + containing just the key "B" and its value. Using `["B"]` or `["A","C"]` as + `keys` will yield an error. #### Return modes - When succesful, the result, `associated_attr`, associates one attribute as a - param for each op in `target`'s payload. + When successful, the result, `associated_attr`, associates one attribute as + a param for each op in `target`'s payload. - If the lookup fails - as DLTI specifications or entries with the right - names are missing (i.e. the values of `device` and `key`) - a definite - failure is returned. + If the lookup fails - as no DLTI attributes/interfaces are found or entries + with the right names are missing - a silenceable failure is returned. }]; let arguments = (ins TransformHandleTypeInterface:$target, - OptionalAttr:$device, - StrAttr:$key); + StrArrayAttr:$keys); let results = (outs TransformParamTypeInterface:$associated_attr); let assemblyFormat = - "(`:``:` $device^ `:``:`)? $key `at` $target attr-dict `:`" - "functional-type(operands, results)"; + "$keys `at` $target attr-dict `:` functional-type(operands, results)"; let extraClassDeclaration = [{ ::mlir::DiagnosedSilenceableFailure applyToOne( diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h index ab65f92820a6a8..848d2dee4a6309 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h @@ -23,6 +23,7 @@ namespace mlir { class DataLayout; class DataLayoutEntryInterface; +class DLTIQueryInterface; class TargetDeviceSpecInterface; class TargetSystemSpecInterface; using DataLayoutEntryKey = llvm::PointerUnion; diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td index bc5080c9c6a558..d6e955be4291a3 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td @@ -20,6 +20,29 @@ include "mlir/IR/OpBase.td" // Attribute interfaces //===----------------------------------------------------------------------===// +def DLTIQueryInterface : AttrInterface<"DLTIQueryInterface"> { + let cppNamespace = "::mlir"; + + let description = [{ + Attribute interface exposing querying-mechanism for key-value associations. + + The central feature of DLTI attributes is to allow looking up values at + keys. This interface represent the core functionality to do so - as such + most DLTI attributes should be implementing this interface. + + Note that as the `query` method returns an attribute, this attribute can + be recursively queried when it also implements this interface. + }]; + let methods = [ + InterfaceMethod< + /*description=*/"Returns the attribute associated with the key.", + /*retTy=*/"::mlir::FailureOr<::mlir::Attribute>", + /*methodName=*/"query", + /*args=*/(ins "::mlir::DataLayoutEntryKey":$key) + > + ]; +} + def DataLayoutEntryInterface : AttrInterface<"DataLayoutEntryInterface"> { let cppNamespace = "::mlir"; @@ -68,7 +91,7 @@ def DataLayoutEntryInterface : AttrInterface<"DataLayoutEntryInterface"> { }]; } -def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> { +def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface", [DLTIQueryInterface]> { let cppNamespace = "::mlir"; let description = [{ @@ -173,7 +196,7 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> { /*defaultImplementation=*/[{ return ::mlir::detail::verifyDataLayoutSpec($_attr, loc); }] - >, + > ]; let extraClassDeclaration = [{ @@ -184,6 +207,15 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> { return getSpecForType(TypeID::get()); } + /// Helper for default implementation of `DLTIQueryInterface`'s `query`. + inline ::mlir::FailureOr<::mlir::Attribute> + queryHelper(::mlir::DataLayoutEntryKey key) const { + for (DataLayoutEntryInterface entry : getEntries()) + if (entry.getKey() == key) + return entry.getValue(); + return ::mlir::failure(); + } + /// Populates the given maps with lists of entries grouped by the type or /// identifier they are associated with. Users are not expected to call this /// method directly. @@ -194,7 +226,7 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> { }]; } -def TargetDeviceSpecInterface : AttrInterface<"TargetDeviceSpecInterface"> { +def TargetDeviceSpecInterface : AttrInterface<"TargetDeviceSpecInterface", [DLTIQueryInterface]> { let cppNamespace = "::mlir"; let description = [{ @@ -239,9 +271,20 @@ def TargetDeviceSpecInterface : AttrInterface<"TargetDeviceSpecInterface"> { /*defaultImplementation=*/[{ return ::mlir::success(); }] > ]; + + let extraClassDeclaration = [{ + /// Helper for default implementation of `DLTIQueryInterface`'s `query`. + ::mlir::FailureOr<::mlir::Attribute> + queryHelper(::mlir::DataLayoutEntryKey key) const { + if (auto strKey = llvm::dyn_cast(key)) + if (DataLayoutEntryInterface spec = getSpecForIdentifier(strKey)) + return spec.getValue(); + return ::mlir::failure(); + } + }]; } -def TargetSystemSpecInterface : AttrInterface<"TargetSystemSpecInterface"> { +def TargetSystemSpecInterface : AttrInterface<"TargetSystemSpecInterface", [DLTIQueryInterface]> { let cppNamespace = "::mlir"; let description = [{ @@ -287,6 +330,15 @@ def TargetSystemSpecInterface : AttrInterface<"TargetSystemSpecInterface"> { let extraClassDeclaration = [{ using DeviceID = StringAttr; + + /// Helper for default implementation of `DLTIQueryInterface`'s `query`. + ::mlir::FailureOr<::mlir::Attribute> + queryHelper(::mlir::DataLayoutEntryKey key) const { + if (auto strKey = llvm::dyn_cast<::mlir::StringAttr>(key)) + if (auto deviceSpec = getDeviceSpecForDeviceID(strKey)) + return *deviceSpec; + return ::mlir::failure(); + } }]; } diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp index c995f44c380e57..7f8e11a1b73341 100644 --- a/mlir/lib/Dialect/DLTI/DLTI.cpp +++ b/mlir/lib/Dialect/DLTI/DLTI.cpp @@ -109,12 +109,11 @@ void DataLayoutEntryAttr::print(AsmPrinter &os) const { } //===----------------------------------------------------------------------===// -// DataLayoutSpecAttr +// DLTIMapAttr //===----------------------------------------------------------------------===// -LogicalResult -DataLayoutSpecAttr::verify(function_ref emitError, - ArrayRef entries) { +static LogicalResult verifyEntries(function_ref emitError, + ArrayRef entries) { DenseSet types; DenseSet ids; for (DataLayoutEntryInterface entry : entries) { @@ -130,6 +129,21 @@ DataLayoutSpecAttr::verify(function_ref emitError, return success(); } +LogicalResult MapAttr::verify(function_ref emitError, + ArrayRef entries) { + return verifyEntries(emitError, entries); +} + +//===----------------------------------------------------------------------===// +// DataLayoutSpecAttr +//===----------------------------------------------------------------------===// + +LogicalResult +DataLayoutSpecAttr::verify(function_ref emitError, + ArrayRef entries) { + return verifyEntries(emitError, entries); +} + /// Given a list of old and a list of new entries, overwrites old entries with /// new ones if they have matching keys, appends new entries to the old entry /// list otherwise. @@ -393,39 +407,62 @@ TargetSystemSpecAttr::verify(function_ref emitError, // DLTIDialect //===----------------------------------------------------------------------===// -DataLayoutSpecInterface dlti::getDataLayoutSpec(Operation *op) { - DataLayoutSpecInterface dlSpec = nullptr; - - for (Operation *cur = op; cur && !dlSpec; cur = cur->getParentOp()) { - if (auto dataLayoutOp = dyn_cast(cur)) - dlSpec = dataLayoutOp.getDataLayoutSpec(); - else if (auto moduleOp = dyn_cast(cur)) - dlSpec = moduleOp.getDataLayoutSpec(); - else - for (NamedAttribute attr : cur->getAttrs()) - if ((dlSpec = llvm::dyn_cast(attr.getValue()))) - break; - } +/// Retrieve the first `DLTIQueryInterface`-implementing attribute that is +/// attached to `op` or such an attr on as close as possible an ancestor. The +/// op the attribute is attached to is returned as well. +static std::pair +getClosestQueryable(Operation *op) { + DLTIQueryInterface queryable = {}; + + // Search op and its ancestors for the first attached DLTIQueryInterface attr. + do { + for (NamedAttribute attr : op->getAttrs()) + if ((queryable = llvm::dyn_cast(attr.getValue()))) + break; + } while (!queryable && (op = op->getParentOp())); - return dlSpec; + return std::pair(queryable, op); } -TargetSystemSpecInterface dlti::getTargetSystemSpec(Operation *op) { - TargetSystemSpecInterface sysSpec = nullptr; - - for (Operation *cur = op; cur && !sysSpec; cur = cur->getParentOp()) { - if (auto dataLayoutOp = dyn_cast(cur)) - sysSpec = dataLayoutOp.getTargetSystemSpec(); - else if (auto moduleOp = dyn_cast(cur)) - sysSpec = moduleOp.getTargetSystemSpec(); - else - for (NamedAttribute attr : cur->getAttrs()) - if ((sysSpec = - llvm::dyn_cast(attr.getValue()))) - break; +FailureOr dlti::query(Operation *op, ArrayRef keys, + bool emitError) { + auto [queryable, queryOp] = getClosestQueryable(op); + Operation *reportOp = (queryOp ? queryOp : op); + + if (!queryable) { + if (emitError) { + auto diag = op->emitError() << "target op of failed DLTI query"; + diag.attachNote(reportOp->getLoc()) + << "no DLTI-queryable attrs on target op or any of its ancestors"; + } + return failure(); + } + + Attribute currentAttr = queryable; + for (auto &&[idx, key] : llvm::enumerate(keys)) { + if (auto map = llvm::dyn_cast(currentAttr)) { + auto maybeAttr = map.query(key); + if (failed(maybeAttr)) { + if (emitError) { + auto diag = op->emitError() << "target op of failed DLTI query"; + diag.attachNote(reportOp->getLoc()) + << "key " << key << " has no DLTI-mapping per attr: " << map; + } + return failure(); + } + currentAttr = *maybeAttr; + } else { + if (emitError) { + auto diag = op->emitError() << "target op of failed DLTI query"; + diag.attachNote(reportOp->getLoc()) + << "got non-DLTI-queryable attribute upon looking up keys [" + << keys.take_front(idx) << "] at op"; + } + return failure(); + } } - return sysSpec; + return currentAttr; } constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutAttrName; @@ -480,7 +517,9 @@ LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op, if (isa(op)) return detail::verifyDataLayoutOp(op); return success(); - } else if (attr.getName() == DLTIDialect::kTargetSystemDescAttrName) { + } + + if (attr.getName() == DLTIDialect::kTargetSystemDescAttrName) { if (!llvm::isa(attr.getValue())) { return op->emitError() << "'" << DLTIDialect::kTargetSystemDescAttrName @@ -489,6 +528,14 @@ LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op, return success(); } + if (attr.getName() == DLTIDialect::kMapAttrName) { + if (!llvm::isa(attr.getValue())) { + return op->emitError() << "'" << DLTIDialect::kMapAttrName + << "' is expected to be a #dlti.map attribute"; + } + return success(); + } + return op->emitError() << "attribute '" << attr.getName().getValue() << "' not supported by dialect"; } diff --git a/mlir/lib/Dialect/DLTI/TransformOps/DLTITransformOps.cpp b/mlir/lib/Dialect/DLTI/TransformOps/DLTITransformOps.cpp index 032228b2f05ca2..90aef82bddff00 100644 --- a/mlir/lib/Dialect/DLTI/TransformOps/DLTITransformOps.cpp +++ b/mlir/lib/Dialect/DLTI/TransformOps/DLTITransformOps.cpp @@ -33,36 +33,15 @@ void transform::QueryOp::getEffects( DiagnosedSilenceableFailure transform::QueryOp::applyToOne( transform::TransformRewriter &rewriter, Operation *target, transform::ApplyToEachResultList &results, TransformState &state) { - StringAttr deviceId = getDeviceAttr(); - StringAttr key = getKeyAttr(); - - DataLayoutEntryInterface entry; - if (deviceId) { - TargetSystemSpecInterface sysSpec = dlti::getTargetSystemSpec(target); - if (!sysSpec) - return mlir::emitDefiniteFailure(target->getLoc()) - << "no target system spec associated to: " << target; - - if (auto targetSpec = sysSpec.getDeviceSpecForDeviceID(deviceId)) - entry = targetSpec->getSpecForIdentifier(key); - else - return mlir::emitDefiniteFailure(target->getLoc()) - << "no " << deviceId << " target device spec found"; - } else { - DataLayoutSpecInterface dlSpec = dlti::getDataLayoutSpec(target); - if (!dlSpec) - return mlir::emitDefiniteFailure(target->getLoc()) - << "no data layout spec associated to: " << target; - - entry = dlSpec.getSpecForIdentifier(key); - } + auto keys = SmallVector(getKeys().getAsRange()); - if (!entry) - return mlir::emitDefiniteFailure(target->getLoc()) - << "no DLTI entry for key: " << key; + FailureOr result = dlti::query(target, keys, /*emitError=*/true); - results.push_back(entry.getValue()); + if (failed(result)) + return emitSilenceableFailure(getLoc(), + "'transform.dlti.query' op failed to apply"); + results.push_back(*result); return DiagnosedSilenceableFailure::success(); } diff --git a/mlir/test/Dialect/DLTI/invalid.mlir b/mlir/test/Dialect/DLTI/invalid.mlir index 36bf6088fab7e9..05f919fa256713 100644 --- a/mlir/test/Dialect/DLTI/invalid.mlir +++ b/mlir/test/Dialect/DLTI/invalid.mlir @@ -5,6 +5,11 @@ // ----- +// expected-error@below {{'dlti.map' is expected to be a #dlti.map attribute}} +"test.unknown_op"() { dlti.map = 42 } : () -> () + +// ----- + // expected-error@below {{'dlti.dl_spec' is expected to be a #dlti.dl_spec attribute}} "test.unknown_op"() { dlti.dl_spec = 42 } : () -> () diff --git a/mlir/test/Dialect/DLTI/query.mlir b/mlir/test/Dialect/DLTI/query.mlir index 2504958de09289..10e91afd2ca7e1 100644 --- a/mlir/test/Dialect/DLTI/query.mlir +++ b/mlir/test/Dialect/DLTI/query.mlir @@ -1,15 +1,32 @@ // RUN: mlir-opt -transform-interpreter -canonicalize -split-input-file -verify-diagnostics %s | FileCheck %s +// expected-remark @below {{associated attr 42 : i32}} +module attributes { test.dlti = #dlti.map<#dlti.dl_entry<"test.id", 42 : i32>>} { + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op + %param = transform.dlti.query ["test.id"] at %module : (!transform.any_op) -> !transform.any_param + transform.debug.emit_param_as_remark %param, "associated attr" at %module : !transform.any_param, !transform.any_op + transform.yield + } +} + +// ----- + // expected-remark @below {{associated attr 42 : i32}} module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"test.id", 42 : i32>>} { - func.func private @f() + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %module : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["test.id"] at %module : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %module : !transform.any_param, !transform.any_op transform.yield } @@ -25,7 +42,7 @@ module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"test.id", 42 : i32 module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %funcs : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["test.id"] at %funcs : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %funcs : !transform.any_param, !transform.any_op transform.yield } @@ -42,7 +59,7 @@ module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %module : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["test.id"] at %module : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %module : !transform.any_param, !transform.any_op transform.yield } @@ -65,7 +82,7 @@ module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"test.id", 42 : i32 module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %matmul = transform.structured.match ops{["linalg.matmul"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %matmul : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["test.id"] at %matmul : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %matmul : !transform.any_param, !transform.any_op transform.yield } @@ -88,7 +105,7 @@ module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"test.id", 42 : i32 module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %matmul = transform.structured.match ops{["linalg.matmul"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %matmul : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["test.id"] at %matmul : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %matmul : !transform.any_param, !transform.any_op transform.yield } @@ -97,7 +114,9 @@ module attributes {transform.with_named_sequence} { // ----- // expected-remark @below {{associated attr 42 : i32}} -module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>>} { +module attributes { test.dlti = + #dlti.target_system_spec<"CPU": + #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>>} { func.func private @f() } @@ -105,7 +124,7 @@ module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op %module = transform.get_parent_op %func : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"CPU"::"test.id" at %module : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["CPU","test.id"] at %module : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %module : !transform.any_param, !transform.any_op transform.yield } @@ -116,13 +135,13 @@ module attributes {transform.with_named_sequence} { module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { // expected-remark @below {{associated attr 43 : i32}} - func.func private @f() + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"GPU"::"test.id" at %func : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["GPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op transform.yield } @@ -139,7 +158,7 @@ module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_dev module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"CPU"::"test.id" at %func : (!transform.any_op) -> !transform.any_param + %param = transform.dlti.query ["CPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op transform.yield } @@ -147,8 +166,35 @@ module attributes {transform.with_named_sequence} { // ----- -module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"cache::L1::size_in_bytes", 65536 : i32>, - #dlti.dl_entry<"cache::L1d::size_in_bytes", 32768 : i32>>> } { +module attributes { test.dlti = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec< + #dlti.dl_entry<"cache::L1::size_in_bytes", 65536 : i32>, + #dlti.dl_entry<"cache::L1d::size_in_bytes", 32768 : i32>>> } { + // expected-remark @below {{L1::size_in_bytes 65536 : i32}} + // expected-remark @below {{L1d::size_in_bytes 32768 : i32}} + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + %l1_size = transform.dlti.query ["CPU","cache::L1::size_in_bytes"] at %func : (!transform.any_op) -> !transform.param + %l1d_size = transform.dlti.query ["CPU","cache::L1d::size_in_bytes"] at %func : (!transform.any_op) -> !transform.param + transform.debug.emit_param_as_remark %l1_size, "L1::size_in_bytes" at %func : !transform.param, !transform.any_op + transform.debug.emit_param_as_remark %l1d_size, "L1d::size_in_bytes" at %func : !transform.param, !transform.any_op + transform.yield + } +} + +// ----- + +#l1_size = #dlti.map<#dlti.dl_entry<"size_in_bytes", 65536 : i32>> +#l1d_size = #dlti.map<#dlti.dl_entry<"size_in_bytes", 32768 : i32>> +module attributes { test.dlti = + #dlti.target_system_spec<"CPU": + #dlti.target_device_spec<#dlti.dl_entry<"cache", + #dlti.map<#dlti.dl_entry<"L1", #l1_size>, + #dlti.dl_entry<"L1d", #l1d_size> >>>> } { // expected-remark @below {{L1::size_in_bytes 65536 : i32}} // expected-remark @below {{L1d::size_in_bytes 32768 : i32}} func.func private @f() @@ -157,8 +203,8 @@ module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_dev module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %l1_size = transform.dlti.query ::"CPU"::"cache::L1::size_in_bytes" at %func : (!transform.any_op) -> !transform.param - %l1d_size = transform.dlti.query ::"CPU"::"cache::L1d::size_in_bytes" at %func : (!transform.any_op) -> !transform.param + %l1_size = transform.dlti.query ["CPU","cache","L1","size_in_bytes"] at %func : (!transform.any_op) -> !transform.param + %l1d_size = transform.dlti.query ["CPU","cache","L1d","size_in_bytes"] at %func : (!transform.any_op) -> !transform.param transform.debug.emit_param_as_remark %l1_size, "L1::size_in_bytes" at %func : !transform.param, !transform.any_op transform.debug.emit_param_as_remark %l1d_size, "L1d::size_in_bytes" at %func : !transform.param, !transform.any_op transform.yield @@ -167,15 +213,16 @@ module attributes {transform.with_named_sequence} { // ----- -module attributes { test.dlti = #dlti.target_system_spec<"CPU": - #dlti.target_device_spec<#dlti.dl_entry<"inner_most_tile_size", 42 : i32>>>} { +module attributes { test.dlti = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec< + #dlti.dl_entry<"inner_most_tile_size", 42 : i32>>>} { // CHECK-LABEL: func @matmul_tensors func.func @matmul_tensors( %arg0: tensor, %arg1: tensor, %arg2: tensor) -> tensor { // CHECK: scf.for {{.*}} to {{.*}} step {{.*}}42 // CHECK: tensor.extract_slice - // CHECK: linalg.matmul + // CHECK: linalg.matmul // CHECK: tensor.insert_slice // CHECK: scf.yield %0 = linalg.matmul ins(%arg0, %arg1: tensor, tensor) @@ -190,7 +237,7 @@ module attributes { test.dlti = #dlti.target_system_spec<"CPU": module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %matmul = transform.structured.match ops{["linalg.matmul"]} in %arg : (!transform.any_op) -> !transform.any_op - %tile_size = transform.dlti.query ::"CPU"::"inner_most_tile_size" at %matmul : (!transform.any_op) -> !transform.param + %tile_size = transform.dlti.query ["CPU","inner_most_tile_size"] at %matmul : (!transform.any_op) -> !transform.param transform.structured.tile_using_for %matmul tile_sizes [%tile_size] : (!transform.any_op, !transform.param) -> (!transform.any_op, !transform.any_op) transform.yield } @@ -198,67 +245,91 @@ module attributes {transform.with_named_sequence} { // ----- -module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, - "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { - // expected-error @below {{no "NPU" target device spec found}} - func.func private @f() +// expected-note @below {{key "NPU" has no DLTI-mapping per attr: #dlti.target_system_spec}} +module attributes { test.dlti = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, + "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { + // expected-error @below {{target op of failed DLTI query}} + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"NPU"::"test.id" at %func : (!transform.any_op) -> !transform.any_param - transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["NPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.yield } } // ----- -module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, - "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { - // expected-error @below {{no DLTI entry for key: "unspecified"}} - func.func private @f() +// expected-note @below {{key "unspecified" has no DLTI-mapping per attr: #dlti.target_device_spec}} +module attributes { test.dlti = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, + "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { + // expected-error @below {{target op of failed DLTI query}} + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"CPU"::"unspecified" at %func : (!transform.any_op) -> !transform.any_param - transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["CPU","unspecified"] at %func : (!transform.any_op) -> !transform.any_param transform.yield } } // ----- -module attributes { test.dlti = #dlti.target_system_spec<"CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, - "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { - // expected-error @below {{no data layout spec associated to: }} - func.func private @f() +// expected-note @below {{key "test.id" has no DLTI-mapping per attr: #dlti.target_system_spec}} +module attributes { test.dlti = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 42 : i32>>, + "GPU": #dlti.target_device_spec<#dlti.dl_entry<"test.id", 43 : i32>>>} { + // expected-error @below {{target op of failed DLTI query}} + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query "test.id" at %func : (!transform.any_op) -> !transform.any_param - transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.yield } } // ----- +// expected-note @below {{key "CPU" has no DLTI-mapping per attr: #dlti.dl_spec}} module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"test.id", 42 : i32>>} { - // expected-error @below {{no target system spec associated to: }} - func.func private @f() + // expected-error @below {{target op of failed DLTI query}} + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"CPU"::"test.id" at %func : (!transform.any_op) -> !transform.any_param - transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["CPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param + transform.yield + } +} + +// ----- + +// expected-note @below {{got non-DLTI-queryable attribute upon looking up keys ["CPU"]}} +module attributes { test.dlti = #dlti.dl_spec<#dlti.dl_entry<"CPU", 42 : i32>>} { + // expected-error @below {{target op of failed DLTI query}} + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["CPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.yield } } @@ -266,15 +337,16 @@ module attributes {transform.with_named_sequence} { // ----- module { - // expected-error @below {{no target system spec associated to: }} - func.func private @f() + // expected-error @below {{target op of failed DLTI query}} + // expected-note @below {{no DLTI-queryable attrs on target op or any of its ancestors}} + func.func private @f() } module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %func = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op - %param = transform.dlti.query ::"CPU"::"test.id" at %func : (!transform.any_op) -> !transform.any_param - transform.debug.emit_param_as_remark %param, "associated attr" at %func : !transform.any_param, !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["CPU","test.id"] at %func : (!transform.any_op) -> !transform.any_param transform.yield } } @@ -289,8 +361,7 @@ module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg: !transform.any_op) { %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op // expected-error @below {{expected the type of the parameter attribute ('i32') to match the parameter type ('i64')}} - %param = transform.dlti.query "test.id" at %funcs : (!transform.any_op) -> !transform.param - transform.debug.emit_param_as_remark %param, "associated attr" at %funcs : !transform.param, !transform.any_op + %param = transform.dlti.query ["test.id"] at %funcs : (!transform.any_op) -> !transform.param transform.yield } -} +} \ No newline at end of file diff --git a/mlir/test/Dialect/DLTI/valid.mlir b/mlir/test/Dialect/DLTI/valid.mlir index 8ee7a7eaa069db..4133eac5424ce8 100644 --- a/mlir/test/Dialect/DLTI/valid.mlir +++ b/mlir/test/Dialect/DLTI/valid.mlir @@ -1,5 +1,41 @@ // RUN: mlir-opt -split-input-file %s | FileCheck %s + +// CHECK: module attributes { +// CHECK-SAME: dlti.map = #dlti.map< +// CHECK-SAME: #dlti.dl_entry<"magic_num", 42 : i32>, +// CHECK-SAME: #dlti.dl_entry<"magic_num_float", 4.242000e+01 : f32>, +// CHECK-SAME: #dlti.dl_entry<"magic_type", i32>, +// CHECK-SAME: #dlti.dl_entry>> +// CHECK-SAME: >} { +// CHECK: } +module attributes { + dlti.map = #dlti.map< + #dlti.dl_entry<"magic_num", 42 : i32>, + #dlti.dl_entry<"magic_num_float", 42.42 : f32>, + #dlti.dl_entry<"magic_type", i32>, + #dlti.dl_entry>> + >} {} + +// ----- + +// CHECK: module attributes { +// CHECK-SAME: dlti.map = #dlti.map< +// CHECK-SAME: #dlti.dl_entry<"CPU", #dlti.map< +// CHECK-SAME: #dlti.dl_entry<"L1_cache_size_in_bytes", 4096 : i32>>>, +// CHECK-SAME: #dlti.dl_entry<"GPU", #dlti.map< +// CHECK-SAME: #dlti.dl_entry<"max_vector_op_width", 128 : i32>>> +// CHECK-SAME: >} { +// CHECK: } +module attributes { + dlti.map = #dlti.map< + #dlti.dl_entry<"CPU", #dlti.map< + #dlti.dl_entry<"L1_cache_size_in_bytes", 4096 : i32>>>, + #dlti.dl_entry<"GPU", #dlti.map< + #dlti.dl_entry<"max_vector_op_width", 128 : i32>>> + >} {} + // ----- // CHECK: module attributes { @@ -147,3 +183,26 @@ module attributes { "GPU": #dlti.target_device_spec< #dlti.dl_entry<"L1_cache_size_in_bytes", "128">> >} {} + + +// ----- + +// Check values of mixed type +// +// CHECK: module attributes { +// CHECK-SAME: dlti.target_system_spec = #dlti.target_system_spec< +// CHECK-SAME: "CPU" : #dlti.target_device_spec< +// CHECK-SAME: #dlti.dl_entry<"vector_unit", #dlti.map< +// CHECK-SAME: #dlti.dl_entry<"max_op_width", 4.096000e+03 : f32>>>>, +// CHECK-SAME: "GPU" : #dlti.target_device_spec< +// CHECK-SAME: #dlti.dl_entry<"L1_cache_size_in_bytes", "128">> +// CHECK-SAME: >} { +// CHECK: } +module attributes { + dlti.target_system_spec = #dlti.target_system_spec< + "CPU": #dlti.target_device_spec< + #dlti.dl_entry<"vector_unit", #dlti.map< + #dlti.dl_entry<"max_op_width", 4096.0 : f32>>>>, + "GPU": #dlti.target_device_spec< + #dlti.dl_entry<"L1_cache_size_in_bytes", "128">> + >} {} diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp index d1227b045d4ed3..b667785c16f162 100644 --- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp +++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp @@ -58,9 +58,9 @@ class DataLayoutSpecStorage : public AttributeStorage { /// Simple data layout spec containing a list of entries that always verifies /// as valid. struct CustomDataLayoutSpec - : public Attribute::AttrBase { + : public Attribute::AttrBase< + CustomDataLayoutSpec, Attribute, DataLayoutSpecStorage, + DLTIQueryInterface::Trait, DataLayoutSpecInterface::Trait> { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CustomDataLayoutSpec) using Base::Base; @@ -92,6 +92,9 @@ struct CustomDataLayoutSpec StringAttr getStackAlignmentIdentifier(MLIRContext *context) const { return Builder(context).getStringAttr(kStackAlignmentKeyName); } + FailureOr query(DataLayoutEntryKey key) const { + return llvm::cast(*this).queryHelper(key); + } }; class TargetSystemSpecStorage : public AttributeStorage { @@ -113,9 +116,9 @@ class TargetSystemSpecStorage : public AttributeStorage { }; struct CustomTargetSystemSpec - : public Attribute::AttrBase { + : public Attribute::AttrBase< + CustomTargetSystemSpec, Attribute, TargetSystemSpecStorage, + DLTIQueryInterface::Trait, TargetSystemSpecInterface::Trait> { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(CustomDataLayoutSpec) using Base::Base; @@ -138,6 +141,9 @@ struct CustomTargetSystemSpec } return std::nullopt; } + FailureOr query(DataLayoutEntryKey key) const { + return llvm::cast(*this).queryHelper(key); + } }; /// A type subject to data layout that exits the program if it is queried more