xref: /llvm-project/mlir/include/mlir/Dialect/DLTI/DLTIAttrs.td (revision 5c1752e368585e55c0335a7d7651fe43d42af282)
1//===- DLTIAttrs.td - DLTI dialect attributes definition --*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef MLIR_DIALECT_DLTI_DLTIATTRS_TD
10#define MLIR_DIALECT_DLTI_DLTIATTRS_TD
11
12include "mlir/Dialect/DLTI/DLTI.td"
13include "mlir/Interfaces/DataLayoutInterfaces.td"
14include "mlir/IR/AttrTypeBase.td"
15
16class DLTIAttr<string name, list<Trait> traits = [],
17                string baseCppClass = "::mlir::Attribute">
18    : AttrDef<DLTI_Dialect, name, traits, baseCppClass> { }
19
20//===----------------------------------------------------------------------===//
21// DataLayoutEntryAttr
22//===----------------------------------------------------------------------===//
23
24def DLTI_DataLayoutEntryAttr :
25    DLTIAttr<"DataLayoutEntry", [DataLayoutEntryInterface]> {
26  let summary = "An attribute to represent an entry of a data layout specification.";
27  let description = [{
28    A data layout entry attribute is a key-value pair where the key is a type or
29    an identifier and the value is another attribute. These entries form a data
30    layout specification.
31  }];
32  let parameters = (ins
33    "DataLayoutEntryKey":$key, "Attribute":$value
34  );
35  // TODO: We do not generate storage class because llvm::PointerUnion
36  // does not work with hash_key method.
37  let genStorageClass = 0;
38  let mnemonic = "dl_entry";
39  let genVerifyDecl = 0;
40  let hasCustomAssemblyFormat = 1;
41  let extraClassDeclaration = [{
42    /// Returns the entry with the given key and value.
43    static DataLayoutEntryAttr get(StringAttr key, Attribute value);
44    static DataLayoutEntryAttr get(MLIRContext *context, Type key, Attribute value);
45    static DataLayoutEntryAttr get(Type key, Attribute value);
46  }];
47}
48
49//===----------------------------------------------------------------------===//
50// DataLayoutSpecAttr
51//===----------------------------------------------------------------------===//
52
53def DLTI_DataLayoutSpecAttr :
54    DLTIAttr<"DataLayoutSpec", [DataLayoutSpecInterface]> {
55  let summary = "An attribute to represent a data layout specification.";
56  let description = [{
57    A data layout specification is a list of entries that specify (partial) data
58    layout information. It is expected to be attached to operations that serve
59    as scopes for data layout requests.
60  }];
61  let parameters = (ins
62    ArrayRefParameter<"DataLayoutEntryInterface", "">:$entries
63  );
64  let mnemonic = "dl_spec";
65  let genVerifyDecl = 1;
66  let hasCustomAssemblyFormat = 1;
67  let extraClassDeclaration = [{
68    /// Combines this specification with `specs`, enclosing specifications listed
69    /// from outermost to innermost. This overwrites the older entries with the
70    /// same key as the newer entries if the entries are compatible. Returns null
71    /// if the specifications are not compatible.
72    DataLayoutSpecAttr combineWith(ArrayRef<DataLayoutSpecInterface> specs) const;
73
74    /// Returns the endiannes identifier.
75    StringAttr getEndiannessIdentifier(MLIRContext *context) const;
76
77    /// Returns the alloca memory space identifier.
78    StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const;
79
80    /// Returns the program memory space identifier.
81    StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const;
82
83    /// Returns the global memory space identifier.
84    StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const;
85
86    /// Returns the stack alignment identifier.
87    StringAttr getStackAlignmentIdentifier(MLIRContext *context) const;
88
89    /// Returns the attribute associated with the key.
90    FailureOr<Attribute> query(DataLayoutEntryKey key) {
91      return ::llvm::cast<mlir::DataLayoutSpecInterface>(*this).queryHelper(key);
92    }
93  }];
94}
95
96//===----------------------------------------------------------------------===//
97// MapAttr
98//===----------------------------------------------------------------------===//
99
100def DLTI_MapAttr : DLTIAttr<"Map", [DLTIQueryInterface]> {
101  let summary = "A mapping of DLTI-information by way of key-value pairs";
102  let description = [{
103    A Data Layout and Target Information map is a list of entries effectively
104    encoding a dictionary, mapping DLTI-related keys to DLTI-related values.
105
106    This attribute's main purpose is to facilate querying IR for arbitrary
107    key-value associations that encode DLTI. Facility functions exist to perform
108    recursive lookups on nested DLTI-map/query interface-implementing
109    attributes.
110
111    Consider the following flat encoding of a single-key dictionary
112    ```
113    #dlti.map<"CPU::cache::L1::size_in_bytes" = 65536 : i32>>
114    ```
115    versus nested maps, which make it possible to obtain sub-dictionaries of
116    related information (with the following example making use of other
117    attributes that also implement the `DLTIQueryInterface`):
118    ```
119    #dlti.target_system_spec<"CPU" =
120      #dlti.target_device_spec<"cache" =
121        #dlti.map<"L1" = #dlti.map<"size_in_bytes" = 65536 : i32>,
122                  "L1d" = #dlti.map<"size_in_bytes" = 32768 : i32> >>>
123    ```
124
125    With the flat encoding, the implied structure of the key is ignored, that is
126    the only successful query (as expressed in the Transform Dialect) is:
127    `transform.dlti.query ["CPU::cache::L1::size_in_bytes"] at %op`,
128    where `%op` is a handle to an operation which associates the flat-encoding
129    `#dlti.map` attribute.
130
131    For querying nested dictionaries, the relevant keys need to be separately
132    provided. That is, if `%op` is an handle to an op which has the nesting
133    `#dlti.target_system_spec`-attribute from above attached, then
134    `transform.dlti.query ["CPU","cache","L1","size_in_bytes"] at %op` gives
135    back the first leaf value contained. To access the other leaf, we need to do
136    `transform.dlti.query ["CPU","cache","L1d","size_in_bytes"] at %op`.
137   }];
138  let parameters = (ins
139    ArrayRefParameter<"DataLayoutEntryInterface", "">:$entries
140  );
141  let mnemonic = "map";
142  let genVerifyDecl = 1;
143  let hasCustomAssemblyFormat = 1;
144  let extraClassDeclaration = [{
145    /// Returns the attribute associated with the key.
146    FailureOr<Attribute> query(DataLayoutEntryKey key) {
147      for (DataLayoutEntryInterface entry : getEntries())
148        if (entry.getKey() == key)
149            return entry.getValue();
150      return ::mlir::failure();
151    }
152  }];
153}
154
155//===----------------------------------------------------------------------===//
156// TargetSystemSpecAttr
157//===----------------------------------------------------------------------===//
158
159def DLTI_TargetSystemSpecAttr :
160    DLTIAttr<"TargetSystemSpec", [TargetSystemSpecInterface]> {
161  let summary = "An attribute to represent target system specification.";
162  let description = [{
163    A system specification describes the overall system containing
164    multiple devices, with each device having a unique ID (string)
165    and its corresponding TargetDeviceSpec object.
166
167    Example:
168    ```
169    dlti.target_system_spec =
170     #dlti.target_system_spec<
171      "CPU" = #dlti.target_device_spec<
172        "L1_cache_size_in_bytes" = 4096: ui32>,
173      "GPU" = #dlti.target_device_spec<
174        "max_vector_op_width" = 64 : ui32>,
175      "XPU" = #dlti.target_device_spec<
176        "max_vector_op_width" = 4096 : ui32>>
177    ```
178
179    The verifier checks that keys are strings and pointed to values implement
180    DLTI's TargetDeviceSpecInterface.
181  }];
182  let parameters = (ins
183    ArrayRefParameter<"DataLayoutEntryInterface">:$entries
184  );
185  let mnemonic = "target_system_spec";
186  let genVerifyDecl = 1;
187  let hasCustomAssemblyFormat = 1;
188  let extraClassDeclaration = [{
189    /// Return the device specification that matches the given device ID
190    std::optional<TargetDeviceSpecInterface>
191    getDeviceSpecForDeviceID(
192      TargetSystemSpecInterface::DeviceID deviceID);
193
194    /// Returns the attribute associated with the key.
195    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
196      return ::llvm::cast<mlir::TargetSystemSpecInterface>(*this).queryHelper(key);
197    }
198  }];
199  let extraClassDefinition = [{
200    std::optional<TargetDeviceSpecInterface>
201    $cppClass::getDeviceSpecForDeviceID(
202        TargetSystemSpecInterface::DeviceID deviceID) {
203      for (const auto& entry : getEntries()) {
204        if (entry.getKey() == DataLayoutEntryKey(deviceID))
205          if (auto deviceSpec =
206              ::llvm::dyn_cast<TargetDeviceSpecInterface>(entry.getValue()))
207            return deviceSpec;
208      }
209      return std::nullopt;
210    }
211  }];
212}
213
214//===----------------------------------------------------------------------===//
215// TargetDeviceSpecAttr
216//===----------------------------------------------------------------------===//
217
218def DLTI_TargetDeviceSpecAttr :
219    DLTIAttr<"TargetDeviceSpec", [TargetDeviceSpecInterface]> {
220  let summary = "An attribute to represent target device specification.";
221  let description = [{
222    Each device specification describes a single device and its
223    hardware properties. Each device specification can contain any number
224    of optional hardware properties (e.g., max_vector_op_width below).
225
226    Example:
227    ```
228    #dlti.target_device_spec<"max_vector_op_width" = 64 : ui32>
229    ```
230  }];
231  let parameters = (ins
232    ArrayRefParameter<"DataLayoutEntryInterface">:$entries
233  );
234  let mnemonic = "target_device_spec";
235  let genVerifyDecl = 1;
236  let hasCustomAssemblyFormat = 1;
237
238  let extraClassDeclaration = [{
239    /// Returns the attribute associated with the key.
240    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
241      return ::llvm::cast<mlir::TargetDeviceSpecInterface>(*this).queryHelper(key);
242    }
243  }];
244}
245
246#endif  // MLIR_DIALECT_DLTI_DLTIATTRS_TD
247