MLIR  20.0.0git
DLTI.cpp
Go to the documentation of this file.
1 //===- DLTI.cpp - Data Layout And Target Info MLIR Dialect Implementation -===//
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 
10 #include "mlir/IR/Builders.h"
11 #include "mlir/IR/BuiltinDialect.h"
12 #include "mlir/IR/BuiltinOps.h"
13 #include "mlir/IR/BuiltinTypes.h"
14 #include "mlir/IR/Dialect.h"
16 #include "llvm/ADT/TypeSwitch.h"
17 
18 #include "llvm/ADT/TypeSwitch.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/MathExtras.h"
21 
22 using namespace mlir;
23 
24 #include "mlir/Dialect/DLTI/DLTIDialect.cpp.inc"
25 
26 #define GET_ATTRDEF_CLASSES
27 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
28 
29 #define DEBUG_TYPE "dlti"
30 
31 //===----------------------------------------------------------------------===//
32 // DataLayoutEntryAttr
33 //===----------------------------------------------------------------------===//
34 namespace mlir {
35 namespace detail {
37 public:
38  using KeyTy = std::pair<DataLayoutEntryKey, Attribute>;
39 
42 
44  construct(AttributeStorageAllocator &allocator, const KeyTy &key) {
45  return new (allocator.allocate<DataLayoutEntryAttrStorage>())
46  DataLayoutEntryAttrStorage(key.first, key.second);
47  }
48 
49  bool operator==(const KeyTy &other) const {
50  return other.first == entryKey && other.second == value;
51  }
52 
55 };
56 } // namespace detail
57 } // namespace mlir
58 
59 DataLayoutEntryAttr DataLayoutEntryAttr::get(StringAttr key, Attribute value) {
60  return Base::get(key.getContext(), key, value);
61 }
62 
63 DataLayoutEntryAttr DataLayoutEntryAttr::get(Type key, Attribute value) {
64  return Base::get(key.getContext(), key, value);
65 }
66 
67 DataLayoutEntryKey DataLayoutEntryAttr::getKey() const {
68  return getImpl()->entryKey;
69 }
70 
71 Attribute DataLayoutEntryAttr::getValue() const { return getImpl()->value; }
72 
73 /// Parses an attribute with syntax:
74 /// attr ::= `#target.` `dl_entry` `<` (type | quoted-string) `,` attr `>`
76  if (failed(parser.parseLess()))
77  return {};
78 
79  Type type = nullptr;
80  std::string identifier;
81  SMLoc idLoc = parser.getCurrentLocation();
82  OptionalParseResult parsedType = parser.parseOptionalType(type);
83  if (parsedType.has_value() && failed(parsedType.value()))
84  return {};
85  if (!parsedType.has_value()) {
86  OptionalParseResult parsedString = parser.parseOptionalString(&identifier);
87  if (!parsedString.has_value() || failed(parsedString.value())) {
88  parser.emitError(idLoc) << "expected a type or a quoted string";
89  return {};
90  }
91  }
92 
93  Attribute value;
94  if (failed(parser.parseComma()) || failed(parser.parseAttribute(value)) ||
95  failed(parser.parseGreater()))
96  return {};
97 
98  return type ? get(type, value)
99  : get(parser.getBuilder().getStringAttr(identifier), value);
100 }
101 
102 void DataLayoutEntryAttr::print(AsmPrinter &os) const {
103  os << "<";
104  if (auto type = llvm::dyn_cast_if_present<Type>(getKey()))
105  os << type;
106  else
107  os << "\"" << getKey().get<StringAttr>().strref() << "\"";
108  os << ", " << getValue() << ">";
109 }
110 
111 //===----------------------------------------------------------------------===//
112 // DLTIMapAttr
113 //===----------------------------------------------------------------------===//
114 
117  DenseSet<Type> types;
119  for (DataLayoutEntryInterface entry : entries) {
120  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
121  if (!types.insert(type).second)
122  return emitError() << "repeated layout entry key: " << type;
123  } else {
124  auto id = entry.getKey().get<StringAttr>();
125  if (!ids.insert(id).second)
126  return emitError() << "repeated layout entry key: " << id.getValue();
127  }
128  }
129  return success();
130 }
131 
134  return verifyEntries(emitError, entries);
135 }
136 
137 //===----------------------------------------------------------------------===//
138 // DataLayoutSpecAttr
139 //===----------------------------------------------------------------------===//
140 
141 LogicalResult
144  return verifyEntries(emitError, entries);
145 }
146 
147 /// Given a list of old and a list of new entries, overwrites old entries with
148 /// new ones if they have matching keys, appends new entries to the old entry
149 /// list otherwise.
150 static void
153  unsigned oldEntriesSize = oldEntries.size();
154  for (DataLayoutEntryInterface entry : newEntries) {
155  // We expect a small (dozens) number of entries, so it is practically
156  // cheaper to iterate over the list linearly rather than to create an
157  // auxiliary hashmap to avoid duplication. Also note that we never need to
158  // check for duplicate keys the values that were added from `newEntries`.
159  bool replaced = false;
160  for (unsigned i = 0; i < oldEntriesSize; ++i) {
161  if (oldEntries[i].getKey() == entry.getKey()) {
162  oldEntries[i] = entry;
163  replaced = true;
164  break;
165  }
166  }
167  if (!replaced)
168  oldEntries.push_back(entry);
169  }
170 }
171 
172 /// Combines a data layout spec into the given lists of entries organized by
173 /// type class and identifier, overwriting them if necessary. Fails to combine
174 /// if the two entries with identical keys are not compatible.
175 static LogicalResult
176 combineOneSpec(DataLayoutSpecInterface spec,
179  // A missing spec should be fine.
180  if (!spec)
181  return success();
182 
183  DenseMap<TypeID, DataLayoutEntryList> newEntriesForType;
185  spec.bucketEntriesByType(newEntriesForType, newEntriesForID);
186 
187  // Try overwriting the old entries with the new ones.
188  for (auto &kvp : newEntriesForType) {
189  if (!entriesForType.count(kvp.first)) {
190  entriesForType[kvp.first] = std::move(kvp.second);
191  continue;
192  }
193 
194  Type typeSample = kvp.second.front().getKey().get<Type>();
195  assert(&typeSample.getDialect() !=
196  typeSample.getContext()->getLoadedDialect<BuiltinDialect>() &&
197  "unexpected data layout entry for built-in type");
198 
199  auto interface = llvm::cast<DataLayoutTypeInterface>(typeSample);
200  if (!interface.areCompatible(entriesForType.lookup(kvp.first), kvp.second))
201  return failure();
202 
203  overwriteDuplicateEntries(entriesForType[kvp.first], kvp.second);
204  }
205 
206  for (const auto &kvp : newEntriesForID) {
207  StringAttr id = kvp.second.getKey().get<StringAttr>();
208  Dialect *dialect = id.getReferencedDialect();
209  if (!entriesForID.count(id)) {
210  entriesForID[id] = kvp.second;
211  continue;
212  }
213 
214  // Attempt to combine the enties using the dialect interface. If the
215  // dialect is not loaded for some reason, use the default combinator
216  // that conservatively accepts identical entries only.
217  entriesForID[id] =
218  dialect ? cast<DataLayoutDialectInterface>(dialect)->combine(
219  entriesForID[id], kvp.second)
221  kvp.second);
222  if (!entriesForID[id])
223  return failure();
224  }
225 
226  return success();
227 }
228 
229 DataLayoutSpecAttr
230 DataLayoutSpecAttr::combineWith(ArrayRef<DataLayoutSpecInterface> specs) const {
231  // Only combine with attributes of the same kind.
232  // TODO: reconsider this when the need arises.
233  if (llvm::any_of(specs, [](DataLayoutSpecInterface spec) {
234  return !llvm::isa<DataLayoutSpecAttr>(spec);
235  }))
236  return {};
237 
238  // Combine all specs in order, with `this` being the last one.
241  for (DataLayoutSpecInterface spec : specs)
242  if (failed(combineOneSpec(spec, entriesForType, entriesForID)))
243  return nullptr;
244  if (failed(combineOneSpec(*this, entriesForType, entriesForID)))
245  return nullptr;
246 
247  // Rebuild the linear list of entries.
249  llvm::append_range(entries, llvm::make_second_range(entriesForID));
250  for (const auto &kvp : entriesForType)
251  llvm::append_range(entries, kvp.getSecond());
252 
253  return DataLayoutSpecAttr::get(getContext(), entries);
254 }
255 
256 StringAttr
257 DataLayoutSpecAttr::getEndiannessIdentifier(MLIRContext *context) const {
258  return Builder(context).getStringAttr(DLTIDialect::kDataLayoutEndiannessKey);
259 }
260 
261 StringAttr
262 DataLayoutSpecAttr::getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
263  return Builder(context).getStringAttr(
264  DLTIDialect::kDataLayoutAllocaMemorySpaceKey);
265 }
266 
267 StringAttr DataLayoutSpecAttr::getProgramMemorySpaceIdentifier(
268  MLIRContext *context) const {
269  return Builder(context).getStringAttr(
270  DLTIDialect::kDataLayoutProgramMemorySpaceKey);
271 }
272 
273 StringAttr
274 DataLayoutSpecAttr::getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
275  return Builder(context).getStringAttr(
276  DLTIDialect::kDataLayoutGlobalMemorySpaceKey);
277 }
278 
279 StringAttr
280 DataLayoutSpecAttr::getStackAlignmentIdentifier(MLIRContext *context) const {
281  return Builder(context).getStringAttr(
282  DLTIDialect::kDataLayoutStackAlignmentKey);
283 }
284 
285 /// Parses an attribute with syntax
286 /// attr ::= `#target.` `dl_spec` `<` attr-list? `>`
287 /// attr-list ::= attr
288 /// | attr `,` attr-list
290  if (failed(parser.parseLess()))
291  return {};
292 
293  // Empty spec.
294  if (succeeded(parser.parseOptionalGreater()))
295  return get(parser.getContext(), {});
296 
298  if (parser.parseCommaSeparatedList(
299  [&]() { return parser.parseAttribute(entries.emplace_back()); }) ||
300  parser.parseGreater())
301  return {};
302 
303  return getChecked([&] { return parser.emitError(parser.getNameLoc()); },
304  parser.getContext(), entries);
305 }
306 
307 void DataLayoutSpecAttr::print(AsmPrinter &os) const {
308  os << "<";
309  llvm::interleaveComma(getEntries(), os);
310  os << ">";
311 }
312 
313 //===----------------------------------------------------------------------===//
314 // TargetDeviceSpecAttr
315 //===----------------------------------------------------------------------===//
316 
317 namespace mlir {
318 /// A FieldParser for key-value pairs of DeviceID-target device spec pairs that
319 /// make up a target system spec.
320 template <>
322  static FailureOr<DeviceIDTargetDeviceSpecPair> parse(AsmParser &parser) {
323  std::string deviceID;
324 
325  if (failed(parser.parseString(&deviceID))) {
326  parser.emitError(parser.getCurrentLocation())
327  << "DeviceID is missing, or is not of string type";
328  return failure();
329  }
330 
331  if (failed(parser.parseColon())) {
332  parser.emitError(parser.getCurrentLocation()) << "Missing colon";
333  return failure();
334  }
335 
336  auto target_device_spec =
338  if (failed(target_device_spec)) {
339  parser.emitError(parser.getCurrentLocation())
340  << "Error in parsing target device spec";
341  return failure();
342  }
343 
344  return std::make_pair(parser.getBuilder().getStringAttr(deviceID),
345  *target_device_spec);
346  }
347 };
348 
351  return printer << param.first << " : " << param.second;
352 }
353 
354 } // namespace mlir
355 
356 LogicalResult
359  // Entries in a target device spec can only have StringAttr as key. It does
360  // not support type as a key. Hence not reusing
361  // DataLayoutEntryInterface::verify.
363  for (DataLayoutEntryInterface entry : entries) {
364  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey())) {
365  return emitError()
366  << "dlti.target_device_spec does not allow type as a key: "
367  << type;
368  } else {
369  // Check that keys in a target device spec are unique.
370  auto id = entry.getKey().get<StringAttr>();
371  if (!ids.insert(id).second)
372  return emitError() << "repeated layout entry key: " << id.getValue();
373  }
374  }
375 
376  return success();
377 }
378 
379 //===----------------------------------------------------------------------===//
380 // TargetSystemSpecAttr
381 //===----------------------------------------------------------------------===//
382 
383 LogicalResult
387 
388  for (const auto &entry : entries) {
389  TargetDeviceSpecInterface target_device_spec = entry.second;
390 
391  // First verify that a target device spec is valid.
393  target_device_spec.getEntries())))
394  return failure();
395 
396  // Check that device IDs are unique across all entries.
397  TargetSystemSpecInterface::DeviceID device_id = entry.first;
398  if (!device_ids.insert(device_id).second) {
399  return emitError() << "repeated Device ID in dlti.target_system_spec: "
400  << device_id;
401  }
402  }
403  return success();
404 }
405 
406 //===----------------------------------------------------------------------===//
407 // DLTIDialect
408 //===----------------------------------------------------------------------===//
409 
410 /// Retrieve the first `DLTIQueryInterface`-implementing attribute that is
411 /// attached to `op` or such an attr on as close as possible an ancestor. The
412 /// op the attribute is attached to is returned as well.
413 static std::pair<DLTIQueryInterface, Operation *>
415  DLTIQueryInterface queryable = {};
416 
417  // Search op and its ancestors for the first attached DLTIQueryInterface attr.
418  do {
419  for (NamedAttribute attr : op->getAttrs())
420  if ((queryable = llvm::dyn_cast<DLTIQueryInterface>(attr.getValue())))
421  break;
422  } while (!queryable && (op = op->getParentOp()));
423 
424  return std::pair(queryable, op);
425 }
426 
427 FailureOr<Attribute>
429  if (keys.empty()) {
430  if (emitError) {
431  auto diag = op->emitError() << "target op of failed DLTI query";
432  diag.attachNote(op->getLoc()) << "no keys provided to attempt query with";
433  }
434  return failure();
435  }
436 
437  auto [queryable, queryOp] = getClosestQueryable(op);
438  Operation *reportOp = (queryOp ? queryOp : op);
439 
440  if (!queryable) {
441  if (emitError) {
442  auto diag = op->emitError() << "target op of failed DLTI query";
443  diag.attachNote(reportOp->getLoc())
444  << "no DLTI-queryable attrs on target op or any of its ancestors";
445  }
446  return failure();
447  }
448 
449  auto keyToStr = [](DataLayoutEntryKey key) -> std::string {
450  std::string buf;
452  .Case<StringAttr, Type>( // The only two kinds of key we know of.
453  [&](auto key) { llvm::raw_string_ostream(buf) << key; })
454  .Default([](auto) { llvm_unreachable("unexpected entry key kind"); });
455  return buf;
456  };
457 
458  Attribute currentAttr = queryable;
459  for (auto &&[idx, key] : llvm::enumerate(keys)) {
460  if (auto map = llvm::dyn_cast<DLTIQueryInterface>(currentAttr)) {
461  auto maybeAttr = map.query(key);
462  if (failed(maybeAttr)) {
463  if (emitError) {
464  auto diag = op->emitError() << "target op of failed DLTI query";
465  diag.attachNote(reportOp->getLoc())
466  << "key " << keyToStr(key)
467  << " has no DLTI-mapping per attr: " << map;
468  }
469  return failure();
470  }
471  currentAttr = *maybeAttr;
472  } else {
473  if (emitError) {
474  std::string commaSeparatedKeys;
475  llvm::interleave(
476  keys.take_front(idx), // All prior keys.
477  [&](auto key) { commaSeparatedKeys += keyToStr(key); },
478  [&]() { commaSeparatedKeys += ","; });
479 
480  auto diag = op->emitError() << "target op of failed DLTI query";
481  diag.attachNote(reportOp->getLoc())
482  << "got non-DLTI-queryable attribute upon looking up keys ["
483  << commaSeparatedKeys << "] at op";
484  }
485  return failure();
486  }
487  }
488 
489  return currentAttr;
490 }
491 
492 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutAttrName;
493 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessKey;
494 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessBig;
495 constexpr const StringLiteral mlir::DLTIDialect::kDataLayoutEndiannessLittle;
496 
497 namespace {
498 class TargetDataLayoutInterface : public DataLayoutDialectInterface {
499 public:
501 
502  LogicalResult verifyEntry(DataLayoutEntryInterface entry,
503  Location loc) const final {
504  StringRef entryName = entry.getKey().get<StringAttr>().strref();
505  if (entryName == DLTIDialect::kDataLayoutEndiannessKey) {
506  auto value = llvm::dyn_cast<StringAttr>(entry.getValue());
507  if (value &&
508  (value.getValue() == DLTIDialect::kDataLayoutEndiannessBig ||
509  value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle))
510  return success();
511  return emitError(loc) << "'" << entryName
512  << "' data layout entry is expected to be either '"
513  << DLTIDialect::kDataLayoutEndiannessBig << "' or '"
514  << DLTIDialect::kDataLayoutEndiannessLittle << "'";
515  }
516  if (entryName == DLTIDialect::kDataLayoutAllocaMemorySpaceKey ||
517  entryName == DLTIDialect::kDataLayoutProgramMemorySpaceKey ||
518  entryName == DLTIDialect::kDataLayoutGlobalMemorySpaceKey ||
519  entryName == DLTIDialect::kDataLayoutStackAlignmentKey)
520  return success();
521  return emitError(loc) << "unknown data layout entry name: " << entryName;
522  }
523 };
524 } // namespace
525 
526 void DLTIDialect::initialize() {
527  addAttributes<
528 #define GET_ATTRDEF_LIST
529 #include "mlir/Dialect/DLTI/DLTIAttrs.cpp.inc"
530  >();
531  addInterfaces<TargetDataLayoutInterface>();
532 }
533 
534 LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op,
535  NamedAttribute attr) {
536  if (attr.getName() == DLTIDialect::kDataLayoutAttrName) {
537  if (!llvm::isa<DataLayoutSpecAttr>(attr.getValue())) {
538  return op->emitError() << "'" << DLTIDialect::kDataLayoutAttrName
539  << "' is expected to be a #dlti.dl_spec attribute";
540  }
541  if (isa<ModuleOp>(op))
542  return detail::verifyDataLayoutOp(op);
543  return success();
544  }
545 
546  if (attr.getName() == DLTIDialect::kTargetSystemDescAttrName) {
547  if (!llvm::isa<TargetSystemSpecAttr>(attr.getValue())) {
548  return op->emitError()
549  << "'" << DLTIDialect::kTargetSystemDescAttrName
550  << "' is expected to be a #dlti.target_system_spec attribute";
551  }
552  return success();
553  }
554 
555  if (attr.getName() == DLTIDialect::kMapAttrName) {
556  if (!llvm::isa<MapAttr>(attr.getValue())) {
557  return op->emitError() << "'" << DLTIDialect::kMapAttrName
558  << "' is expected to be a #dlti.map attribute";
559  }
560  return success();
561  }
562 
563  return op->emitError() << "attribute '" << attr.getName().getValue()
564  << "' not supported by dialect";
565 }
static std::pair< DLTIQueryInterface, Operation * > getClosestQueryable(Operation *op)
Retrieve the first DLTIQueryInterface-implementing attribute that is attached to op or such an attr o...
Definition: DLTI.cpp:414
static LogicalResult combineOneSpec(DataLayoutSpecInterface spec, DenseMap< TypeID, DataLayoutEntryList > &entriesForType, DenseMap< StringAttr, DataLayoutEntryInterface > &entriesForID)
Combines a data layout spec into the given lists of entries organized by type class and identifier,...
Definition: DLTI.cpp:176
static void overwriteDuplicateEntries(SmallVectorImpl< DataLayoutEntryInterface > &oldEntries, ArrayRef< DataLayoutEntryInterface > newEntries)
Given a list of old and a list of new entries, overwrites old entries with new ones if they have matc...
Definition: DLTI.cpp:151
static LogicalResult verifyEntries(function_ref< InFlightDiagnostic()> emitError, ArrayRef< DataLayoutEntryInterface > entries)
Definition: DLTI.cpp:115
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual OptionalParseResult parseOptionalType(Type &result)=0
Parse an optional type.
MLIRContext * getContext() const
Definition: AsmPrinter.cpp:73
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLess()=0
Parse a '<' token.
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalGreater()=0
Parse a '>' token if present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalString(std::string *string)=0
Parse a quoted string token if present.
virtual ParseResult parseGreater()=0
Parse a '>' token.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
Base storage class appearing in an attribute.
Attributes are known-constant values of operations.
Definition: Attributes.h:25
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:281
An interface to be implemented by dialects that can have identifiers in the data layout specification...
static DataLayoutEntryInterface defaultCombine(DataLayoutEntryInterface outer, DataLayoutEntryInterface inner)
Default implementation of entry combination that combines identical entries and returns null otherwis...
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:38
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:313
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:207
StringAttr getName() const
Return the name of the attribute.
Definition: Attributes.cpp:49
Attribute getValue() const
Return the value of the attribute.
Definition: Attributes.h:221
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:223
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:234
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition: Operation.h:507
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:268
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:39
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:52
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:49
This is a utility allocator used to allocate memory for instances of derived types.
T * allocate()
Allocate an instance of the provided type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
Dialect & getDialect() const
Get the dialect this type is registered to.
Definition: Types.h:123
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
DataLayoutEntryAttrStorage(DataLayoutEntryKey entryKey, Attribute value)
Definition: DLTI.cpp:40
bool operator==(const KeyTy &other) const
Definition: DLTI.cpp:49
std::pair< DataLayoutEntryKey, Attribute > KeyTy
Definition: DLTI.cpp:38
static DataLayoutEntryAttrStorage * construct(AttributeStorageAllocator &allocator, const KeyTy &key)
Definition: DLTI.cpp:44
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Definition: Matchers.h:344
LogicalResult verifyDataLayoutOp(Operation *op)
Verifies that the operation implementing the data layout interface, or a module operation,...
FailureOr< Attribute > query(Operation *op, ArrayRef< DataLayoutEntryKey > keys, bool emitError=false)
Perform a DLTI-query at op, recursively querying each key of keys on query interface-implementing att...
Definition: DLTI.cpp:428
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Definition: Query.cpp:20
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
std::pair< StringAttr, TargetDeviceSpecInterface > DeviceIDTargetDeviceSpecPair
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:426
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
static FailureOr< DeviceIDTargetDeviceSpecPair > parse(AsmParser &parser)
Definition: DLTI.cpp:322
Provide a template class that can be specialized by users to dispatch to parsers.