1//===- BuiltinTypeInterfaces.td - Builtin type interfaces --*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file contains definitions for type interfaces that closely interact with 10// attributes, types, and operations in the builtin dialect. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef MLIR_IR_BUILTINTYPEINTERFACES_TD_ 15#define MLIR_IR_BUILTINTYPEINTERFACES_TD_ 16 17include "mlir/IR/OpBase.td" 18 19def FloatTypeInterface : TypeInterface<"FloatType"> { 20 let cppNamespace = "::mlir"; 21 let description = [{ 22 This type interface should be implemented by all floating-point types. It 23 defines the LLVM APFloat semantics and provides a few helper functions. 24 }]; 25 26 let methods = [ 27 InterfaceMethod< 28 /*desc=*/[{ 29 Returns the APFloat semantics for this floating-point type. 30 }], 31 /*retTy=*/"const ::llvm::fltSemantics &", 32 /*methodName=*/"getFloatSemantics", 33 /*args=*/(ins) 34 >, 35 InterfaceMethod< 36 /*desc=*/[{ 37 Returns a float type with bitwidth scaled by `scale`. Returns a "null" 38 float type if the scaled element type cannot be represented. 39 }], 40 /*retTy=*/"::mlir::FloatType", 41 /*methodName=*/"scaleElementBitwidth", 42 /*args=*/(ins "unsigned":$scale), 43 /*methodBody=*/"", 44 /*defaultImplementation=*/"return ::mlir::FloatType();" 45 > 46 ]; 47 48 let extraClassDeclaration = [{ 49 /// Return the bitwidth of this float type. 50 unsigned getWidth(); 51 52 /// Return the width of the mantissa of this type. 53 /// The width includes the integer bit. 54 unsigned getFPMantissaWidth(); 55 }]; 56} 57 58//===----------------------------------------------------------------------===// 59// MemRefElementTypeInterface 60//===----------------------------------------------------------------------===// 61 62def MemRefElementTypeInterface : TypeInterface<"MemRefElementTypeInterface"> { 63 let cppNamespace = "::mlir"; 64 let description = [{ 65 Indication that this type can be used as element in memref types. 66 67 Implementing this interface establishes a contract between this type and the 68 memref type indicating that this type can be used as element of ranked or 69 unranked memrefs. The type is expected to: 70 71 - model an entity stored in memory; 72 - have non-zero size. 73 74 For example, scalar values such as integers can implement this interface, 75 but indicator types such as `void` or `unit` should not. 76 77 The interface currently has no methods and is used by types to opt into 78 being memref elements. This may change in the future, in particular to 79 require types to provide their size or alignment given a data layout. 80 }]; 81} 82 83//===----------------------------------------------------------------------===// 84// ShapedType 85//===----------------------------------------------------------------------===// 86 87def ShapedTypeInterface : TypeInterface<"ShapedType"> { 88 let cppNamespace = "::mlir"; 89 let description = [{ 90 This interface provides a common API for interacting with multi-dimensional 91 container types. These types contain a shape and an element type. 92 93 A shape is a list of sizes corresponding to the dimensions of the container. 94 If the number of dimensions in the shape is unknown, the shape is "unranked". 95 If the number of dimensions is known, the shape "ranked". The sizes of the 96 dimensions of the shape must be positive, or kDynamic (in which case the 97 size of the dimension is dynamic, or not statically known). 98 }]; 99 let methods = [ 100 InterfaceMethod<[{ 101 Returns a clone of this type with the given shape and element type. 102 103 If no shape is provided, the shape of this type is used. In that case, if 104 this type is unranked, so is the resulting type. 105 106 If a shape is provided, the resulting type is always ranked, even if this 107 type is unranked. 108 }], 109 "::mlir::ShapedType", "cloneWith", (ins 110 "::std::optional<::llvm::ArrayRef<int64_t>>":$shape, 111 "::mlir::Type":$elementType 112 )>, 113 114 InterfaceMethod<[{ 115 Returns the element type of this shaped type. 116 }], 117 "::mlir::Type", "getElementType">, 118 119 InterfaceMethod<[{ 120 Returns if this type is ranked, i.e. it has a known number of dimensions. 121 }], 122 "bool", "hasRank">, 123 124 InterfaceMethod<[{ 125 Returns the shape of this type if it is ranked, otherwise asserts. 126 }], 127 "::llvm::ArrayRef<int64_t>", "getShape">, 128 ]; 129 130 let extraClassDeclaration = [{ 131 static constexpr int64_t kDynamic = 132 std::numeric_limits<int64_t>::min(); 133 134 /// Whether the given dimension size indicates a dynamic dimension. 135 static constexpr bool isDynamic(int64_t dValue) { 136 return dValue == kDynamic; 137 } 138 139 /// Whether the given shape has any size that indicates a dynamic dimension. 140 static bool isDynamicShape(ArrayRef<int64_t> dSizes) { 141 return any_of(dSizes, [](int64_t dSize) { return isDynamic(dSize); }); 142 } 143 144 /// Return the number of elements present in the given shape. 145 static int64_t getNumElements(ArrayRef<int64_t> shape); 146 147 /// Return a clone of this type with the given new shape and element type. 148 /// The returned type is ranked, even if this type is unranked. 149 auto clone(::llvm::ArrayRef<int64_t> shape, Type elementType) { 150 return cloneWith(shape, elementType); 151 } 152 153 /// Return a clone of this type with the given new shape. The returned type 154 /// is ranked, even if this type is unranked. 155 auto clone(::llvm::ArrayRef<int64_t> shape) { 156 return cloneWith(shape, getElementType()); 157 } 158 }]; 159 160 let extraSharedClassDeclaration = [{ 161 /// Return a clone of this type with the given new element type. The 162 /// returned type is ranked if and only if this type is ranked. In that 163 /// case, the returned type has the same shape as this type. 164 auto clone(::mlir::Type elementType) { 165 return $_type.cloneWith(/*shape=*/std::nullopt, elementType); 166 } 167 168 /// If an element type is an integer or a float, return its width. Otherwise, 169 /// abort. 170 unsigned getElementTypeBitWidth() const { 171 return $_type.getElementType().getIntOrFloatBitWidth(); 172 } 173 174 /// If this is a ranked type, return the rank. Otherwise, abort. 175 int64_t getRank() const { 176 assert($_type.hasRank() && "cannot query rank of unranked shaped type"); 177 return $_type.getShape().size(); 178 } 179 180 /// If it has static shape, return the number of elements. Otherwise, abort. 181 int64_t getNumElements() const { 182 assert(hasStaticShape() && "cannot get element count of dynamic shaped type"); 183 return ::mlir::ShapedType::getNumElements($_type.getShape()); 184 } 185 186 /// Returns true if this dimension has a dynamic size (for ranked types); 187 /// aborts for unranked types. 188 bool isDynamicDim(unsigned idx) const { 189 assert(idx < getRank() && "invalid index for shaped type"); 190 return ::mlir::ShapedType::isDynamic($_type.getShape()[idx]); 191 } 192 193 /// Returns if this type has a static shape, i.e. if the type is ranked and 194 /// all dimensions have known size (>= 0). 195 bool hasStaticShape() const { 196 return $_type.hasRank() && 197 !::mlir::ShapedType::isDynamicShape($_type.getShape()); 198 } 199 200 /// Returns if this type has a static shape and the shape is equal to 201 /// `shape` return true. 202 bool hasStaticShape(::llvm::ArrayRef<int64_t> shape) const { 203 return hasStaticShape() && $_type.getShape() == shape; 204 } 205 206 /// If this is a ranked type, return the number of dimensions with dynamic 207 /// size. Otherwise, abort. 208 size_t getNumDynamicDims() const { 209 return llvm::count_if($_type.getShape(), ::mlir::ShapedType::isDynamic); 210 } 211 212 /// If this is ranked type, return the size of the specified dimension. 213 /// Otherwise, abort. 214 int64_t getDimSize(unsigned idx) const { 215 assert(idx < getRank() && "invalid index for shaped type"); 216 return $_type.getShape()[idx]; 217 } 218 219 /// Returns the position of the dynamic dimension relative to just the dynamic 220 /// dimensions, given its `index` within the shape. 221 unsigned getDynamicDimIndex(unsigned index) const { 222 assert(index < getRank() && "invalid index"); 223 assert(::mlir::ShapedType::isDynamic(getDimSize(index)) && "invalid index"); 224 return llvm::count_if($_type.getShape().take_front(index), 225 ::mlir::ShapedType::isDynamic); 226 } 227 }]; 228} 229 230#endif // MLIR_IR_BUILTINTYPEINTERFACES_TD_ 231