MLIR  15.0.0git
LLVMTypes.cpp
Go to the documentation of this file.
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file implements the types for the LLVM dialect in MLIR. These MLIR types
9 // correspond to the LLVM IR type system.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "TypeDetail.h"
14 
17 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/TypeSupport.h"
20 
21 #include "llvm/ADT/ScopeExit.h"
22 #include "llvm/ADT/TypeSwitch.h"
23 #include "llvm/Support/TypeSize.h"
24 
25 using namespace mlir;
26 using namespace mlir::LLVM;
27 
28 constexpr const static unsigned kBitsInByte = 8;
29 
30 //===----------------------------------------------------------------------===//
31 // Array type.
32 //===----------------------------------------------------------------------===//
33 
35  return !type.isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
36  LLVMFunctionType, LLVMTokenType, LLVMScalableVectorType>();
37 }
38 
39 LLVMArrayType LLVMArrayType::get(Type elementType, unsigned numElements) {
40  assert(elementType && "expected non-null subtype");
41  return Base::get(elementType.getContext(), elementType, numElements);
42 }
43 
46  Type elementType, unsigned numElements) {
47  assert(elementType && "expected non-null subtype");
48  return Base::getChecked(emitError, elementType.getContext(), elementType,
49  numElements);
50 }
51 
52 Type LLVMArrayType::getElementType() const { return getImpl()->elementType; }
53 
55  return getImpl()->numElements;
56 }
57 
60  Type elementType, unsigned numElements) {
61  if (!isValidElementType(elementType))
62  return emitError() << "invalid array element type: " << elementType;
63  return success();
64 }
65 
66 unsigned LLVMArrayType::getTypeSizeInBits(const DataLayout &dataLayout,
67  DataLayoutEntryListRef params) const {
68  return kBitsInByte * getTypeSize(dataLayout, params);
69 }
70 
71 unsigned LLVMArrayType::getTypeSize(const DataLayout &dataLayout,
72  DataLayoutEntryListRef params) const {
73  return llvm::alignTo(dataLayout.getTypeSize(getElementType()),
74  dataLayout.getTypeABIAlignment(getElementType())) *
76 }
77 
78 unsigned LLVMArrayType::getABIAlignment(const DataLayout &dataLayout,
79  DataLayoutEntryListRef params) const {
80  return dataLayout.getTypeABIAlignment(getElementType());
81 }
82 
83 unsigned
85  DataLayoutEntryListRef params) const {
86  return dataLayout.getTypePreferredAlignment(getElementType());
87 }
88 
89 //===----------------------------------------------------------------------===//
90 // Function type.
91 //===----------------------------------------------------------------------===//
92 
94  return !type.isa<LLVMVoidType, LLVMFunctionType>();
95 }
96 
98  return !type.isa<LLVMFunctionType, LLVMMetadataType, LLVMLabelType>();
99 }
100 
102  bool isVarArg) {
103  assert(result && "expected non-null result");
104  return Base::get(result.getContext(), result, arguments, isVarArg);
105 }
106 
109  Type result, ArrayRef<Type> arguments,
110  bool isVarArg) {
111  assert(result && "expected non-null result");
112  return Base::getChecked(emitError, result.getContext(), result, arguments,
113  isVarArg);
114 }
115 
117  TypeRange results) const {
118  assert(results.size() == 1 && "expected a single result type");
119  return get(results[0], llvm::to_vector(inputs), isVarArg());
120 }
121 
122 Type LLVMFunctionType::getReturnType() { return getImpl()->getReturnType(); }
124  return getImpl()->getReturnType();
125 }
126 
128  return getImpl()->getArgumentTypes().size();
129 }
130 
132  return getImpl()->getArgumentTypes()[i];
133 }
134 
135 bool LLVMFunctionType::isVarArg() const { return getImpl()->isVariadic(); }
136 
138  return getImpl()->getArgumentTypes();
139 }
140 
143  Type result, ArrayRef<Type> arguments, bool) {
144  if (!isValidResultType(result))
145  return emitError() << "invalid function result type: " << result;
146 
147  for (Type arg : arguments)
148  if (!isValidArgumentType(arg))
149  return emitError() << "invalid function argument type: " << arg;
150 
151  return success();
152 }
153 
154 //===----------------------------------------------------------------------===//
155 // Pointer type.
156 //===----------------------------------------------------------------------===//
157 
159  if (!type)
160  return true;
161  return isCompatibleOuterType(type)
162  ? !type.isa<LLVMVoidType, LLVMTokenType, LLVMMetadataType,
163  LLVMLabelType>()
164  : type.isa<PointerElementTypeInterface>();
165 }
166 
167 LLVMPointerType LLVMPointerType::get(Type pointee, unsigned addressSpace) {
168  assert(pointee && "expected non-null subtype, pass the context instead if "
169  "the opaque pointer type is desired");
170  return Base::get(pointee.getContext(), pointee, addressSpace);
171 }
172 
174  unsigned addressSpace) {
175  return Base::get(context, Type(), addressSpace);
176 }
177 
180  Type pointee, unsigned addressSpace) {
181  return Base::getChecked(emitError, pointee.getContext(), pointee,
182  addressSpace);
183 }
184 
187  MLIRContext *context, unsigned addressSpace) {
188  return Base::getChecked(emitError, context, Type(), addressSpace);
189 }
190 
191 Type LLVMPointerType::getElementType() const { return getImpl()->pointeeType; }
192 
193 bool LLVMPointerType::isOpaque() const { return !getImpl()->pointeeType; }
194 
196  return getImpl()->addressSpace;
197 }
198 
201  Type pointee, unsigned) {
202  if (!isValidElementType(pointee))
203  return emitError() << "invalid pointer element type: " << pointee;
204  return success();
205 }
206 
207 namespace {
208 /// The positions of different values in the data layout entry.
209 enum class DLEntryPos { Size = 0, Abi = 1, Preferred = 2, Address = 3 };
210 } // namespace
211 
212 constexpr const static unsigned kDefaultPointerSizeBits = 64;
213 constexpr const static unsigned kDefaultPointerAlignment = 8;
214 
215 /// Returns the value that corresponds to named position `pos` from the
216 /// attribute `attr` assuming it's a dense integer elements attribute.
217 static unsigned extractPointerSpecValue(Attribute attr, DLEntryPos pos) {
218  return attr.cast<DenseIntElementsAttr>()
219  .getValues<unsigned>()[static_cast<unsigned>(pos)];
220 }
221 
222 /// Returns the part of the data layout entry that corresponds to `pos` for the
223 /// given `type` by interpreting the list of entries `params`. For the pointer
224 /// type in the default address space, returns the default value if the entries
225 /// do not provide a custom one, for other address spaces returns None.
226 static Optional<unsigned>
228  DLEntryPos pos) {
229  // First, look for the entry for the pointer in the current address space.
230  Attribute currentEntry;
231  for (DataLayoutEntryInterface entry : params) {
232  if (!entry.isTypeEntry())
233  continue;
234  if (entry.getKey().get<Type>().cast<LLVMPointerType>().getAddressSpace() ==
235  type.getAddressSpace()) {
236  currentEntry = entry.getValue();
237  break;
238  }
239  }
240  if (currentEntry) {
241  return extractPointerSpecValue(currentEntry, pos) /
242  (pos == DLEntryPos::Size ? 1 : kBitsInByte);
243  }
244 
245  // If not found, and this is the pointer to the default memory space, assume
246  // 64-bit pointers.
247  if (type.getAddressSpace() == 0) {
248  return pos == DLEntryPos::Size ? kDefaultPointerSizeBits
250  }
251 
252  return llvm::None;
253 }
254 
255 unsigned
257  DataLayoutEntryListRef params) const {
258  if (Optional<unsigned> size =
259  getPointerDataLayoutEntry(params, *this, DLEntryPos::Size))
260  return *size;
261 
262  // For other memory spaces, use the size of the pointer to the default memory
263  // space.
264  if (isOpaque())
265  return dataLayout.getTypeSizeInBits(get(getContext()));
266  return dataLayout.getTypeSizeInBits(get(getElementType()));
267 }
268 
269 unsigned LLVMPointerType::getABIAlignment(const DataLayout &dataLayout,
270  DataLayoutEntryListRef params) const {
271  if (Optional<unsigned> alignment =
272  getPointerDataLayoutEntry(params, *this, DLEntryPos::Abi))
273  return *alignment;
274 
275  if (isOpaque())
276  return dataLayout.getTypeABIAlignment(get(getContext()));
277  return dataLayout.getTypeABIAlignment(get(getElementType()));
278 }
279 
280 unsigned
282  DataLayoutEntryListRef params) const {
283  if (Optional<unsigned> alignment =
284  getPointerDataLayoutEntry(params, *this, DLEntryPos::Preferred))
285  return *alignment;
286 
287  if (isOpaque())
288  return dataLayout.getTypePreferredAlignment(get(getContext()));
289  return dataLayout.getTypePreferredAlignment(get(getElementType()));
290 }
291 
293  DataLayoutEntryListRef newLayout) const {
294  for (DataLayoutEntryInterface newEntry : newLayout) {
295  if (!newEntry.isTypeEntry())
296  continue;
297  unsigned size = kDefaultPointerSizeBits;
298  unsigned abi = kDefaultPointerAlignment;
299  auto newType = newEntry.getKey().get<Type>().cast<LLVMPointerType>();
300  const auto *it =
301  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
302  if (auto type = entry.getKey().dyn_cast<Type>()) {
303  return type.cast<LLVMPointerType>().getAddressSpace() ==
304  newType.getAddressSpace();
305  }
306  return false;
307  });
308  if (it == oldLayout.end()) {
309  llvm::find_if(oldLayout, [&](DataLayoutEntryInterface entry) {
310  if (auto type = entry.getKey().dyn_cast<Type>()) {
311  return type.cast<LLVMPointerType>().getAddressSpace() == 0;
312  }
313  return false;
314  });
315  }
316  if (it != oldLayout.end()) {
317  size = extractPointerSpecValue(*it, DLEntryPos::Size);
318  abi = extractPointerSpecValue(*it, DLEntryPos::Abi);
319  }
320 
321  Attribute newSpec = newEntry.getValue().cast<DenseIntElementsAttr>();
322  unsigned newSize = extractPointerSpecValue(newSpec, DLEntryPos::Size);
323  unsigned newAbi = extractPointerSpecValue(newSpec, DLEntryPos::Abi);
324  if (size != newSize || abi < newAbi || abi % newAbi != 0)
325  return false;
326  }
327  return true;
328 }
329 
331  Location loc) const {
332  for (DataLayoutEntryInterface entry : entries) {
333  if (!entry.isTypeEntry())
334  continue;
335  auto key = entry.getKey().get<Type>().cast<LLVMPointerType>();
336  auto values = entry.getValue().dyn_cast<DenseIntElementsAttr>();
337  if (!values || (values.size() != 3 && values.size() != 4)) {
338  return emitError(loc)
339  << "expected layout attribute for " << entry.getKey().get<Type>()
340  << " to be a dense integer elements attribute with 3 or 4 "
341  "elements";
342  }
343  if (key.getElementType() && !key.getElementType().isInteger(8)) {
344  return emitError(loc) << "unexpected layout attribute for pointer to "
345  << key.getElementType();
346  }
347  if (extractPointerSpecValue(values, DLEntryPos::Abi) >
348  extractPointerSpecValue(values, DLEntryPos::Preferred)) {
349  return emitError(loc) << "preferred alignment is expected to be at least "
350  "as large as ABI alignment";
351  }
352  }
353  return success();
354 }
355 
356 //===----------------------------------------------------------------------===//
357 // Struct type.
358 //===----------------------------------------------------------------------===//
359 
361  return !type.isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
362  LLVMFunctionType, LLVMTokenType, LLVMScalableVectorType>();
363 }
364 
366  StringRef name) {
367  return Base::get(context, name, /*opaque=*/false);
368 }
369 
372  StringRef name) {
373  return Base::getChecked(emitError, context, name, /*opaque=*/false);
374 }
375 
377  StringRef name,
378  ArrayRef<Type> elements,
379  bool isPacked) {
380  std::string stringName = name.str();
381  unsigned counter = 0;
382  do {
383  auto type = LLVMStructType::getIdentified(context, stringName);
384  if (type.isInitialized() || failed(type.setBody(elements, isPacked))) {
385  counter += 1;
386  stringName = (Twine(name) + "." + std::to_string(counter)).str();
387  continue;
388  }
389  return type;
390  } while (true);
391 }
392 
394  ArrayRef<Type> types, bool isPacked) {
395  return Base::get(context, types, isPacked);
396 }
397 
400  MLIRContext *context, ArrayRef<Type> types,
401  bool isPacked) {
402  return Base::getChecked(emitError, context, types, isPacked);
403 }
404 
406  return Base::get(context, name, /*opaque=*/true);
407 }
408 
411  MLIRContext *context, StringRef name) {
412  return Base::getChecked(emitError, context, name, /*opaque=*/true);
413 }
414 
416  assert(isIdentified() && "can only set bodies of identified structs");
417  assert(llvm::all_of(types, LLVMStructType::isValidElementType) &&
418  "expected valid body types");
419  return Base::mutate(types, isPacked);
420 }
421 
422 bool LLVMStructType::isPacked() const { return getImpl()->isPacked(); }
423 bool LLVMStructType::isIdentified() const { return getImpl()->isIdentified(); }
425  return getImpl()->isIdentified() &&
426  (getImpl()->isOpaque() || !getImpl()->isInitialized());
427 }
428 bool LLVMStructType::isInitialized() { return getImpl()->isInitialized(); }
429 StringRef LLVMStructType::getName() { return getImpl()->getIdentifier(); }
431  return isIdentified() ? getImpl()->getIdentifiedStructBody()
432  : getImpl()->getTypeList();
433 }
434 
436  StringRef, bool) {
437  return success();
438 }
439 
442  ArrayRef<Type> types, bool) {
443  for (Type t : types)
444  if (!isValidElementType(t))
445  return emitError() << "invalid LLVM structure element type: " << t;
446 
447  return success();
448 }
449 
450 unsigned
452  DataLayoutEntryListRef params) const {
453  unsigned structSize = 0;
454  unsigned structAlignment = 1;
455  for (Type element : getBody()) {
456  unsigned elementAlignment =
457  isPacked() ? 1 : dataLayout.getTypeABIAlignment(element);
458  // Add padding to the struct size to align it to the abi alignment of the
459  // element type before than adding the size of the element
460  structSize = llvm::alignTo(structSize, elementAlignment);
461  structSize += dataLayout.getTypeSize(element);
462 
463  // The alignment requirement of a struct is equal to the strictest alignment
464  // requirement of its elements.
465  structAlignment = std::max(elementAlignment, structAlignment);
466  }
467  // At the end, add padding to the struct to satisfy its own alignment
468  // requirement. Otherwise structs inside of arrays would be misaligned.
469  structSize = llvm::alignTo(structSize, structAlignment);
470  return structSize * kBitsInByte;
471 }
472 
473 namespace {
474 enum class StructDLEntryPos { Abi = 0, Preferred = 1 };
475 } // namespace
476 
477 static Optional<unsigned>
479  StructDLEntryPos pos) {
480  const auto *currentEntry =
481  llvm::find_if(params, [](DataLayoutEntryInterface entry) {
482  return entry.isTypeEntry();
483  });
484  if (currentEntry == params.end())
485  return llvm::None;
486 
487  auto attr = currentEntry->getValue().cast<DenseIntElementsAttr>();
488  if (pos == StructDLEntryPos::Preferred &&
489  attr.size() <= static_cast<unsigned>(StructDLEntryPos::Preferred))
490  // If no preferred was specified, fall back to abi alignment
491  pos = StructDLEntryPos::Abi;
492 
493  return attr.getValues<unsigned>()[static_cast<unsigned>(pos)];
494 }
495 
496 static unsigned calculateStructAlignment(const DataLayout &dataLayout,
497  DataLayoutEntryListRef params,
498  LLVMStructType type,
499  StructDLEntryPos pos) {
500  // Packed structs always have an abi alignment of 1
501  if (pos == StructDLEntryPos::Abi && type.isPacked()) {
502  return 1;
503  }
504 
505  // The alignment requirement of a struct is equal to the strictest alignment
506  // requirement of its elements.
507  unsigned structAlignment = 1;
508  for (Type iter : type.getBody()) {
509  structAlignment =
510  std::max(dataLayout.getTypeABIAlignment(iter), structAlignment);
511  }
512 
513  // Entries are only allowed to be stricter than the required alignment
514  if (Optional<unsigned> entryResult =
515  getStructDataLayoutEntry(params, type, pos))
516  return std::max(*entryResult / kBitsInByte, structAlignment);
517 
518  return structAlignment;
519 }
520 
521 unsigned LLVMStructType::getABIAlignment(const DataLayout &dataLayout,
522  DataLayoutEntryListRef params) const {
523  return calculateStructAlignment(dataLayout, params, *this,
524  StructDLEntryPos::Abi);
525 }
526 
527 unsigned
529  DataLayoutEntryListRef params) const {
530  return calculateStructAlignment(dataLayout, params, *this,
531  StructDLEntryPos::Preferred);
532 }
533 
535  return attr.cast<DenseIntElementsAttr>()
536  .getValues<unsigned>()[static_cast<unsigned>(pos)];
537 }
538 
540  DataLayoutEntryListRef newLayout) const {
541  for (DataLayoutEntryInterface newEntry : newLayout) {
542  if (!newEntry.isTypeEntry())
543  continue;
544 
545  const auto *previousEntry =
546  llvm::find_if(oldLayout, [](DataLayoutEntryInterface entry) {
547  return entry.isTypeEntry();
548  });
549  if (previousEntry == oldLayout.end())
550  continue;
551 
552  unsigned abi = extractStructSpecValue(previousEntry->getValue(),
553  StructDLEntryPos::Abi);
554  unsigned newAbi =
555  extractStructSpecValue(newEntry.getValue(), StructDLEntryPos::Abi);
556  if (abi < newAbi || abi % newAbi != 0)
557  return false;
558  }
559  return true;
560 }
561 
563  Location loc) const {
564  for (DataLayoutEntryInterface entry : entries) {
565  if (!entry.isTypeEntry())
566  continue;
567 
568  auto key = entry.getKey().get<Type>().cast<LLVMStructType>();
569  auto values = entry.getValue().dyn_cast<DenseIntElementsAttr>();
570  if (!values || (values.size() != 2 && values.size() != 1)) {
571  return emitError(loc)
572  << "expected layout attribute for " << entry.getKey().get<Type>()
573  << " to be a dense integer elements attribute of 1 or 2 elements";
574  }
575 
576  if (key.isIdentified() || !key.getBody().empty()) {
577  return emitError(loc) << "unexpected layout attribute for struct " << key;
578  }
579 
580  if (values.size() == 1)
581  continue;
582 
583  if (extractStructSpecValue(values, StructDLEntryPos::Abi) >
584  extractStructSpecValue(values, StructDLEntryPos::Preferred)) {
585  return emitError(loc) << "preferred alignment is expected to be at least "
586  "as large as ABI alignment";
587  }
588  }
589  return mlir::success();
590 }
591 
592 //===----------------------------------------------------------------------===//
593 // Vector types.
594 //===----------------------------------------------------------------------===//
595 
596 /// Verifies that the type about to be constructed is well-formed.
597 template <typename VecTy>
598 static LogicalResult
600  Type elementType, unsigned numElements) {
601  if (numElements == 0)
602  return emitError() << "the number of vector elements must be positive";
603 
604  if (!VecTy::isValidElementType(elementType))
605  return emitError() << "invalid vector element type";
606 
607  return success();
608 }
609 
611  unsigned numElements) {
612  assert(elementType && "expected non-null subtype");
613  return Base::get(elementType.getContext(), elementType, numElements);
614 }
615 
618  Type elementType, unsigned numElements) {
619  assert(elementType && "expected non-null subtype");
620  return Base::getChecked(emitError, elementType.getContext(), elementType,
621  numElements);
622 }
623 
625  return static_cast<detail::LLVMTypeAndSizeStorage *>(impl)->elementType;
626 }
627 
629  return getImpl()->numElements;
630 }
631 
633  return type.isa<LLVMPointerType, LLVMPPCFP128Type>();
634 }
635 
638  Type elementType, unsigned numElements) {
639  return verifyVectorConstructionInvariants<LLVMFixedVectorType>(
640  emitError, elementType, numElements);
641 }
642 
643 //===----------------------------------------------------------------------===//
644 // LLVMScalableVectorType.
645 //===----------------------------------------------------------------------===//
646 
648  unsigned minNumElements) {
649  assert(elementType && "expected non-null subtype");
650  return Base::get(elementType.getContext(), elementType, minNumElements);
651 }
652 
655  Type elementType, unsigned minNumElements) {
656  assert(elementType && "expected non-null subtype");
657  return Base::getChecked(emitError, elementType.getContext(), elementType,
658  minNumElements);
659 }
660 
662  return static_cast<detail::LLVMTypeAndSizeStorage *>(impl)->elementType;
663 }
664 
666  return getImpl()->numElements;
667 }
668 
670  if (auto intType = type.dyn_cast<IntegerType>())
671  return intType.isSignless();
672 
673  return isCompatibleFloatingPointType(type) || type.isa<LLVMPointerType>();
674 }
675 
678  Type elementType, unsigned numElements) {
679  return verifyVectorConstructionInvariants<LLVMScalableVectorType>(
680  emitError, elementType, numElements);
681 }
682 
683 //===----------------------------------------------------------------------===//
684 // Utility functions.
685 //===----------------------------------------------------------------------===//
686 
688  // clang-format off
689  if (type.isa<
690  BFloat16Type,
691  Float16Type,
692  Float32Type,
693  Float64Type,
694  Float80Type,
695  Float128Type,
698  LLVMLabelType,
699  LLVMMetadataType,
700  LLVMPPCFP128Type,
703  LLVMTokenType,
706  LLVMVoidType,
707  LLVMX86MMXType
708  >()) {
709  // clang-format on
710  return true;
711  }
712 
713  // Only signless integers are compatible.
714  if (auto intType = type.dyn_cast<IntegerType>())
715  return intType.isSignless();
716 
717  // 1D vector types are compatible.
718  if (auto vecType = type.dyn_cast<VectorType>())
719  return vecType.getRank() == 1;
720 
721  return false;
722 }
723 
724 static bool isCompatibleImpl(Type type, SetVector<Type> &callstack) {
725  if (callstack.contains(type))
726  return true;
727 
728  callstack.insert(type);
729  auto stackPopper = llvm::make_scope_exit([&] { callstack.pop_back(); });
730 
731  auto isCompatible = [&](Type type) {
732  return isCompatibleImpl(type, callstack);
733  };
734 
735  return llvm::TypeSwitch<Type, bool>(type)
736  .Case<LLVMStructType>([&](auto structType) {
737  return llvm::all_of(structType.getBody(), isCompatible);
738  })
739  .Case<LLVMFunctionType>([&](auto funcType) {
740  return isCompatible(funcType.getReturnType()) &&
741  llvm::all_of(funcType.getParams(), isCompatible);
742  })
743  .Case<IntegerType>([](auto intType) { return intType.isSignless(); })
744  .Case<VectorType>([&](auto vecType) {
745  return vecType.getRank() == 1 && isCompatible(vecType.getElementType());
746  })
747  .Case<LLVMPointerType>([&](auto pointerType) {
748  if (pointerType.isOpaque())
749  return true;
750  return isCompatible(pointerType.getElementType());
751  })
752  // clang-format off
753  .Case<
757  >([&](auto containerType) {
758  return isCompatible(containerType.getElementType());
759  })
760  .Case<
761  BFloat16Type,
762  Float16Type,
763  Float32Type,
764  Float64Type,
765  Float80Type,
766  Float128Type,
767  LLVMLabelType,
768  LLVMMetadataType,
769  LLVMPPCFP128Type,
770  LLVMTokenType,
771  LLVMVoidType,
772  LLVMX86MMXType
773  >([](Type) { return true; })
774  // clang-format on
775  .Default([](Type) { return false; });
776 }
777 
779  SetVector<Type> callstack;
780  return isCompatibleImpl(type, callstack);
781 }
782 
784  return type.isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
785  Float80Type, Float128Type, LLVMPPCFP128Type>();
786 }
787 
790  return true;
791 
792  if (auto vecType = type.dyn_cast<VectorType>()) {
793  if (vecType.getRank() != 1)
794  return false;
795  Type elementType = vecType.getElementType();
796  if (auto intType = elementType.dyn_cast<IntegerType>())
797  return intType.isSignless();
798  return elementType.isa<BFloat16Type, Float16Type, Float32Type, Float64Type,
799  Float80Type, Float128Type>();
800  }
801  return false;
802 }
803 
805  return llvm::TypeSwitch<Type, Type>(type)
806  .Case<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>(
807  [](auto ty) { return ty.getElementType(); })
808  .Default([](Type) -> Type {
809  llvm_unreachable("incompatible with LLVM vector type");
810  });
811 }
812 
813 llvm::ElementCount mlir::LLVM::getVectorNumElements(Type type) {
815  .Case([](VectorType ty) {
816  if (ty.isScalable())
817  return llvm::ElementCount::getScalable(ty.getNumElements());
818  return llvm::ElementCount::getFixed(ty.getNumElements());
819  })
820  .Case([](LLVMFixedVectorType ty) {
821  return llvm::ElementCount::getFixed(ty.getNumElements());
822  })
823  .Case([](LLVMScalableVectorType ty) {
824  return llvm::ElementCount::getScalable(ty.getMinNumElements());
825  })
826  .Default([](Type) -> llvm::ElementCount {
827  llvm_unreachable("incompatible with LLVM vector type");
828  });
829 }
830 
832  assert(
833  (vectorType
834  .isa<LLVMFixedVectorType, LLVMScalableVectorType, VectorType>()) &&
835  "expected LLVM-compatible vector type");
836  return !vectorType.isa<LLVMFixedVectorType>() &&
837  (vectorType.isa<LLVMScalableVectorType>() ||
838  vectorType.cast<VectorType>().isScalable());
839 }
840 
841 Type mlir::LLVM::getVectorType(Type elementType, unsigned numElements,
842  bool isScalable) {
843  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
844  bool useBuiltIn = VectorType::isValidElementType(elementType);
845  (void)useBuiltIn;
846  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
847  "to be either builtin or LLVM dialect type");
848  if (useLLVM) {
849  if (isScalable)
850  return LLVMScalableVectorType::get(elementType, numElements);
851  return LLVMFixedVectorType::get(elementType, numElements);
852  }
853  return VectorType::get(numElements, elementType, (unsigned)isScalable);
854 }
855 
856 Type mlir::LLVM::getFixedVectorType(Type elementType, unsigned numElements) {
857  bool useLLVM = LLVMFixedVectorType::isValidElementType(elementType);
858  bool useBuiltIn = VectorType::isValidElementType(elementType);
859  (void)useBuiltIn;
860  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible fixed-vector type "
861  "to be either builtin or LLVM dialect type");
862  if (useLLVM)
863  return LLVMFixedVectorType::get(elementType, numElements);
864  return VectorType::get(numElements, elementType);
865 }
866 
867 Type mlir::LLVM::getScalableVectorType(Type elementType, unsigned numElements) {
868  bool useLLVM = LLVMScalableVectorType::isValidElementType(elementType);
869  bool useBuiltIn = VectorType::isValidElementType(elementType);
870  (void)useBuiltIn;
871  assert((useLLVM ^ useBuiltIn) && "expected LLVM-compatible scalable-vector "
872  "type to be either builtin or LLVM dialect "
873  "type");
874  if (useLLVM)
875  return LLVMScalableVectorType::get(elementType, numElements);
876  return VectorType::get(numElements, elementType, /*numScalableDims=*/1);
877 }
878 
880  assert(isCompatibleType(type) &&
881  "expected a type compatible with the LLVM dialect");
882 
884  .Case<BFloat16Type, Float16Type>(
885  [](Type) { return llvm::TypeSize::Fixed(16); })
886  .Case<Float32Type>([](Type) { return llvm::TypeSize::Fixed(32); })
887  .Case<Float64Type, LLVMX86MMXType>(
888  [](Type) { return llvm::TypeSize::Fixed(64); })
889  .Case<Float80Type>([](Type) { return llvm::TypeSize::Fixed(80); })
890  .Case<Float128Type>([](Type) { return llvm::TypeSize::Fixed(128); })
891  .Case<IntegerType>([](IntegerType intTy) {
892  return llvm::TypeSize::Fixed(intTy.getWidth());
893  })
894  .Case<LLVMPPCFP128Type>([](Type) { return llvm::TypeSize::Fixed(128); })
895  .Case<LLVMFixedVectorType>([](LLVMFixedVectorType t) {
896  llvm::TypeSize elementSize =
898  return llvm::TypeSize(elementSize.getFixedSize() * t.getNumElements(),
899  elementSize.isScalable());
900  })
901  .Case<VectorType>([](VectorType t) {
902  assert(isCompatibleVectorType(t) &&
903  "unexpected incompatible with LLVM vector type");
904  llvm::TypeSize elementSize =
905  getPrimitiveTypeSizeInBits(t.getElementType());
906  return llvm::TypeSize(elementSize.getFixedSize() * t.getNumElements(),
907  elementSize.isScalable());
908  })
909  .Default([](Type ty) {
910  assert((ty.isa<LLVMVoidType, LLVMLabelType, LLVMMetadataType,
911  LLVMTokenType, LLVMStructType, LLVMArrayType,
913  "unexpected missing support for primitive type");
914  return llvm::TypeSize::Fixed(0);
915  });
916 }
917 
918 #include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.cpp.inc"
Include the generated interface declarations.
static bool isValidArgumentType(Type type)
Checks if the given type can be used an argument in a function type.
Definition: LLVMTypes.cpp:93
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:783
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, Type pointee, unsigned)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:200
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Definition: LLVMTypes.cpp:813
U cast() const
Definition: Attributes.h:130
Type getFixedVectorType(Type elementType, unsigned numElements)
Creates an LLVM dialect-compatible type with the given element type and length.
Definition: LLVMTypes.cpp:856
static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name, ArrayRef< Type > elements, bool isPacked=false)
Gets a new identified struct with the given body.
Definition: LLVMTypes.cpp:376
LLVM dialect scalable vector type, represents a sequence of elements of unknown length that is known ...
Definition: LLVMTypes.h:407
unsigned getMinNumElements()
Returns the scaling factor of the number of elements in the vector.
Definition: LLVMTypes.cpp:665
ArrayRef< Type > getReturnTypes()
Returns the result type of the function as an ArrayRef, enabling better integration with generic MLIR...
Definition: LLVMTypes.cpp:123
StringRef getName()
Returns the name of an identified struct.
Definition: LLVMTypes.cpp:429
static bool isCompatibleImpl(Type type, SetVector< Type > &callstack)
Definition: LLVMTypes.cpp:724
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
Definition: LLVMTypes.cpp:687
static LLVMStructType getOpaque(StringRef name, MLIRContext *context)
Gets or creates an intentionally-opaque identified struct.
Definition: LLVMTypes.cpp:405
static LLVMStructType getLiteral(MLIRContext *context, ArrayRef< Type > types, bool isPacked=false)
Gets or creates a literal struct with the given body in the provided context.
Definition: LLVMTypes.cpp:393
static LLVMPointerType getChecked(function_ref< InFlightDiagnostic()> emitError, Type pointee, unsigned addressSpace=0)
Definition: LLVMTypes.cpp:179
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:311
static LLVMArrayType get(Type elementType, unsigned numElements)
Gets or creates an instance of LLVM dialect array type containing numElements of elementType, in the same context as elementType.
Definition: LLVMTypes.cpp:39
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
Definition: LLVMTypes.cpp:841
ArrayRef< Type > getParams()
Returns a list of argument types of the function.
Definition: LLVMTypes.cpp:137
Type getElementType()
Returns the element type of the vector.
Definition: LLVMTypes.cpp:624
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
LLVM dialect function type.
Definition: LLVMTypes.h:123
static unsigned calculateStructAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:496
static LLVMStructType getIdentifiedChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, StringRef name)
Definition: LLVMTypes.cpp:370
bool isOpaque() const
Returns true if this type is the opaque pointer type, i.e., it has no pointed-to type.
Definition: LLVMTypes.cpp:193
unsigned getTypeSizeInBits(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Hooks for DataLayoutTypeInterface.
Definition: LLVMTypes.cpp:451
bool areCompatible(DataLayoutEntryListRef oldLayout, DataLayoutEntryListRef newLayout) const
Definition: LLVMTypes.cpp:292
static bool isValidResultType(Type type)
Checks if the given type can be used as a result in a function type.
Definition: LLVMTypes.cpp:97
static LLVMArrayType getChecked(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Definition: LLVMTypes.cpp:45
unsigned getAddressSpace() const
Returns the address space of the pointer.
Definition: LLVMTypes.cpp:195
static LLVMFunctionType get(Type result, ArrayRef< Type > arguments, bool isVarArg=false)
Gets or creates an instance of LLVM dialect function in the same context as the result type...
Definition: LLVMTypes.cpp:101
bool isOpaque()
Checks if a struct is opaque.
Definition: LLVMTypes.cpp:424
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned minNumElements)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:677
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, StringRef, bool)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:435
static Optional< unsigned > getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type, DLEntryPos pos)
Returns the part of the data layout entry that corresponds to pos for the given type by interpreting ...
Definition: LLVMTypes.cpp:227
LLVMFunctionType clone(TypeRange inputs, TypeRange results) const
Returns a clone of this function type with the given argument and result types.
Definition: LLVMTypes.cpp:116
static ConcreteT get(MLIRContext *ctx, Args... args)
Get or create a new ConcreteT instance within the ctx.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
static LLVMScalableVectorType getChecked(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned minNumElements)
Definition: LLVMTypes.cpp:654
unsigned getTypeSize(Type t) const
Returns the size of the given type in the current scope.
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, Type result, ArrayRef< Type > arguments, bool)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:142
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
unsigned getPreferredAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:84
constexpr static const unsigned kDefaultPointerAlignment
Definition: LLVMTypes.cpp:213
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:778
bool isVarArg() const
Returns whether the function is variadic.
Definition: LLVMTypes.cpp:135
unsigned getTypeSize(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:71
bool isInitialized()
Checks if a struct is initialized.
Definition: LLVMTypes.cpp:428
unsigned getPreferredAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:528
Common storage used for LLVM dialect types that need an element type and a number: arrays...
Definition: TypeDetail.h:414
U dyn_cast() const
Definition: Types.h:244
Attributes are known-constant values of operations.
Definition: Attributes.h:24
Type getElementType() const
Returns the element type of the array.
Definition: LLVMTypes.cpp:52
bool areCompatible(DataLayoutEntryListRef oldLayout, DataLayoutEntryListRef newLayout) const
Definition: LLVMTypes.cpp:539
unsigned getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
LogicalResult verifyEntries(DataLayoutEntryListRef entries, Location loc) const
Definition: LLVMTypes.cpp:330
Type getParamType(unsigned i)
Returns i-th argument of the function. Asserts on out-of-bounds.
Definition: LLVMTypes.cpp:131
Type getReturnType()
Returns the result type of the function.
Definition: LLVMTypes.cpp:122
static unsigned extractPointerSpecValue(Attribute attr, DLEntryPos pos)
Returns the value that corresponds to named position pos from the attribute attr assuming it&#39;s a dens...
Definition: LLVMTypes.cpp:217
unsigned getNumParams()
Returns the number of arguments to the function.
Definition: LLVMTypes.cpp:127
static LLVMPointerType get(MLIRContext *context, unsigned addressSpace=0)
Gets or creates an instance of LLVM dialect pointer type pointing to an object of pointee type in the...
Definition: LLVMTypes.cpp:173
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
unsigned getNumElements()
Returns the number of elements in the fixed vector.
Definition: LLVMTypes.cpp:628
unsigned getABIAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:521
unsigned getTypeSizeInBits(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Hooks for DataLayoutTypeInterface.
Definition: LLVMTypes.cpp:66
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
Definition: LLVMTypes.cpp:430
static LLVMStructType getIdentified(MLIRContext *context, StringRef name)
Gets or creates an identified struct with the given name in the provided context. ...
Definition: LLVMTypes.cpp:365
static bool isValidElementType(Type type)
Checks if the given type can be contained in a structure type.
Definition: LLVMTypes.cpp:360
static LLVMFunctionType getChecked(function_ref< InFlightDiagnostic()> emitError, Type result, ArrayRef< Type > arguments, bool isVarArg=false)
Definition: LLVMTypes.cpp:108
static bool isValidElementType(Type type)
Checks if the given type can be used in a vector type.
Definition: LLVMTypes.cpp:632
static LogicalResult verifyVectorConstructionInvariants(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:599
unsigned getPreferredAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:281
Type getScalableVectorType(Type elementType, unsigned numElements)
Creates an LLVM dialect-compatible type with the given element type and length.
Definition: LLVMTypes.cpp:867
unsigned getABIAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:78
Type getElementType()
Returns the element type of the vector.
Definition: LLVMTypes.cpp:661
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:19
unsigned getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
LLVM dialect array type.
Definition: LLVMTypes.h:74
static LLVMFixedVectorType getChecked(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Definition: LLVMTypes.cpp:617
static Optional< unsigned > getStructDataLayoutEntry(DataLayoutEntryListRef params, LLVMStructType type, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:478
unsigned getNumElements() const
Returns the number of elements in the array type.
Definition: LLVMTypes.cpp:54
static LLVMFixedVectorType get(Type elementType, unsigned numElements)
Gets or creates a fixed vector type containing numElements of elementType in the same context as elem...
Definition: LLVMTypes.cpp:610
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool isPacked() const
Checks if a struct is packed.
Definition: LLVMTypes.cpp:422
static bool isValidElementType(Type type)
Checks if the given type can be used inside an array type.
Definition: LLVMTypes.cpp:34
unsigned getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
static bool isValidElementType(Type type)
Checks if the given type can have a pointer type pointing to it.
Definition: LLVMTypes.cpp:158
LogicalResult mutate(Args &&...args)
Mutate the current storage instance.
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Definition: LLVMTypes.h:265
ImplType * getImpl() const
Utility for easy access to the storage instance.
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect. ...
Definition: LLVMTypes.cpp:788
static VectorType vectorType(CodeGen &codegen, Type etp)
Constructs vector type.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
bool isIdentified() const
Checks if a struct is identified.
Definition: LLVMTypes.cpp:423
static unsigned extractStructSpecValue(Attribute attr, StructDLEntryPos pos)
Definition: LLVMTypes.cpp:534
LLVM dialect pointer type.
Definition: LLVMTypes.h:182
llvm::TypeSize getPrimitiveTypeSizeInBits(Type type)
Returns the size of the given primitive LLVM dialect-compatible type (including vectors) in bits...
Definition: LLVMTypes.cpp:879
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
Definition: LLVMTypes.cpp:831
unsigned getTypeSizeInBits(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Hooks for DataLayoutTypeInterface.
Definition: LLVMTypes.cpp:256
static LLVMStructType getOpaqueChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, StringRef name)
Definition: LLVMTypes.cpp:410
StructDLEntryPos
Definition: LLVMTypes.cpp:474
DLEntryPos
The positions of different values in the data layout entry.
Definition: LLVMTypes.cpp:209
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:637
static LLVMScalableVectorType get(Type elementType, unsigned minNumElements)
Gets or creates a scalable vector type containing a non-zero multiple of minNumElements of elementTyp...
Definition: LLVMTypes.cpp:647
unsigned getABIAlignment(const DataLayout &dataLayout, DataLayoutEntryListRef params) const
Definition: LLVMTypes.cpp:269
LogicalResult setBody(ArrayRef< Type > types, bool isPacked)
Set the body of an identified struct.
Definition: LLVMTypes.cpp:415
bool isa() const
Definition: Types.h:234
static bool isValidElementType(Type type)
Checks if the given type can be used in a vector type.
Definition: LLVMTypes.cpp:669
LLVM dialect fixed vector type, represents a sequence of elements of known length that can be process...
Definition: LLVMTypes.h:369
static LogicalResult verify(function_ref< InFlightDiagnostic()> emitError, Type elementType, unsigned numElements)
Verifies that the type about to be constructed is well-formed.
Definition: LLVMTypes.cpp:59
constexpr static const unsigned kDefaultPointerSizeBits
Definition: LLVMTypes.cpp:212
LogicalResult verifyEntries(DataLayoutEntryListRef entries, Location loc) const
Definition: LLVMTypes.cpp:562
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
Definition: LLVMTypes.cpp:804
Type getElementType() const
Returns the pointed-to type. It may be null if the pointer is opaque.
Definition: LLVMTypes.cpp:191
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
An attribute that represents a reference to a dense integer vector or tensor object.
U cast() const
Definition: Types.h:250
The main mechanism for performing data layout queries.
static LLVMStructType getLiteralChecked(function_ref< InFlightDiagnostic()> emitError, MLIRContext *context, ArrayRef< Type > types, bool isPacked=false)
Definition: LLVMTypes.cpp:399
constexpr static const unsigned kBitsInByte
Definition: LLVMTypes.cpp:28
static ConcreteT getChecked(const Location &loc, Args... args)
Get or create a new ConcreteT instance within the ctx, defined at the given, potentially unknown...