Skip to content

Reimplementing target description concept using DLTI attribute #92138

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

Merged
merged 8 commits into from
Jun 19, 2024

Conversation

nhasabni
Copy link
Contributor

@nhasabni nhasabni commented May 14, 2024

and Interfaces. This is a newer implementation of PR #85141 and RFC by considering reviews and comments on the original PR.

As an example of attributes supported by this commit:

module attributes {
   dlti.target_system_spec =
     #dlti.target_device_spec<
       #dlti.dl_entry<"dlti.device_id", 0: ui32>,
       #dlti.dl_entry<"dlti.device_type", "CPU">,
       #dlti.dl_entry<"dlti.L1_cache_size_in_bytes", 8192 : ui32>>,
     #dlti.target_device_spec <
       #dlti.dl_entry<"dlti.device_id", 1: ui32>,
       #dlti.dl_entry<"dlti.device_type", "GPU">,
       #dlti.dl_entry<"dlti.max_vector_op_width", 64 : ui32>>,
    #dlti.target_device_spec <
       #dlti.dl_entry<"dlti.device_id", 2: ui32>,
       #dlti.dl_entry<"dlti.device_type", "XPU">>>
}

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented May 14, 2024

@llvm/pr-subscribers-mlir-dlti
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-backend-amdgpu

Author: Niranjan Hasabnis (nhasabni)

Changes

and Interfaces. This is a newer implementation of PR #85141 and RFC by considering reviews and comments on the original PR.

As an example of attributes supported by this commit:

module attributes {
   dlti.tsd_spec =
     #dlti.tdd_spec&lt;
       #dlti.dl_entry&lt;"dlti.device_id", 0: ui32&gt;,
       #dlti.dl_entry&lt;"dlti.device_type", "CPU"&gt;,
       #dlti.dl_entry&lt;"dlti.canonicalizer_max_iterations", 100 : i32&gt;,
       #dlti.dl_entry&lt;"dlti.canonicalizer_max_num_rewrites", -5 : i32&gt;&gt;,
    #dlti.tdd_spec&lt;
       #dlti.dl_entry&lt;"dlti.device_id", 1: ui32&gt;,
       #dlti.dl_entry&lt;"dlti.device_type", "GPU"&gt;,
       #dlti.dl_entry&lt;"dlti.max_vector_op_width", 64 : ui32&gt;&gt;,
    #dlti.tdd_spec&lt;
       #dlti.dl_entry&lt;"dlti.device_id", 2: ui32&gt;,
       #dlti.dl_entry&lt;"dlti.device_type", "XPU"&gt;&gt;&gt;
}

Patch is 62.15 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92138.diff

14 Files Affected:

  • (modified) mlir/include/mlir/Dialect/DLTI/DLTI.h (+146)
  • (modified) mlir/include/mlir/Dialect/DLTI/DLTIBase.td (+44)
  • (modified) mlir/include/mlir/Dialect/DLTI/Traits.h (+7)
  • (modified) mlir/include/mlir/IR/BuiltinOps.td (+1)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.h (+65)
  • (modified) mlir/include/mlir/Interfaces/DataLayoutInterfaces.td (+228)
  • (modified) mlir/lib/Conversion/AMDGPUToROCDL/AMDGPUToROCDL.cpp (+12-1)
  • (modified) mlir/lib/Dialect/DLTI/DLTI.cpp (+363-4)
  • (modified) mlir/lib/Dialect/DLTI/Traits.cpp (+6)
  • (modified) mlir/lib/Dialect/Linalg/Transforms/BlockPackMatmul.cpp (+21-1)
  • (modified) mlir/lib/IR/BuiltinDialect.cpp (+11)
  • (modified) mlir/lib/Interfaces/DataLayoutInterfaces.cpp (+183-2)
  • (modified) mlir/lib/Transforms/Canonicalizer.cpp (+51)
  • (modified) mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp (+10)
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTI.h b/mlir/include/mlir/Dialect/DLTI/DLTI.h
index 5ac7c11e6ffee..f78e8bdc5eb98 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTI.h
+++ b/mlir/include/mlir/Dialect/DLTI/DLTI.h
@@ -21,6 +21,8 @@ namespace mlir {
 namespace impl {
 class DataLayoutEntryStorage;
 class DataLayoutSpecStorage;
+class TargetSystemDescSpecAttrStorage;
+class TargetDeviceDescSpecAttrStorage;
 } // namespace impl
 
 //===----------------------------------------------------------------------===//
@@ -124,6 +126,150 @@ class DataLayoutSpecAttr
   static constexpr StringLiteral name = "builtin.data_layout_spec";
 };
 
