MLIR  18.0.0git
DataLayoutInterfaces.cpp
Go to the documentation of this file.
1 //===- DataLayoutInterfaces.cpp - Data Layout Interface 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/BuiltinDialect.h"
11 #include "mlir/IR/BuiltinOps.h"
12 #include "mlir/IR/BuiltinTypes.h"
13 #include "mlir/IR/Operation.h"
14 
15 #include "llvm/ADT/TypeSwitch.h"
16 #include "llvm/Support/MathExtras.h"
17 
18 using namespace mlir;
19 
20 //===----------------------------------------------------------------------===//
21 // Default implementations
22 //===----------------------------------------------------------------------===//
23 
24 /// Reports that the given type is missing the data layout information and
25 /// exits.
26 [[noreturn]] static void reportMissingDataLayout(Type type) {
27  std::string message;
28  llvm::raw_string_ostream os(message);
29  os << "neither the scoping op nor the type class provide data layout "
30  "information for "
31  << type;
32  llvm::report_fatal_error(Twine(os.str()));
33 }
34 
35 /// Returns the bitwidth of the index type if specified in the param list.
36 /// Assumes 64-bit index otherwise.
37 static uint64_t getIndexBitwidth(DataLayoutEntryListRef params) {
38  if (params.empty())
39  return 64;
40  auto attr = cast<IntegerAttr>(params.front().getValue());
41  return attr.getValue().getZExtValue();
42 }
43 
44 llvm::TypeSize
47  llvm::TypeSize bits = getDefaultTypeSizeInBits(type, dataLayout, params);
48  return divideCeil(bits, 8);
49 }
50 
51 llvm::TypeSize
53  DataLayoutEntryListRef params) {
54  if (isa<IntegerType, FloatType>(type))
55  return llvm::TypeSize::getFixed(type.getIntOrFloatBitWidth());
56 
57  if (auto ctype = dyn_cast<ComplexType>(type)) {
58  Type et = ctype.getElementType();
59  uint64_t innerAlignment =
60  getDefaultPreferredAlignment(et, dataLayout, params) * 8;
61  llvm::TypeSize innerSize = getDefaultTypeSizeInBits(et, dataLayout, params);
62 
63  // Include padding required to align the imaginary value in the complex
64  // type.
65  return llvm::alignTo(innerSize, innerAlignment) + innerSize;
66  }
67 
68  // Index is an integer of some bitwidth.
69  if (isa<IndexType>(type))
70  return dataLayout.getTypeSizeInBits(
72 
73  // Sizes of vector types are rounded up to those of types with closest
74  // power-of-two number of elements in the innermost dimension. We also assume
75  // there is no bit-packing at the moment element sizes are taken in bytes and
76  // multiplied with 8 bits.
77  // TODO: make this extensible.
78  if (auto vecType = dyn_cast<VectorType>(type))
79  return vecType.getNumElements() / vecType.getShape().back() *
80  llvm::PowerOf2Ceil(vecType.getShape().back()) *
81  dataLayout.getTypeSize(vecType.getElementType()) * 8;
82 
83  if (auto typeInterface = dyn_cast<DataLayoutTypeInterface>(type))
84  return typeInterface.getTypeSizeInBits(dataLayout, params);
85 
87 }
88 
89 static DataLayoutEntryInterface
90 findEntryForIntegerType(IntegerType intType,
92  assert(!params.empty() && "expected non-empty parameter list");
93  std::map<unsigned, DataLayoutEntryInterface> sortedParams;
94  for (DataLayoutEntryInterface entry : params) {
95  sortedParams.insert(std::make_pair(
96  entry.getKey().get<Type>().getIntOrFloatBitWidth(), entry));
97  }
98  auto iter = sortedParams.lower_bound(intType.getWidth());
99  if (iter == sortedParams.end())
100  iter = std::prev(iter);
101 
102  return iter->second;
103 }
104 
105 constexpr const static uint64_t kDefaultBitsInByte = 8u;
106 
107 static uint64_t extractABIAlignment(DataLayoutEntryInterface entry) {
108  auto values =
109  cast<DenseIntElementsAttr>(entry.getValue()).getValues<uint64_t>();
110  return static_cast<uint64_t>(*values.begin()) / kDefaultBitsInByte;
111 }
112 
113 static uint64_t
114 getIntegerTypeABIAlignment(IntegerType intType,
116  constexpr uint64_t kDefaultSmallIntAlignment = 4u;
117  constexpr unsigned kSmallIntSize = 64;
118  if (params.empty()) {
119  return intType.getWidth() < kSmallIntSize
120  ? llvm::PowerOf2Ceil(
121  llvm::divideCeil(intType.getWidth(), kDefaultBitsInByte))
122  : kDefaultSmallIntAlignment;
123  }
124 
125  return extractABIAlignment(findEntryForIntegerType(intType, params));
126 }
127 
128 static uint64_t
129 getFloatTypeABIAlignment(FloatType fltType, const DataLayout &dataLayout,
131  assert(params.size() <= 1 && "at most one data layout entry is expected for "
132  "the singleton floating-point type");
133  if (params.empty())
134  return llvm::PowerOf2Ceil(dataLayout.getTypeSize(fltType).getFixedValue());
135  return extractABIAlignment(params[0]);
136 }
137 
139  Type type, const DataLayout &dataLayout,
141  // Natural alignment is the closest power-of-two number above.
142  if (isa<VectorType>(type))
143  return llvm::PowerOf2Ceil(dataLayout.getTypeSize(type));
144 
145  if (auto fltType = dyn_cast<FloatType>(type))
146  return getFloatTypeABIAlignment(fltType, dataLayout, params);
147 
148  // Index is an integer of some bitwidth.
149  if (isa<IndexType>(type))
150  return dataLayout.getTypeABIAlignment(
151  IntegerType::get(type.getContext(), getIndexBitwidth(params)));
152 
153  if (auto intType = dyn_cast<IntegerType>(type))
154  return getIntegerTypeABIAlignment(intType, params);
155 
156  if (auto ctype = dyn_cast<ComplexType>(type))
157  return getDefaultABIAlignment(ctype.getElementType(), dataLayout, params);
158 
159  if (auto typeInterface = dyn_cast<DataLayoutTypeInterface>(type))
160  return typeInterface.getABIAlignment(dataLayout, params);
161 
163 }
164 
165 static uint64_t extractPreferredAlignment(DataLayoutEntryInterface entry) {
166  auto values =
167  cast<DenseIntElementsAttr>(entry.getValue()).getValues<uint64_t>();
168  return *std::next(values.begin(), values.size() - 1) / kDefaultBitsInByte;
169 }
170 
171 static uint64_t
173  const DataLayout &dataLayout,
175  if (params.empty())
176  return llvm::PowerOf2Ceil(dataLayout.getTypeSize(intType).getFixedValue());
177 
178  return extractPreferredAlignment(findEntryForIntegerType(intType, params));
179 }
180 
181 static uint64_t
184  assert(params.size() <= 1 && "at most one data layout entry is expected for "
185  "the singleton floating-point type");
186  if (params.empty())
187  return dataLayout.getTypeABIAlignment(fltType);
188  return extractPreferredAlignment(params[0]);
189 }
190 
192  Type type, const DataLayout &dataLayout,
194  // Preferred alignment is same as natural for floats and vectors.
195  if (isa<VectorType>(type))
196  return dataLayout.getTypeABIAlignment(type);
197 
198  if (auto fltType = dyn_cast<FloatType>(type))
199  return getFloatTypePreferredAlignment(fltType, dataLayout, params);
200 
201  // Preferred alignment is the closest power-of-two number above for integers
202  // (ABI alignment may be smaller).
203  if (auto intType = dyn_cast<IntegerType>(type))
204  return getIntegerTypePreferredAlignment(intType, dataLayout, params);
205 
206  if (isa<IndexType>(type)) {
207  return dataLayout.getTypePreferredAlignment(
208  IntegerType::get(type.getContext(), getIndexBitwidth(params)));
209  }
210 
211  if (auto ctype = dyn_cast<ComplexType>(type))
212  return getDefaultPreferredAlignment(ctype.getElementType(), dataLayout,
213  params);
214 
215  if (auto typeInterface = dyn_cast<DataLayoutTypeInterface>(type))
216  return typeInterface.getPreferredAlignment(dataLayout, params);
217 
219 }
220 
221 // Returns the memory space used for allocal operations if specified in the
222 // given entry. If the entry is empty the default memory space represented by
223 // an empty attribute is returned.
224 Attribute
225 mlir::detail::getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry) {
226  if (entry == DataLayoutEntryInterface()) {
227  return Attribute();
228  }
229 
230  return entry.getValue();
231 }
232 
233 // Returns the stack alignment if specified in the given entry. If the entry is
234 // empty the default alignment zero is returned.
235 uint64_t
236 mlir::detail::getDefaultStackAlignment(DataLayoutEntryInterface entry) {
237  if (entry == DataLayoutEntryInterface())
238  return 0;
239 
240  auto value = cast<IntegerAttr>(entry.getValue());
241  return value.getValue().getZExtValue();
242 }
243 
246  TypeID typeID) {
247  return llvm::to_vector<4>(llvm::make_filter_range(
248  entries, [typeID](DataLayoutEntryInterface entry) {
249  auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
250  return type && type.getTypeID() == typeID;
251  }));
252 }
253 
254 DataLayoutEntryInterface
256  StringAttr id) {
257  const auto *it = llvm::find_if(entries, [id](DataLayoutEntryInterface entry) {
258  if (!entry.getKey().is<StringAttr>())
259  return false;
260  return entry.getKey().get<StringAttr>() == id;
261  });
262  return it == entries.end() ? DataLayoutEntryInterface() : *it;
263 }
264 
265 static DataLayoutSpecInterface getSpec(Operation *operation) {
267  .Case<ModuleOp, DataLayoutOpInterface>(
268  [&](auto op) { return op.getDataLayoutSpec(); })
269  .Default([](Operation *) {
270  llvm_unreachable("expected an op with data layout spec");
271  return DataLayoutSpecInterface();
272  });
273 }
274 
275 /// Populates `opsWithLayout` with the list of proper ancestors of `leaf` that
276 /// are either modules or implement the `DataLayoutOpInterface`.
277 static void
280  SmallVectorImpl<Location> *opLocations = nullptr) {
281  if (!leaf)
282  return;
283 
284  for (Operation *parent = leaf->getParentOp(); parent != nullptr;
285  parent = parent->getParentOp()) {
287  .Case<ModuleOp>([&](ModuleOp op) {
288  // Skip top-level module op unless it has a layout. Top-level module
289  // without layout is most likely the one implicitly added by the
290  // parser and it doesn't have location. Top-level null specification
291  // would have had the same effect as not having a specification at all
292  // (using type defaults).
293  if (!op->getParentOp() && !op.getDataLayoutSpec())
294  return;
295  specs.push_back(op.getDataLayoutSpec());
296  if (opLocations)
297  opLocations->push_back(op.getLoc());
298  })
299  .Case<DataLayoutOpInterface>([&](DataLayoutOpInterface op) {
300  specs.push_back(op.getDataLayoutSpec());
301  if (opLocations)
302  opLocations->push_back(op.getLoc());
303  });
304  }
305 }
306 
307 /// Returns a layout spec that is a combination of the layout specs attached
308 /// to the given operation and all its ancestors.
309 static DataLayoutSpecInterface getCombinedDataLayout(Operation *leaf) {
310  if (!leaf)
311  return {};
312 
313  assert((isa<ModuleOp, DataLayoutOpInterface>(leaf)) &&
314  "expected an op with data layout spec");
315 
318  collectParentLayouts(leaf, specs);
319 
320  // Fast track if there are no ancestors.
321  if (specs.empty())
322  return getSpec(leaf);
323 
324  // Create the list of non-null specs (null/missing specs can be safely
325  // ignored) from the outermost to the innermost.
326  auto nonNullSpecs = llvm::to_vector<2>(llvm::make_filter_range(
327  llvm::reverse(specs),
328  [](DataLayoutSpecInterface iface) { return iface != nullptr; }));
329 
330  // Combine the specs using the innermost as anchor.
331  if (DataLayoutSpecInterface current = getSpec(leaf))
332  return current.combineWith(nonNullSpecs);
333  if (nonNullSpecs.empty())
334  return {};
335  return nonNullSpecs.back().combineWith(
336  llvm::ArrayRef(nonNullSpecs).drop_back());
337 }
338 
340  DataLayoutSpecInterface spec = getSpec(op);
341  // The layout specification may be missing and it's fine.
342  if (!spec)
343  return success();
344 
345  if (failed(spec.verifySpec(op->getLoc())))
346  return failure();
347  if (!getCombinedDataLayout(op)) {
349  op->emitError()
350  << "data layout does not combine with layouts of enclosing ops";
352  SmallVector<Location> opLocations;
353  collectParentLayouts(op, specs, &opLocations);
354  for (Location loc : opLocations)
355  diag.attachNote(loc) << "enclosing op with data layout";
356  return diag;
357  }
358  return success();
359 }
360 
361 llvm::TypeSize mlir::detail::divideCeil(llvm::TypeSize numerator,
362  uint64_t denominator) {
363  uint64_t divided =
364  llvm::divideCeil(numerator.getKnownMinValue(), denominator);
365  return llvm::TypeSize::get(divided, numerator.isScalable());
366 }
367 
368 //===----------------------------------------------------------------------===//
369 // DataLayout
370 //===----------------------------------------------------------------------===//
371 
372 template <typename OpTy>
373 void checkMissingLayout(DataLayoutSpecInterface originalLayout, OpTy op) {
374  if (!originalLayout) {
375  assert((!op || !op.getDataLayoutSpec()) &&
376  "could not compute layout information for an op (failed to "
377  "combine attributes?)");
378  }
379 }
380 
382 
383 mlir::DataLayout::DataLayout(DataLayoutOpInterface op)
384  : originalLayout(getCombinedDataLayout(op)), scope(op),
385  allocaMemorySpace(std::nullopt), stackAlignment(std::nullopt) {
386 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
387  checkMissingLayout(originalLayout, op);
388  collectParentLayouts(op, layoutStack);
389 #endif
390 }
391 
393  : originalLayout(getCombinedDataLayout(op)), scope(op),
394  allocaMemorySpace(std::nullopt), stackAlignment(std::nullopt) {
395 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
396  checkMissingLayout(originalLayout, op);
397  collectParentLayouts(op, layoutStack);
398 #endif
399 }
400 
402  // Search the closest parent either being a module operation or implementing
403  // the data layout interface.
404  while (op) {
405  if (auto module = dyn_cast<ModuleOp>(op))
406  return DataLayout(module);
407  if (auto iface = dyn_cast<DataLayoutOpInterface>(op))
408  return DataLayout(iface);
409  op = op->getParentOp();
410  }
411  return DataLayout();
412 }
413 
414 void mlir::DataLayout::checkValid() const {
415 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
417  collectParentLayouts(scope, specs);
418  assert(specs.size() == layoutStack.size() &&
419  "data layout object used, but no longer valid due to the change in "
420  "number of nested layouts");
421  for (auto pair : llvm::zip(specs, layoutStack)) {
422  Attribute newLayout = std::get<0>(pair);
423  Attribute origLayout = std::get<1>(pair);
424  assert(newLayout == origLayout &&
425  "data layout object used, but no longer valid "
426  "due to the change in layout attributes");
427  }
428 #endif
429  assert(((!scope && !this->originalLayout) ||
430  (scope && this->originalLayout == getCombinedDataLayout(scope))) &&
431  "data layout object used, but no longer valid due to the change in "
432  "layout spec");
433 }
434 
435 /// Looks up the value for the given type key in the given cache. If there is no
436 /// such value in the cache, compute it using the given callback and put it in
437 /// the cache before returning.
438 template <typename T>
440  function_ref<T(Type)> compute) {
441  auto it = cache.find(t);
442  if (it != cache.end())
443  return it->second;
444 
445  auto result = cache.try_emplace(t, compute(t));
446  return result.first->second;
447 }
448 
449 llvm::TypeSize mlir::DataLayout::getTypeSize(Type t) const {
450  checkValid();
451  return cachedLookup<llvm::TypeSize>(t, sizes, [&](Type ty) {
452  DataLayoutEntryList list;
453  if (originalLayout)
454  list = originalLayout.getSpecForType(ty.getTypeID());
455  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
456  return iface.getTypeSize(ty, *this, list);
457  return detail::getDefaultTypeSize(ty, *this, list);
458  });
459 }
460 
461 llvm::TypeSize mlir::DataLayout::getTypeSizeInBits(Type t) const {
462  checkValid();
463  return cachedLookup<llvm::TypeSize>(t, bitsizes, [&](Type ty) {
464  DataLayoutEntryList list;
465  if (originalLayout)
466  list = originalLayout.getSpecForType(ty.getTypeID());
467  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
468  return iface.getTypeSizeInBits(ty, *this, list);
469  return detail::getDefaultTypeSizeInBits(ty, *this, list);
470  });
471 }
472 
474  checkValid();
475  return cachedLookup<uint64_t>(t, abiAlignments, [&](Type ty) {
476  DataLayoutEntryList list;
477  if (originalLayout)
478  list = originalLayout.getSpecForType(ty.getTypeID());
479  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
480  return iface.getTypeABIAlignment(ty, *this, list);
481  return detail::getDefaultABIAlignment(ty, *this, list);
482  });
483 }
484 
486  checkValid();
487  return cachedLookup<uint64_t>(t, preferredAlignments, [&](Type ty) {
488  DataLayoutEntryList list;
489  if (originalLayout)
490  list = originalLayout.getSpecForType(ty.getTypeID());
491  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
492  return iface.getTypePreferredAlignment(ty, *this, list);
493  return detail::getDefaultPreferredAlignment(ty, *this, list);
494  });
495 }
496 
498  checkValid();
499  if (allocaMemorySpace)
500  return *allocaMemorySpace;
501  DataLayoutEntryInterface entry;
502  if (originalLayout)
503  entry = originalLayout.getSpecForIdentifier(
504  originalLayout.getAllocaMemorySpaceIdentifier(
505  originalLayout.getContext()));
506  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
507  allocaMemorySpace = iface.getAllocaMemorySpace(entry);
508  else
509  allocaMemorySpace = detail::getDefaultAllocaMemorySpace(entry);
510  return *allocaMemorySpace;
511 }
512 
514  checkValid();
515  if (stackAlignment)
516  return *stackAlignment;
517  DataLayoutEntryInterface entry;
518  if (originalLayout)
519  entry = originalLayout.getSpecForIdentifier(
520  originalLayout.getStackAlignmentIdentifier(
521  originalLayout.getContext()));
522  if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope))
523  stackAlignment = iface.getStackAlignment(entry);
524  else
525  stackAlignment = detail::getDefaultStackAlignment(entry);
526  return *stackAlignment;
527 }
528 
529 //===----------------------------------------------------------------------===//
530 // DataLayoutSpecInterface
531 //===----------------------------------------------------------------------===//
532 
533 void DataLayoutSpecInterface::bucketEntriesByType(
536  for (DataLayoutEntryInterface entry : getEntries()) {
537  if (auto type = llvm::dyn_cast_if_present<Type>(entry.getKey()))
538  types[type.getTypeID()].push_back(entry);
539  else
540  ids[entry.getKey().get<StringAttr>()] = entry;
541  }
542 }
543 
545  Location loc) {
546  // First, verify individual entries.
547  for (DataLayoutEntryInterface entry : spec.getEntries())
548  if (failed(entry.verifyEntry(loc)))
549  return failure();
550 
551  // Second, dispatch verifications of entry groups to types or dialects they
552  // are associated with.
555  spec.bucketEntriesByType(types, ids);
556 
557  for (const auto &kvp : types) {
558  auto sampleType = kvp.second.front().getKey().get<Type>();
559  if (isa<IndexType>(sampleType)) {
560  assert(kvp.second.size() == 1 &&
561  "expected one data layout entry for non-parametric 'index' type");
562  if (!isa<IntegerAttr>(kvp.second.front().getValue()))
563  return emitError(loc)
564  << "expected integer attribute in the data layout entry for "
565  << sampleType;
566  continue;
567  }
568 
569  if (isa<IntegerType, FloatType>(sampleType)) {
570  for (DataLayoutEntryInterface entry : kvp.second) {
571  auto value = dyn_cast<DenseIntElementsAttr>(entry.getValue());
572  if (!value || !value.getElementType().isSignlessInteger(64)) {
573  emitError(loc) << "expected a dense i64 elements attribute in the "
574  "data layout entry "
575  << entry;
576  return failure();
577  }
578 
579  auto elements = llvm::to_vector<2>(value.getValues<uint64_t>());
580  unsigned numElements = elements.size();
581  if (numElements < 1 || numElements > 2) {
582  emitError(loc) << "expected 1 or 2 elements in the data layout entry "
583  << entry;
584  return failure();
585  }
586 
587  uint64_t abi = elements[0];
588  uint64_t preferred = numElements == 2 ? elements[1] : abi;
589  if (preferred < abi) {
590  emitError(loc)
591  << "preferred alignment is expected to be greater than or equal "
592  "to the abi alignment in data layout entry "
593  << entry;
594  return failure();
595  }
596  }
597  continue;
598  }
599 
600  if (isa<BuiltinDialect>(&sampleType.getDialect()))
601  return emitError(loc) << "unexpected data layout for a built-in type";
602 
603  auto dlType = dyn_cast<DataLayoutTypeInterface>(sampleType);
604  if (!dlType)
605  return emitError(loc)
606  << "data layout specified for a type that does not support it";
607  if (failed(dlType.verifyEntries(kvp.second, loc)))
608  return failure();
609  }
610 
611  for (const auto &kvp : ids) {
612  StringAttr identifier = kvp.second.getKey().get<StringAttr>();
613  Dialect *dialect = identifier.getReferencedDialect();
614 
615  // Ignore attributes that belong to an unknown dialect, the dialect may
616  // actually implement the relevant interface but we don't know about that.
617  if (!dialect)
618  continue;
619 
620  const auto *iface = dyn_cast<DataLayoutDialectInterface>(dialect);
621  if (!iface) {
622  return emitError(loc)
623  << "the '" << dialect->getNamespace()
624  << "' dialect does not support identifier data layout entries";
625  }
626  if (failed(iface->verifyEntry(kvp.second, loc)))
627  return failure();
628  }
629 
630  return success();
631 }
632 
633 #include "mlir/Interfaces/DataLayoutAttrInterface.cpp.inc"
634 #include "mlir/Interfaces/DataLayoutOpInterface.cpp.inc"
635 #include "mlir/Interfaces/DataLayoutTypeInterface.cpp.inc"
static uint64_t getIntegerTypePreferredAlignment(IntegerType intType, const DataLayout &dataLayout, ArrayRef< DataLayoutEntryInterface > params)
static DataLayoutSpecInterface getCombinedDataLayout(Operation *leaf)
Returns a layout spec that is a combination of the layout specs attached to the given operation and a...
constexpr static const uint64_t kDefaultBitsInByte
static uint64_t getIntegerTypeABIAlignment(IntegerType intType, ArrayRef< DataLayoutEntryInterface > params)
static T cachedLookup(Type t, DenseMap< Type, T > &cache, function_ref< T(Type)> compute)
Looks up the value for the given type key in the given cache.
static uint64_t extractPreferredAlignment(DataLayoutEntryInterface entry)
static void collectParentLayouts(Operation *leaf, SmallVectorImpl< DataLayoutSpecInterface > &specs, SmallVectorImpl< Location > *opLocations=nullptr)
Populates opsWithLayout with the list of proper ancestors of leaf that are either modules or implemen...
static uint64_t getFloatTypePreferredAlignment(FloatType fltType, const DataLayout &dataLayout, ArrayRef< DataLayoutEntryInterface > params)
static uint64_t getFloatTypeABIAlignment(FloatType fltType, const DataLayout &dataLayout, ArrayRef< DataLayoutEntryInterface > params)
static DataLayoutSpecInterface getSpec(Operation *operation)
static uint64_t getIndexBitwidth(DataLayoutEntryListRef params)
Returns the bitwidth of the index type if specified in the param list.
static uint64_t extractABIAlignment(DataLayoutEntryInterface entry)
static DataLayoutEntryInterface findEntryForIntegerType(IntegerType intType, ArrayRef< DataLayoutEntryInterface > params)
void checkMissingLayout(DataLayoutSpecInterface originalLayout, OpTy op)
static void reportMissingDataLayout(Type type)
Reports that the given type is missing the data layout information and exits.
static std::string diag(const llvm::Value &value)
Attributes are known-constant values of operations.
Definition: Attributes.h:25
The main mechanism for performing data layout queries.
Attribute getAllocaMemorySpace() const
Returns the memory space used for AllocaOps.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
uint64_t getStackAlignment() const
Returns the natural alignment of the stack in bits.
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:308
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
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
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:267
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:35
TypeID getTypeID()
Return a unique identifier for the concrete type.
Definition: Types.h:112
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition: Types.cpp:123
Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry)
Default handler for alloca memory space request.
DataLayoutEntryList filterEntriesForType(DataLayoutEntryListRef entries, TypeID typeID)
Given a list of data layout entries, returns a new list containing the entries with keys having the g...
uint64_t getDefaultABIAlignment(Type type, const DataLayout &dataLayout, ArrayRef< DataLayoutEntryInterface > params)
Default handler for the required alignment request.
llvm::TypeSize getDefaultTypeSize(Type type, const DataLayout &dataLayout, DataLayoutEntryListRef params)
Default handler for the type size request.
llvm::TypeSize getDefaultTypeSizeInBits(Type type, const DataLayout &dataLayout, DataLayoutEntryListRef params)
Default handler for the type size in bits request.
uint64_t getDefaultPreferredAlignment(Type type, const DataLayout &dataLayout, ArrayRef< DataLayoutEntryInterface > params)
Default handler for the preferred alignment request.
llvm::TypeSize divideCeil(llvm::TypeSize numerator, uint64_t denominator)
Divides the known min value of the numerator by the denominator and rounds the result up to the next ...
uint64_t getDefaultStackAlignment(DataLayoutEntryInterface entry)
Default handler for the stack alignment request.
LogicalResult verifyDataLayoutOp(Operation *op)
Verifies that the operation implementing the data layout interface, or a module operation,...
LogicalResult verifyDataLayoutSpec(DataLayoutSpecInterface spec, Location loc)
Verifies that a data layout spec is valid.
DataLayoutEntryInterface filterEntryForIdentifier(DataLayoutEntryListRef entries, StringAttr id)
Given a list of data layout entries, returns the entry that has the given identifier as key,...
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26