10#include "TypeDetail.h"
19#include "llvm/ADT/APFloat.h"
20#include "llvm/ADT/Sequence.h"
21#include "llvm/ADT/TypeSwitch.h"
30#define GET_TYPEDEF_CLASSES
31#include "mlir/IR/BuiltinTypes.cpp.inc"
34#include "mlir/IR/BuiltinTypeConstraints.cpp.inc"
41void BuiltinDialect::registerTypes() {
43#define GET_TYPEDEF_LIST
44#include "mlir/IR/BuiltinTypes.cpp.inc"
56 return emitError() <<
"invalid element type for complex";
67 SignednessSemantics signedness) {
68 if (width > IntegerType::kMaxWidth) {
69 return emitError() <<
"integer bitwidth is limited to "
70 << IntegerType::kMaxWidth <<
" bits";
75unsigned IntegerType::getWidth()
const {
return getImpl()->width; }
77IntegerType::SignednessSemantics IntegerType::getSignedness()
const {
78 return getImpl()->signedness;
81IntegerType IntegerType::scaleElementBitwidth(
unsigned scale) {
84 return IntegerType::get(
getContext(), scale * getWidth(), getSignedness());
92#define FLOAT_TYPE_SEMANTICS(TYPE, SEM) \
93 const llvm::fltSemantics &TYPE::getFloatSemantics() const { \
94 return APFloat::SEM(); \
114#undef FLOAT_TYPE_SEMANTICS
116FloatType Float16Type::scaleElementBitwidth(
unsigned scale)
const {
124FloatType BFloat16Type::scaleElementBitwidth(
unsigned scale)
const {
132FloatType Float32Type::scaleElementBitwidth(
unsigned scale)
const {
142unsigned FunctionType::getNumInputs()
const {
return getImpl()->numInputs; }
145 return getImpl()->getInputs();
148unsigned FunctionType::getNumResults()
const {
return getImpl()->numResults; }
151 return getImpl()->getResults();
160FunctionType FunctionType::getWithArgsAndResults(
167 insertTypesInto(getResults(), resultIndices, resultTypes, resultStorage);
168 return clone(newArgTypes, newResultTypes);
173FunctionType::getWithoutArgsAndResults(
const BitVector &argIndices,
174 const BitVector &resultIndices) {
179 return clone(newArgTypes, newResultTypes);
186unsigned GraphType::getNumInputs()
const {
return getImpl()->numInputs; }
188ArrayRef<Type> GraphType::getInputs()
const {
return getImpl()->getInputs(); }
190unsigned GraphType::getNumResults()
const {
return getImpl()->numResults; }
192ArrayRef<Type> GraphType::getResults()
const {
return getImpl()->getResults(); }
208 insertTypesInto(getResults(), resultIndices, resultTypes, resultStorage);
209 return clone(newArgTypes, newResultTypes);
213GraphType GraphType::getWithoutArgsAndResults(
const BitVector &argIndices,
214 const BitVector &resultIndices) {
219 return clone(newArgTypes, newResultTypes);
227 StringAttr dialect, StringRef typeData) {
229 return emitError() <<
"invalid dialect namespace '" << dialect <<
"'";
236 <<
"`!" << dialect <<
"<\"" << typeData <<
"\">"
237 <<
"` type created with unregistered dialect. If this is "
238 "intended, please call allowUnregisteredDialects() on the "
239 "MLIRContext, or use -allow-unregistered-dialect with "
240 "the MLIR opt tool used";
250bool VectorType::isValidElementType(
Type t) {
257 if (!isValidElementType(elementType))
259 <<
"vector elements must be int/index/float type but got "
262 if (any_of(shape, [](int64_t i) {
return i <= 0; }))
264 <<
"vector types must have positive constant sizes but got "
267 if (scalableDims.size() != shape.size())
268 return emitError() <<
"number of dims must match, got "
269 << scalableDims.size() <<
" and " << shape.size();
274VectorType VectorType::scaleElementBitwidth(
unsigned scale) {
278 if (
auto scaledEt = et.scaleElementBitwidth(scale))
279 return VectorType::get(
getShape(), scaledEt, getScalableDims());
281 if (
auto scaledEt = et.scaleElementBitwidth(scale))
282 return VectorType::get(
getShape(), scaledEt, getScalableDims());
287 Type elementType)
const {
288 return VectorType::get(shape.value_or(
getShape()), elementType,
298 .Case<RankedTensorType, UnrankedTensorType>(
299 [](
auto type) {
return type.getElementType(); });
303 return !llvm::isa<UnrankedTensorType>(*
this);
307 return llvm::cast<RankedTensorType>(*this).getShape();
311 Type elementType)
const {
312 if (llvm::dyn_cast<UnrankedTensorType>(*
this)) {
314 return RankedTensorType::get(*
shape, elementType);
315 return UnrankedTensorType::get(elementType);
318 auto rankedTy = llvm::cast<RankedTensorType>(*
this);
320 return RankedTensorType::get(rankedTy.getShape(), elementType,
321 rankedTy.getEncoding());
322 return RankedTensorType::get(
shape.value_or(rankedTy.getShape()), elementType,
323 rankedTy.getEncoding());
327 Type elementType)
const {
328 return ::llvm::cast<RankedTensorType>(
cloneWith(
shape, elementType));
340 return emitError() <<
"invalid tensor element type: " << elementType;
349 return llvm::isa<ComplexType, FloatType, IntegerType, OpaqueType, VectorType,
351 !llvm::isa<BuiltinDialect>(type.
getDialect());
363 if (s < 0 && ShapedType::isStatic(s))
364 return emitError() <<
"invalid tensor dimension size";
365 if (
auto v = llvm::dyn_cast_or_null<VerifiableTensorEncoding>(encoding))
388 [](
auto type) {
return type.getElementType(); });
392 return !llvm::isa<UnrankedMemRefType>(*
this);
396 return llvm::cast<MemRefType>(*this).getShape();
400 Type elementType)
const {
401 if (llvm::dyn_cast<UnrankedMemRefType>(*
this)) {
416FailureOr<PtrLikeTypeInterface>
418 std::optional<Type> elementType)
const {
420 if (llvm::dyn_cast<UnrankedMemRefType>(*
this))
421 return cast<PtrLikeTypeInterface>(
422 UnrankedMemRefType::get(eTy, memorySpace));
427 return cast<PtrLikeTypeInterface>(
static_cast<MemRefType
>(builder));
431 Type elementType)
const {
440 if (
auto rankedMemRefTy = llvm::dyn_cast<MemRefType>(*
this))
441 return rankedMemRefTy.getMemorySpace();
442 return llvm::cast<UnrankedMemRefType>(*this).getMemorySpace();
446 if (
auto rankedMemRefTy = llvm::dyn_cast<MemRefType>(*
this))
447 return rankedMemRefTy.getMemorySpaceAsInt();
448 return llvm::cast<UnrankedMemRefType>(*this).getMemorySpaceAsInt();
455std::optional<llvm::SmallDenseSet<unsigned>>
459 size_t originalRank = originalShape.size(), reducedRank = reducedShape.size();
460 llvm::SmallDenseSet<unsigned> unusedDims;
461 unsigned reducedIdx = 0;
462 for (
unsigned originalIdx = 0; originalIdx < originalRank; ++originalIdx) {
464 int64_t origSize = originalShape[originalIdx];
466 if (matchDynamic && reducedIdx < reducedRank && origSize != 1 &&
467 (ShapedType::isDynamic(reducedShape[reducedIdx]) ||
468 ShapedType::isDynamic(origSize))) {
472 if (reducedIdx < reducedRank && origSize == reducedShape[reducedIdx]) {
477 unusedDims.insert(originalIdx);
484 if (reducedIdx != reducedRank)
491 ShapedType candidateReducedType) {
492 if (originalType == candidateReducedType)
495 ShapedType originalShapedType = llvm::cast<ShapedType>(originalType);
496 ShapedType candidateReducedShapedType =
497 llvm::cast<ShapedType>(candidateReducedType);
502 candidateReducedShapedType.getShape();
503 unsigned originalRank = originalShape.size(),
504 candidateReducedRank = candidateReducedShape.size();
505 if (candidateReducedRank > originalRank)
508 auto optionalUnusedDimsMask =
512 if (!optionalUnusedDimsMask)
515 if (originalShapedType.getElementType() !=
516 candidateReducedShapedType.getElementType())
528 if (llvm::isa<IntegerAttr, StringAttr, DictionaryAttr>(memorySpace))
532 if (!isa<BuiltinDialect>(memorySpace.
getDialect()))
540 if (memorySpace == 0)
543 return IntegerAttr::get(IntegerType::get(ctx, 64), memorySpace);
547 IntegerAttr intMemorySpace = llvm::dyn_cast_or_null<IntegerAttr>(memorySpace);
548 if (intMemorySpace && intMemorySpace.getValue() == 0)
558 assert(llvm::isa<IntegerAttr>(memorySpace) &&
559 "Using `getMemorySpaceInteger` with non-Integer attribute");
561 return static_cast<unsigned>(llvm::cast<IntegerAttr>(memorySpace).getInt());
564unsigned MemRefType::getMemorySpaceAsInt()
const {
569 MemRefLayoutAttrInterface layout,
583MemRefType MemRefType::getChecked(
585 Type elementType, MemRefLayoutAttrInterface layout,
Attribute memorySpace) {
596 elementType, layout, memorySpace);
608 auto layout = AffineMapAttr::get(map);
628 auto layout = AffineMapAttr::get(map);
634 elementType, layout, memorySpace);
638 AffineMap map,
unsigned memorySpaceInd) {
646 auto layout = AffineMapAttr::get(map);
659 unsigned memorySpaceInd) {
667 auto layout = AffineMapAttr::get(map);
674 elementType, layout, memorySpace);
679 MemRefLayoutAttrInterface layout,
682 return emitError() <<
"invalid memref element type";
685 for (int64_t s :
shape)
686 if (s < 0 && ShapedType::isStatic(s))
687 return emitError() <<
"invalid memref size";
689 assert(layout &&
"missing layout specification");
694 return emitError() <<
"unsupported memory space Attribute";
699bool MemRefType::areTrailingDimsContiguous(int64_t n) {
700 assert(n <= getRank() &&
701 "number of dimensions to check must not exceed rank");
702 return n <= getNumContiguousTrailingDims();
705int64_t MemRefType::getNumContiguousTrailingDims() {
706 const int64_t n = getRank();
709 if (getLayout().isIdentity())
727 int64_t dimProduct = 1;
728 for (int64_t i = n - 1; i >= 0; --i) {
731 if (strides[i] != dimProduct)
733 if (
shape[i] == ShapedType::kDynamic)
735 dimProduct *=
shape[i];
741MemRefType MemRefType::canonicalizeStridedLayout() {
742 AffineMap m = getLayout().getAffineMap();
754 if (
auto cst = llvm::dyn_cast<AffineConstantExpr>(m.
getResult(0)))
755 if (cst.getValue() == 0)
770 auto simplifiedLayoutExpr =
772 if (expr != simplifiedLayoutExpr)
775 simplifiedLayoutExpr)));
780 int64_t &offset)
const {
781 return getLayout().getStridesAndOffset(
getShape(), strides, offset);
784std::pair<SmallVector<int64_t>, int64_t>
785MemRefType::getStridesAndOffset()
const {
790 assert(succeeded(status) &&
"Invalid use of check-free getStridesAndOffset");
791 return {strides, offset};
794bool MemRefType::isStrided() {
798 return succeeded(res);
801bool MemRefType::isLastDimUnitStride() {
805 return succeeded(successStrides) && (strides.empty() || strides.back() == 1);
812unsigned UnrankedMemRefType::getMemorySpaceAsInt()
const {
820 return emitError() <<
"invalid memref element type";
823 return emitError() <<
"unsupported memory space Attribute";
833ArrayRef<Type> TupleType::getTypes()
const {
return getImpl()->getTypes(); }
840 for (
Type type : getTypes()) {
841 if (
auto nestedTuple = llvm::dyn_cast<TupleType>(type))
842 nestedTuple.getFlattenedTypes(types);
844 types.push_back(type);
849size_t TupleType::size()
const {
return getImpl()->size(); }
862 assert(!exprs.empty() &&
"expected exprs");
864 assert(!maps.empty() &&
"Expected one non-empty map");
865 unsigned numDims = maps[0].getNumDims(), nSymbols = maps[0].getNumSymbols();
868 bool dynamicPoisonBit =
false;
870 for (
auto en : llvm::zip(llvm::reverse(exprs), llvm::reverse(sizes))) {
871 int64_t size = std::get<1>(en);
876 expr = expr ? expr + dimExpr * stride : dimExpr * stride;
879 assert(runningSize > 0 &&
"integer overflow in size computation");
881 dynamicPoisonBit =
true;
890 exprs.reserve(sizes.size());
891 for (
auto dim : llvm::seq<unsigned>(0, sizes.size()))
static LogicalResult getStridesAndOffset(AffineMap m, ArrayRef< int64_t > shape, SmallVectorImpl< AffineExpr > &strides, AffineExpr &offset)
A stride specification is a list of integer values that are either static or dynamic (encoded with Sh...
static LogicalResult checkTensorElementType(function_ref< InFlightDiagnostic()> emitError, Type elementType)
#define FLOAT_TYPE_SEMANTICS(TYPE, SEM)
static Type getElementType(Type type)
Determine the element type of type.
static ArrayRef< int64_t > getShape(Type type)
Returns the shape of the given type.
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
static AffineMap getMultiDimIdentityMap(unsigned numDims, MLIRContext *context)
Returns an AffineMap with 'numDims' identity result dim exprs.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
unsigned getNumSymbols() const
unsigned getNumDims() const
unsigned getNumResults() const
static SmallVector< AffineMap, 4 > inferFromExprList(ArrayRef< ArrayRef< AffineExpr > > exprsList, MLIRContext *context)
Returns a vector of AffineMaps; each with as many results as exprs.size(), as many dims as the larges...
AffineExpr getResult(unsigned idx) const
bool isIdentity() const
Returns true if this affine map is an identity affine map.
Attributes are known-constant values of operations.
Dialect & getDialect() const
Get the dialect this attribute is registered to.
This class provides a shared interface for ranked and unranked memref types.
ArrayRef< int64_t > getShape() const
Returns the shape of this memref type.
static bool isValidElementType(Type type)
Return true if the specified element type is ok in a memref.
FailureOr< PtrLikeTypeInterface > clonePtrWith(Attribute memorySpace, std::optional< Type > elementType) const
Clone this type with the given memory space and element type.
Attribute getMemorySpace() const
Returns the memory space in which data referred to by this memref resides.
unsigned getMemorySpaceAsInt() const
[deprecated] Returns the memory space in old raw integer representation.
BaseMemRefType cloneWith(std::optional< ArrayRef< int64_t > > shape, Type elementType) const
Clone this type with the given shape and element type.
bool hasRank() const
Returns if this type is ranked, i.e. it has a known number of dimensions.
Type getElementType() const
Returns the element type of this memref type.
MemRefType clone(ArrayRef< int64_t > shape, Type elementType) const
Return a clone of this type with the given new shape and element type.
static bool isValidNamespace(StringRef str)
Utility function that returns if the given string is a valid dialect namespace.
This class represents a diagnostic that is inflight and set to be reported.
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
bool allowsUnregisteredDialects()
Return true if we allow to create operation for unregistered dialects.
This is a builder type that keeps local references to arguments.
Builder & setShape(ArrayRef< int64_t > newShape)
Builder & setMemorySpace(Attribute newMemorySpace)
Builder & setElementType(Type newElementType)
Builder & setLayout(MemRefLayoutAttrInterface newLayout)
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
TensorType cloneWith(std::optional< ArrayRef< int64_t > > shape, Type elementType) const
Clone this type with the given shape and element type.
static bool isValidElementType(Type type)
Return true if the specified element type is ok in a tensor.
ArrayRef< int64_t > getShape() const
Returns the shape of this tensor type.
bool hasRank() const
Returns if this type is ranked, i.e. it has a known number of dimensions.
RankedTensorType clone(ArrayRef< int64_t > shape, Type elementType) const
Return a clone of this type with the given new shape and element type.
Type getElementType() const
Returns the element type of this tensor type.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Dialect & getDialect() const
Get the dialect this type is registered to.
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Attribute wrapIntegerMemorySpace(unsigned memorySpace, MLIRContext *ctx)
Wraps deprecated integer memory space to the new Attribute form.
unsigned getMemorySpaceAsInt(Attribute memorySpace)
[deprecated] Returns the memory space in old raw integer representation.
bool isSupportedMemorySpace(Attribute memorySpace)
Checks if the memorySpace has supported Attribute type.
Attribute skipDefaultMemorySpace(Attribute memorySpace)
Replaces default memorySpace (integer == 0) with empty Attribute.
Include the generated interface declarations.
bool isValidVectorTypeElementType(::mlir::Type type)
SliceVerificationResult
Enum that captures information related to verifier error conditions on slice insert/extract type of o...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
TypeRange filterTypesOut(TypeRange types, const BitVector &indices, SmallVectorImpl< Type > &storage)
Filters out any elements referenced by indices.
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
AffineExpr getAffineConstantExpr(int64_t constant, MLIRContext *context)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
AffineExpr makeCanonicalStridedLayoutExpr(ArrayRef< int64_t > sizes, ArrayRef< AffineExpr > exprs, MLIRContext *context)
Given MemRef sizes that are either static or dynamic, returns the canonical "contiguous" strides Affi...
std::optional< llvm::SmallDenseSet< unsigned > > computeRankReductionMask(ArrayRef< int64_t > originalShape, ArrayRef< int64_t > reducedShape, bool matchDynamic=false)
Given an originalShape and a reducedShape assumed to be a subset of originalShape with some 1 entries...
AffineExpr simplifyAffineExpr(AffineExpr expr, unsigned numDims, unsigned numSymbols)
Simplify an affine expression by flattening and some amount of simple analysis.
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
SliceVerificationResult isRankReducedType(ShapedType originalType, ShapedType candidateReducedType)
Check if originalType can be rank reduced to candidateReducedType type by dropping some dimensions wi...
TypeRange insertTypesInto(TypeRange oldTypes, ArrayRef< unsigned > indices, TypeRange newTypes, SmallVectorImpl< Type > &storage)
Insert a set of newTypes into oldTypes at the given indices.
llvm::function_ref< Fn > function_ref
AffineExpr getAffineSymbolExpr(unsigned position, MLIRContext *context)