+//===----------------------------------------------------------------------===//
+// TargetSystemDescSpecAttr
+//===----------------------------------------------------------------------===//
+
+/// A system description attribute is a list of device descriptors, each
+/// having a unique device ID
+class TargetSystemDescSpecAttr
+    : public Attribute::AttrBase<TargetSystemDescSpecAttr, Attribute,
+                                 impl::TargetSystemDescSpecAttrStorage,
+                                 TargetSystemDescSpecInterface::Trait> {
+public:
+  using Base::Base;
+
+  /// The keyword used for this attribute in custom syntax.
+  constexpr const static StringLiteral kAttrKeyword = "tsd_spec";
+
+  /// Returns a system descriptor attribute from the given system descriptor
+  static TargetSystemDescSpecAttr
+  get(MLIRContext *context, ArrayRef<TargetDeviceDescSpecInterface> entries);
+
+  /// Returns the list of entries.
+  TargetDeviceDescSpecListRef getEntries() const;
+
+  /// Return the device descriptor that matches the given device ID
+  TargetDeviceDescSpecInterface getDeviceDescForDeviceID(uint32_t deviceID);
+
+  /// Returns the specification containing the given list of keys. If the list
+  /// contains duplicate keys or is otherwise invalid, reports errors using the
+  /// given callback and returns null.
+  static TargetSystemDescSpecAttr
+  getChecked(function_ref<InFlightDiagnostic()> emitError, MLIRContext *context,
+             ArrayRef<TargetDeviceDescSpecInterface> entries);
+
+  /// Checks that the given list of entries does not contain duplicate keys.
+  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
+                              ArrayRef<TargetDeviceDescSpecInterface> entries);
+
+  /// Parses an instance of this attribute.
+  static TargetSystemDescSpecAttr parse(AsmParser &parser);
+
+  /// Prints this attribute.
+  void print(AsmPrinter &os) const;
+
+  static constexpr StringLiteral name = "builtin.target_system_description";
+};
+
+//===----------------------------------------------------------------------===//
+// TargetDeviceDescSpecAttr
+//===----------------------------------------------------------------------===//
+
+class TargetDeviceDescSpecAttr
+    : public Attribute::AttrBase<TargetDeviceDescSpecAttr, Attribute,
+                                 impl::TargetDeviceDescSpecAttrStorage,
+                                 TargetDeviceDescSpecInterface::Trait> {
+public:
+  using Base::Base;
+
+  /// The keyword used for this attribute in custom syntax.
+  constexpr const static StringLiteral kAttrKeyword = "tdd_spec";
+
+  /// Returns a system descriptor attribute from the given system descriptor
+  static TargetDeviceDescSpecAttr
+  get(MLIRContext *context, ArrayRef<DataLayoutEntryInterface> entries);
+
+  /// Returns the specification containing the given list of keys. If the list
+  /// contains duplicate keys or is otherwise invalid, reports errors using the
+  /// given callback and returns null.
+  static TargetDeviceDescSpecAttr
+  getChecked(function_ref<InFlightDiagnostic()> emitError, MLIRContext *context,
+             ArrayRef<DataLayoutEntryInterface> entries);
+
+  /// Checks that the given list of entries does not contain duplicate keys.
+  static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
+                              ArrayRef<DataLayoutEntryInterface> entries);
+
+  /// Returns the list of entries.
+  DataLayoutEntryListRef getEntries() const;
+
+  /// Parses an instance of this attribute.
+  static TargetDeviceDescSpecAttr parse(AsmParser &parser);
+
+  /// Prints this attribute.
+  void print(AsmPrinter &os) const;
+
+  /// Returns the device ID identifier.
+  StringAttr getDeviceIDIdentifier(MLIRContext *context);
+
+  /// Returns the device type identifier.
+  StringAttr getDeviceTypeIdentifier(MLIRContext *context);
+
+  /// Returns max vector op width identifier.
+  StringAttr getMaxVectorOpWidthIdentifier(MLIRContext *context);
+
+  /// Returns canonicalizer max iterations identifier.
+  StringAttr getCanonicalizerMaxIterationsIdentifier(MLIRContext *context);
+
+  /// Returns canonicalizer max num rewrites identifier.
+  StringAttr getCanonicalizerMaxNumRewritesIdentifier(MLIRContext *context);
+
+  /// Returns L1 cache size identifier
+  StringAttr getL1CacheSizeInBytesIdentifier(MLIRContext *context);
+
+  /// Returns the interface spec for device ID
+  /// Since we verify that the spec contains device ID the function
+  /// will return a valid spec.
+  DataLayoutEntryInterface getSpecForDeviceID(MLIRContext *context);
+
+  /// Returns the interface spec for device type
+  /// Since we verify that the spec contains device type the function
+  /// will return a valid spec.
+  DataLayoutEntryInterface getSpecForDeviceType(MLIRContext *context);
+
+  /// Returns the interface spec for max vector op width
+  /// Since max vector op width is an optional property, this function will
+  /// return a valid spec if the property is defined, otherwise it
+  /// will return an empty spec.
+  DataLayoutEntryInterface getSpecForMaxVectorOpWidth(MLIRContext *context);
+
+  /// Returns the interface spec for L1 cache size
+  /// Since L1 cache size is an optional property, this function will
+  /// return a valid spec if the property is defined, otherwise it
+  /// will return an empty spec.
+  DataLayoutEntryInterface getSpecForL1CacheSizeInBytes(MLIRContext *context);
+
+  /// Returns the interface spec for canonicalizer max iterations.
+  /// Since this is an optional property, this function will
+  /// return a valid spec if the property is defined, otherwise it
+  /// will return an empty spec.
+  DataLayoutEntryInterface
+  getSpecForCanonicalizerMaxIterations(MLIRContext *context);
+
+  /// Returns the interface spec for canonicalizer max num rewrites.
+  /// Since this is an optional property, this function will
+  /// return a valid spec if the property is defined, otherwise it
+  /// will return an empty spec.
+  DataLayoutEntryInterface
+  getSpecForCanonicalizerMaxNumRewrites(MLIRContext *context);
+
+  /// Return the value of device ID
+  uint32_t getDeviceID(MLIRContext *context);
+
+  static constexpr StringLiteral name = "builtin.target_device_description";
+};
+
 } // namespace mlir
 
 #include "mlir/Dialect/DLTI/DLTIDialect.h.inc"
diff --git a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
index 3572a99fad874..c9a054b3c1e51 100644
--- a/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
+++ b/mlir/include/mlir/Dialect/DLTI/DLTIBase.td
@@ -27,6 +27,13 @@ def DLTI_Dialect : Dialect {
     constexpr const static ::llvm::StringLiteral
     kDataLayoutAttrName = "dlti.dl_spec";
 
+    // Top level attribute name for target system description
+    constexpr const static ::llvm::StringLiteral
+    kTargetSystemDescAttrName = "dlti.tsd_spec";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceDescAttrName = "dlti.tdd_spec";
+
     // Constants used in entries.
     constexpr const static ::llvm::StringLiteral
     kDataLayoutEndiannessKey = "dlti.endianness";
@@ -48,6 +55,25 @@ def DLTI_Dialect : Dialect {
 
     constexpr const static ::llvm::StringLiteral
     kDataLayoutStackAlignmentKey = "dlti.stack_alignment";
+
+    // Constants used in target description part of DLTI
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceIDKey = "dlti.device_id";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceTypeKey = "dlti.device_type";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceMaxVectorOpWidthKey = "dlti.max_vector_op_width";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceCanonicalizerMaxIterationsKey = "dlti.canonicalizer_max_iterations";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceCanonicalizerMaxNumRewritesKey = "dlti.canonicalizer_max_num_rewrites";
+
+    constexpr const static ::llvm::StringLiteral
+    kTargetDeviceL1CacheSizeInBytesKey = "dlti.L1_cache_size_in_bytes";
   }];
 
   let useDefaultAttributePrinterParser = 1;
@@ -71,6 +97,24 @@ def DLTI_DataLayoutSpecAttr : DialectAttr<
   let convertFromStorage = "$_self";
 }
 
+def DLTI_TargetSystemDescSpecAttr : DialectAttr<
+    DLTI_Dialect,
+    CPred<"::llvm::isa<::mlir::TargetSystemDescSpecAttr>($_self)">,
+    "Target system description part of DLTI"> {
+  let storageType = "::mlir::TargetSystemDescSpecAttr";
+  let returnType = "::mlir::TargetSystemDescSpecAttr";
+  let convertFromStorage = "$_self";
+}
+
+def DLTI_TargetDeviceDescSpecAttr : DialectAttr<
+    DLTI_Dialect,
+    CPred<"::llvm::isa<::mlir::TargetDeviceDescSpecAttr>($_self)">,
+    "Target device description part of DLTI"> {
+  let storageType = "::mlir::TargetDeviceDescSpecAttr";
+  let returnType = "::mlir::TargetDeviceDescSpecAttr";
+  let convertFromStorage = "$_self";
+}
+
 def HasDefaultDLTIDataLayout : NativeOpTrait<"HasDefaultDLTIDataLayout"> {
   let cppNamespace = "::mlir";
 }
diff --git a/mlir/include/mlir/Dialect/DLTI/Traits.h b/mlir/include/mlir/Dialect/DLTI/Traits.h
index 5d86195305a95..44083d54c4cad 100644
--- a/mlir/include/mlir/Dialect/DLTI/Traits.h
+++ b/mlir/include/mlir/Dialect/DLTI/Traits.h
@@ -18,6 +18,7 @@ class DataLayoutSpecAttr;
 namespace impl {
 LogicalResult verifyHasDefaultDLTIDataLayoutTrait(Operation *op);
 DataLayoutSpecInterface getDataLayoutSpec(Operation *op);
+TargetSystemDescSpecInterface getTargetSystemDescSpec(Operation *op);
 } // namespace impl
 
 /// Trait to be used by operations willing to use the implementation of the
@@ -37,6 +38,12 @@ class HasDefaultDLTIDataLayout
   DataLayoutSpecInterface getDataLayoutSpec() {
     return impl::getDataLayoutSpec(this->getOperation());
   }
+
+  /// Returns the target system description specification as provided by DLTI
+  /// dialect
+  TargetSystemDescSpecInterface getTargetSystemDescSpec() {
+    return impl::getTargetSystemDescSpec(this->getOperation());
+  }
 };
 } // namespace mlir
 
diff --git a/mlir/include/mlir/IR/BuiltinOps.td b/mlir/include/mlir/IR/BuiltinOps.td
index eda24615c71ea..bdb4ce3ddfe20 100644
--- a/mlir/include/mlir/IR/BuiltinOps.td
+++ b/mlir/include/mlir/IR/BuiltinOps.td
@@ -78,6 +78,7 @@ def ModuleOp : Builtin_Op<"module", [
     //===------------------------------------------------------------------===//
 
     DataLayoutSpecInterface getDataLayoutSpec();
+    TargetSystemDescSpecInterface getTargetSystemDescSpec();
 
     //===------------------------------------------------------------------===//
     // OpAsmOpInterface Methods
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
index 76bf33e89a716..1584a13247dff 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h
@@ -23,11 +23,17 @@
 namespace mlir {
 class DataLayout;
 class DataLayoutEntryInterface;
+class TargetDeviceDescSpecInterface;
+class TargetSystemDescSpecInterface;
 using DataLayoutEntryKey = llvm::PointerUnion<Type, StringAttr>;
 // Using explicit SmallVector size because we cannot infer the size from the
 // forward declaration, and we need the typedef in the actual declaration.
 using DataLayoutEntryList = llvm::SmallVector<DataLayoutEntryInterface, 4>;
 using DataLayoutEntryListRef = llvm::ArrayRef<DataLayoutEntryInterface>;
+// using TargetDeviceDescSpecList =
+// llvm::SmallVector<TargetDeviceDescSpecInterface, 4>;
+using TargetDeviceDescSpecListRef =
+    llvm::ArrayRef<TargetDeviceDescSpecInterface>;
 class DataLayoutOpInterface;
 class DataLayoutSpecInterface;
 class ModuleOp;
@@ -84,6 +90,24 @@ Attribute getDefaultGlobalMemorySpace(DataLayoutEntryInterface entry);
 /// DataLayoutInterface if specified, otherwise returns the default.
 uint64_t getDefaultStackAlignment(DataLayoutEntryInterface entry);
 
+/// return max vector op width from the specified DataLayoutEntry. If the
+/// property is missing from the entry, then return std::nullopt.
+std::optional<uint32_t> getMaxVectorOpWidth(DataLayoutEntryInterface entry);
+
+/// return L1 cache size in bytes from the specified DataLayoutEntry. If the
+/// property is missing from the entry, then return std::nullopt.
+std::optional<uint32_t> getL1CacheSizeInBytes(DataLayoutEntryInterface entry);
+
+/// return canonicalizer max iterations from the specified DataLayoutEntry.
+/// If the property is missing from the entry, then return std::nullopt.
+std::optional<int64_t>
+getCanonicalizerMaxIterations(DataLayoutEntryInterface entry);
+
+/// returncanonicalizer max num rewrites from the specified DataLayoutEntry.
+/// If the property is missing from the entry, then return std::nullopt.
+std::optional<int64_t>
+getCanonicalizerMaxNumRewrites(DataLayoutEntryInterface entry);
+
 /// Given a list of data layout entries, returns a new list containing the
 /// entries with keys having the given type ID, i.e. belonging to the same type
 /// class.
@@ -95,6 +119,11 @@ DataLayoutEntryList filterEntriesForType(DataLayoutEntryListRef entries,
 DataLayoutEntryInterface
 filterEntryForIdentifier(DataLayoutEntryListRef entries, StringAttr id);
 
+/// Given a list of target device entries, returns the entry that has the given
+/// identifier as key, if such an entry exists in the list.
+TargetDeviceDescSpecInterface
+filterEntryForIdentifier(TargetDeviceDescSpecListRef entries, StringAttr id);
+
 /// Verifies that the operation implementing the data layout interface, or a
 /// module operation, is valid. This calls the verifier of the spec attribute
 /// and checks if the layout is compatible with specs attached to the enclosing
@@ -106,6 +135,12 @@ LogicalResult verifyDataLayoutOp(Operation *op);
 /// and dialect interfaces for type and identifier keys respectively.
 LogicalResult verifyDataLayoutSpec(DataLayoutSpecInterface spec, Location loc);
 
+/// Verifies that a target system desc spec is valid. This dispatches to
+/// individual entry verifiers, and then to the verifiers implemented by the
+/// relevant dialect interfaces for identifier keys.
+LogicalResult verifyTargetSystemDescSpec(TargetSystemDescSpecInterface spec,
+                                         Location loc);
+
 /// Divides the known min value of the numerator by the denominator and rounds
 /// the result up to the next integer. Preserves the scalable flag.
 llvm::TypeSize divideCeil(llvm::TypeSize numerator, uint64_t denominator);
@@ -137,6 +172,13 @@ class DataLayoutDialectInterface
     return success();
   }
 
+  /// Checks whether the given data layout entry is valid and reports any errors
+  /// at the provided location. Derived classes should override this.
+  virtual LogicalResult verifyEntry(TargetDeviceDescSpecInterface entry,
+                                    Location loc) const {
+    return success();
+  }
+
   /// Default implementation of entry combination that combines identical
   /// entries and returns null otherwise.
   static DataLayoutEntryInterface
@@ -214,10 +256,33 @@ class DataLayout {
   /// unspecified.
   uint64_t getStackAlignment() const;
 
+  /// Returns for max vector op width if the property is defined for the given
+  /// device ID, otherwise return std::nullopt.
+  std::optional<uint32_t>
+      getMaxVectorOpWidth(TargetDeviceDescSpecInterface::DeviceID) const;
+
+  /// Returns for L1 cache size if the property is defined for the given
+  /// device ID, otherwise return std::nullopt.
+  std::optional<uint32_t>
+      getL1CacheSizeInBytes(TargetDeviceDescSpecInterface::DeviceID) const;
+
+  /// Returns for canonicalizer max iterations if the property is defined for
+  /// the given device ID, otherwise return std::nullopt.
+  std::optional<int64_t> getCanonicalizerMaxIterations(
+      TargetDeviceDescSpecInterface::DeviceID) const;
+
+  /// Returns for canonicalizer max rewrites if the property is defined for
+  /// the given device ID, otherwise return std::nullopt.
+  std::optional<int64_t> getCanonicalizerMaxNumRewrites(
+      TargetDeviceDescSpecInterface::DeviceID) const;
+
 private:
   /// Combined layout spec at the given scope.
   const DataLayoutSpecInterface originalLayout;
 
+  /// Combined target system desc spec at the given scope.
+  const TargetSystemDescSpecInterface originalTargetSystemDesc;
+
 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
   /// List of enclosing layout specs.
   SmallVector<DataLayoutSpecInterface, 2> layoutStack;
diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
index 9edc885b9c5a9..75e609dde8fcf 100644
--- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
+++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td
@@ -194,6 +194,182 @@ def DataLayoutSpecInterface : AttrInterface<"DataLayoutSpecInterface"> {
   }];
 }
 
+def TargetDeviceDescSpecInterface : AttrInterface<"TargetDeviceDescSpecInterface"> {
+  let cppNamespace = "::mlir";
+
+  let description = [{
+    Attribute interface describing a target device description specification.
+
+    A target device description specification is a list of device properties (key)
+    and their values for a specific device. The device is identified using "device_id"
+    (as a key and ui32 value) and "device_type" key which must have a string value.
+    Both "device_id" and "device_type" are mandatory keys. As an example, L1 cache
+    size could be a device property, and its value would be a device specific size.
+
+    A target device description specification is attached to a module as a module level
+    attribute.
+  }];
+
+  let methods = [
+    InterfaceMethod<
+      /*description=*/"Returns the list of layout entries.",
+      /*retTy=*/"::mlir::DataLayoutEntryListRef",
+      /*methodName=*/"getEntries",
+      /*args=*/(ins)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the entry related to the given identifier, if "
+                      "present.",
+      /*retTy=*/"::mlir::DataLayoutEntryInterface",
+      /*methodName=*/"getSpecForIdentifier",
+      /*args=*/(ins "::mlir::StringAttr":$identifier),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{
+        return ::mlir::detail::filterEntryForIdentifier($_attr.getEntries(),
+                                                        identifier);
+      }]
+    >,
+    InterfaceMethod<
+      /*description=*/"Checks that the entry is well-formed, reports errors "
+                      "at the provided location.",
+      /*retTy=*/"::mlir::LogicalResult",
+      /*methodName=*/"verifyEntry",
+      /*args=*/(ins "::mlir::Location":$loc),
+      /*methodBody=*/"",
+      /*defaultImplementation=*/[{ return ::mlir::success(); }]
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the device ID identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getDeviceIDIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the device type identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getDeviceTypeIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the L1 cache size identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getMaxVectorOpWidthIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns canonicalizer max iterations identifier.",
+      /*retTy=*/"::mlir::StringAttr",
+      /*methodName=*/"getCanonicalizerMaxIterationsIdentifier",
+      /*args=*/(ins "::mlir::MLIRContext *":$context)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns canonicalizer max num rew...
[truncated]

@nhasabni
Copy link
Contributor Author

@rengolin @joker-eph Please take a look. This is a DLTI based implementation for representing a target description as attributes. I've also added L1 cache size property and have used this property to calculate block size info in BlockMatMul pass.

@rengolin
Copy link
Member

This is a continuation of #91670 which was unintentionally closed. It addresses @joker-eph's point by adding target properties, not compiler pass options. It also has some usage on different places.

@adam-smnk

Copy link
Member

@ftynse ftynse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This generally goes in the right direction, let's iterate on this.

One large comment: this needs standalone tests for the target description part. For the existing DLTI part, we have a test pass that looks at certain kinds of ops and/or attributes and "interprets" them as requests to the data layout object, the results of these requests are appended back to ops as more attributes that we can FileCheck on. Something similar should be possible here.

@joker-eph
Copy link
Collaborator

This is a continuation of #91670 which was unintentionally closed.

FYI: a PR can be reopened after being closed (not merged) instead of opening a new one.

@rengolin
Copy link
Member

This is a continuation of #91670 which was unintentionally closed.

FYI: a PR can be reopened after being closed (not merged) instead of opening a new one.

I tried this but the PR told me the branch was clean and couldn't reopen, even thought it wasn't. I didn't want to fight Github on this. :(

@nhasabni
Copy link
Contributor Author

@joker-eph @ftynse Thanks for your comments. I've fixed most of them (incl ODS based implementation). Test cases is WIP. I will also separate out the integration of target properties into the passes into a separate PR.

@nhasabni
Copy link
Contributor Author

@joker-eph @ftynse I've addressed all of your comments. Pls take a look. Thanks.

@nhasabni nhasabni force-pushed the system_desc_cost_model_attrbased branch from 9399620 to 5bc3886 Compare May 22, 2024 14:08
@rengolin
Copy link
Member

Windows bot fails with system error, ignore:

fatal error C1060: compiler is out of heap space

@nhasabni
Copy link
Contributor Author

Windows bot fails with system error, ignore:

fatal error C1060: compiler is out of heap space

@rengolin Not sure if this is related to the PR. All the unit tests seem to pass.

@rengolin
Copy link
Member

Windows bot fails with system error, ignore:

fatal error C1060: compiler is out of heap space

@rengolin Not sure if this is related to the PR. All the unit tests seem to pass.

It is not, just ignore. The Windows builder is super slow and unreliable.

@nhasabni
Copy link
Contributor Author

@ftynse @joker-eph Just a gentle ping for the review.

@nhasabni nhasabni force-pushed the system_desc_cost_model_attrbased branch from 1fbacea to dfaacc2 Compare June 6, 2024 19:41
@nhasabni nhasabni force-pushed the system_desc_cost_model_attrbased branch from c5e7278 to c046d42 Compare June 15, 2024 00:15
@rengolin
Copy link
Member

rengolin commented Jun 15, 2024

@ftynse are all your questions addressed?

I'm hoping this is a good enough starting point, not a final design. I'm quite happy to navigate the questions in following PRs, so that we can do in parallel, even if they significantly change the design later.

We're not fixed on the current state, we just think it's a good seed for a shared infrastructure.

Copy link
Member

@ftynse ftynse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a bunch of stylistic nits. Please also think about the overall design for future steps :)

size could be a device property, and its value would be a device specific size.

A target device description specification is attached to a module as a module level
attribute.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since attributes are owned by context anyway, it doesn't cost us much to allow them at all levels. It would also avoid unchecked indirection (what if someone decides to reorder the list in system description, for example?)

checkValid();
DataLayoutEntryInterface entry;
if (originalTargetSystemDesc) {
if (auto device =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: expand auto unless the type is obvious.

}
}

for (const auto &kvp : device_desc_keys) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: (auto &&[first, second] : ... works now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need 2 &?

// is empty (meaning the spec is missing), returns std::nullopt.
std::optional<int64_t>
mlir::detail::getMaxVectorOpWidth(DataLayoutEntryInterface entry) {
if (entry == DataLayoutEntryInterface())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (entry == DataLayoutEntryInterface())
if (!entry)

But is this check useful?

@nhasabni nhasabni force-pushed the system_desc_cost_model_attrbased branch from 1c58e6f to 856426f Compare June 17, 2024 17:35
nhasabni added 8 commits June 18, 2024 18:25
1. Use ODS framework for all of DLTI attrs
2. Removing need of MLIRContext in APIs
3. Removing canonicalizer heuristics from this PR
    Mainly as follows:
    - removing custom attribute parser/printer
    - renaming SystemDescSpec to SystemSpec and TargetDeviceDescSpec to
      TargetDeviceSpec
    - using DeviceID as a type insted of uint32_t
    - grammatical errors
Representing TargetSystemSpec as a set of key-value pairs where key is
the DeviceID (string) and the value is TargetDeviceSpec.
@nhasabni nhasabni force-pushed the system_desc_cost_model_attrbased branch from 8a5eafa to 7964793 Compare June 19, 2024 01:25
Copy link
Collaborator

@joker-eph joker-eph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patience throughout the iterations @nhasabni !

@rengolin rengolin merged commit abd9534 into llvm:main Jun 19, 2024
7 checks passed
Copy link

@nhasabni Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested
by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as
the builds can include changes from many authors. It is not uncommon for your
change to be included in a build that fails due to someone else's changes, or
infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself.
This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

@nhasabni
Copy link
Contributor Author

Thanks for the patience throughout the iterations @nhasabni !

No problem! Thanks for the approval @joker-eph @ftynse!

@rengolin
Copy link
Member

FYI, here's our tracking of the following steps:
libxsmm/tpp-mlir#934

AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
…92138)

and Interfaces. This is a newer implementation of PR
llvm#85141 and
[RFC](https://discourse.llvm.org/t/rfc-target-description-and-cost-model-in-mlir/76990)
by considering reviews and comments on the original PR.

As an example of attributes supported by this commit:

```
module attributes {
   dlti.target_system_spec =
     #dlti.target_device_spec<
       #dlti.dl_entry<"dlti.device_id", 0: ui32>,
       #dlti.dl_entry<"dlti.device_type", "CPU">,
       #dlti.dl_entry<"dlti.L1_cache_size_in_bytes", 8192 : ui32>>,
     #dlti.target_device_spec <
       #dlti.dl_entry<"dlti.device_id", 1: ui32>,
       #dlti.dl_entry<"dlti.device_type", "GPU">,
       #dlti.dl_entry<"dlti.max_vector_op_width", 64 : ui32>>,
    #dlti.target_device_spec <
       #dlti.dl_entry<"dlti.device_id", 2: ui32>,
       #dlti.dl_entry<"dlti.device_type", "XPU">>>
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants