1//===- ViewLikeInterface.td - ViewLike interface -----------*- 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// Defines the interface for view-like operations. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef MLIR_INTERFACES_VIEWLIKEINTERFACE 14#define MLIR_INTERFACES_VIEWLIKEINTERFACE 15 16include "mlir/IR/OpBase.td" 17 18def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> { 19 let description = [{ 20 A view-like operation "views" a buffer in a potentially different way. It 21 takes in a (view of) buffer (and potentially some other operands) and returns 22 another view of buffer. 23 }]; 24 let cppNamespace = "::mlir"; 25 26 let methods = [ 27 InterfaceMethod< 28 "Returns the source buffer from which the view is created.", 29 "Value", "getViewSource"> 30 ]; 31} 32 33def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface"> { 34 let description = [{ 35 Common interface for ops that allow specifying mixed dynamic and static 36 offsets, sizes and strides variadic operands. 37 Ops that implement this interface need to expose the following methods: 38 1. `getArrayAttrRanks` to specify the length of static integer 39 attributes. 40 2. `offsets`, `sizes` and `strides` variadic operands. 41 3. `static_offsets`, resp. `static_sizes` and `static_strides` integer 42 array attributes. 43 44 The invariants of this interface are: 45 1. `static_offsets`, `static_sizes` and `static_strides` have length 46 exactly `getArrayAttrRanks()`[0] (resp. [1], [2]). 47 2. `offsets`, `sizes` and `strides` have each length at most 48 `getArrayAttrRanks()`[0] (resp. [1], [2]). 49 3. if an entry of `static_offsets` (resp. `static_sizes`, 50 `static_strides`) is equal to a special sentinel value, namely 51 `ShapedType::kDynamicStrideOrOffset` (resp. `ShapedType::kDynamicSize`, 52 `ShapedType::kDynamicStrideOrOffset`), then the corresponding entry is 53 a dynamic offset (resp. size, stride). 54 4. a variadic `offset` (resp. `sizes`, `strides`) operand must be present 55 for each dynamic offset (resp. size, stride). 56 57 This interface is useful to factor out common behavior and provide support 58 for carrying or injecting static behavior through the use of the static 59 attributes. 60 }]; 61 62 let cppNamespace = "::mlir"; 63 64 let methods = [ 65 InterfaceMethod< 66 /*desc=*/[{ 67 Return the expected rank of each of the`static_offsets`, `static_sizes` 68 and `static_strides` attributes. 69 }], 70 /*retTy=*/"std::array<unsigned, 3>", 71 /*methodName=*/"getArrayAttrRanks", 72 /*args=*/(ins), 73 /*methodBody=*/"", 74 /*defaultImplementation=*/[{ 75 return $_op.offsets(); 76 }] 77 >, 78 InterfaceMethod< 79 /*desc=*/[{ 80 Return the dynamic offset operands. 81 }], 82 /*retTy=*/"OperandRange", 83 /*methodName=*/"offsets", 84 /*args=*/(ins), 85 /*methodBody=*/"", 86 /*defaultImplementation=*/[{ 87 return $_op.offsets(); 88 }] 89 >, 90 InterfaceMethod< 91 /*desc=*/[{ 92 Return the dynamic size operands. 93 }], 94 /*retTy=*/"OperandRange", 95 /*methodName=*/"sizes", 96 /*args=*/(ins), 97 /*methodBody=*/"", 98 /*defaultImplementation=*/[{ 99 return $_op.sizes(); 100 }] 101 >, 102 InterfaceMethod< 103 /*desc=*/[{ 104 Return the dynamic stride operands. 105 }], 106 /*retTy=*/"OperandRange", 107 /*methodName=*/"strides", 108 /*args=*/(ins), 109 /*methodBody=*/"", 110 /*defaultImplementation=*/[{ 111 return $_op.strides(); 112 }] 113 >, 114 InterfaceMethod< 115 /*desc=*/[{ 116 Return the static offset attributes. 117 }], 118 /*retTy=*/"ArrayAttr", 119 /*methodName=*/"static_offsets", 120 /*args=*/(ins), 121 /*methodBody=*/"", 122 /*defaultImplementation=*/[{ 123 return $_op.static_offsets(); 124 }] 125 >, 126 InterfaceMethod< 127 /*desc=*/[{ 128 Return the static size attributes. 129 }], 130 /*retTy=*/"ArrayAttr", 131 /*methodName=*/"static_sizes", 132 /*args=*/(ins), 133 /*methodBody=*/"", 134 /*defaultImplementation=*/[{ 135 return $_op.static_sizes(); 136 }] 137 >, 138 InterfaceMethod< 139 /*desc=*/[{ 140 Return the dynamic stride attributes. 141 }], 142 /*retTy=*/"ArrayAttr", 143 /*methodName=*/"static_strides", 144 /*args=*/(ins), 145 /*methodBody=*/"", 146 /*defaultImplementation=*/[{ 147 return $_op.static_strides(); 148 }] 149 >, 150 151 InterfaceMethod< 152 /*desc=*/[{ 153 Return true if the offset `idx` is dynamic. 154 }], 155 /*retTy=*/"bool", 156 /*methodName=*/"isDynamicOffset", 157 /*args=*/(ins "unsigned":$idx), 158 /*methodBody=*/"", 159 /*defaultImplementation=*/[{ 160 APInt v = *(static_offsets() 161 .template getAsValueRange<IntegerAttr>().begin() + idx); 162 return ShapedType::isDynamicStrideOrOffset(v.getSExtValue()); 163 }] 164 >, 165 InterfaceMethod< 166 /*desc=*/[{ 167 Return true if the size `idx` is dynamic. 168 }], 169 /*retTy=*/"bool", 170 /*methodName=*/"isDynamicSize", 171 /*args=*/(ins "unsigned":$idx), 172 /*methodBody=*/"", 173 /*defaultImplementation=*/[{ 174 APInt v = *(static_sizes() 175 .template getAsValueRange<IntegerAttr>().begin() + idx); 176 return ShapedType::isDynamic(v.getSExtValue()); 177 }] 178 >, 179 InterfaceMethod< 180 /*desc=*/[{ 181 Return true if the stride `idx` is dynamic. 182 }], 183 /*retTy=*/"bool", 184 /*methodName=*/"isDynamicStride", 185 /*args=*/(ins "unsigned":$idx), 186 /*methodBody=*/"", 187 /*defaultImplementation=*/[{ 188 APInt v = *(static_strides() 189 .template getAsValueRange<IntegerAttr>().begin() + idx); 190 return ShapedType::isDynamicStrideOrOffset(v.getSExtValue()); 191 }] 192 >, 193 194 InterfaceMethod< 195 /*desc=*/[{ 196 Assert the offset `idx` is a static constant and return its value. 197 }], 198 /*retTy=*/"int64_t", 199 /*methodName=*/"getStaticOffset", 200 /*args=*/(ins "unsigned":$idx), 201 /*methodBody=*/"", 202 /*defaultImplementation=*/[{ 203 assert(!$_op.isDynamicOffset(idx) && "expected static offset"); 204 APInt v = *(static_offsets(). 205 template getAsValueRange<IntegerAttr>().begin() + idx); 206 return v.getSExtValue(); 207 }] 208 >, 209 InterfaceMethod< 210 /*desc=*/[{ 211 Assert the size `idx` is a static constant and return its value. 212 }], 213 /*retTy=*/"int64_t", 214 /*methodName=*/"getStaticSize", 215 /*args=*/(ins "unsigned":$idx), 216 /*methodBody=*/"", 217 /*defaultImplementation=*/[{ 218 assert(!$_op.isDynamicSize(idx) && "expected static size"); 219 APInt v = *(static_sizes(). 220 template getAsValueRange<IntegerAttr>().begin() + idx); 221 return v.getSExtValue(); 222 }] 223 >, 224 InterfaceMethod< 225 /*desc=*/[{ 226 Assert the stride `idx` is a static constant and return its value. 227 }], 228 /*retTy=*/"int64_t", 229 /*methodName=*/"getStaticStride", 230 /*args=*/(ins "unsigned":$idx), 231 /*methodBody=*/"", 232 /*defaultImplementation=*/[{ 233 assert(!$_op.isDynamicStride(idx) && "expected static stride"); 234 APInt v = *(static_strides(). 235 template getAsValueRange<IntegerAttr>().begin() + idx); 236 return v.getSExtValue(); 237 }] 238 >, 239 240 InterfaceMethod< 241 /*desc=*/[{ 242 Assert the offset `idx` is dynamic and return the position of the 243 corresponding operand. 244 }], 245 /*retTy=*/"unsigned", 246 /*methodName=*/"getIndexOfDynamicOffset", 247 /*args=*/(ins "unsigned":$idx), 248 /*methodBody=*/"", 249 /*defaultImplementation=*/[{ 250 assert($_op.isDynamicOffset(idx) && "expected dynamic offset"); 251 auto numDynamic = getNumDynamicEntriesUpToIdx( 252 static_offsets().template cast<ArrayAttr>(), 253 ShapedType::isDynamicStrideOrOffset, 254 idx); 255 return 1 + numDynamic; 256 }] 257 >, 258 InterfaceMethod< 259 /*desc=*/[{ 260 Assert the size `idx` is dynamic and return the position of the 261 corresponding operand. 262 }], 263 /*retTy=*/"unsigned", 264 /*methodName=*/"getIndexOfDynamicSize", 265 /*args=*/(ins "unsigned":$idx), 266 /*methodBody=*/"", 267 /*defaultImplementation=*/[{ 268 assert($_op.isDynamicSize(idx) && "expected dynamic size"); 269 auto numDynamic = getNumDynamicEntriesUpToIdx( 270 static_sizes().template cast<ArrayAttr>(), ShapedType::isDynamic, idx); 271 return 1 + offsets().size() + numDynamic; 272 }] 273 >, 274 InterfaceMethod< 275 /*desc=*/[{ 276 Assert the stride `idx` is dynamic and return the position of the 277 corresponding operand. 278 }], 279 /*retTy=*/"unsigned", 280 /*methodName=*/"getIndexOfDynamicStride", 281 /*args=*/(ins "unsigned":$idx), 282 /*methodBody=*/"", 283 /*defaultImplementation=*/[{ 284 assert($_op.isDynamicStride(idx) && "expected dynamic stride"); 285 auto numDynamic = getNumDynamicEntriesUpToIdx( 286 static_strides().template cast<ArrayAttr>(), 287 ShapedType::isDynamicStrideOrOffset, 288 idx); 289 return 1 + offsets().size() + sizes().size() + numDynamic; 290 }] 291 >, 292 InterfaceMethod< 293 /*desc=*/[{ 294 Helper method to compute the number of dynamic entries of `attr`, up to 295 `idx` using `isDynamic` to determine whether an entry is dynamic. 296 }], 297 /*retTy=*/"unsigned", 298 /*methodName=*/"getNumDynamicEntriesUpToIdx", 299 /*args=*/(ins "ArrayAttr":$attr, 300 "llvm::function_ref<bool(int64_t)>":$isDynamic, 301 "unsigned":$idx), 302 /*methodBody=*/"", 303 /*defaultImplementation=*/[{ 304 return std::count_if( 305 attr.getValue().begin(), attr.getValue().begin() + idx, 306 [&](Attribute attr) { 307 return isDynamic(attr.cast<IntegerAttr>().getInt()); 308 }); 309 }] 310 >, 311 312 InterfaceMethod< 313 /*desc=*/[{ 314 Assert the offset `idx` is dynamic and return its value. 315 }], 316 /*retTy=*/"Value", 317 /*methodName=*/"getDynamicOffset", 318 /*args=*/(ins "unsigned":$idx), 319 /*methodBody=*/"", 320 /*defaultImplementation=*/[{ 321 return $_op.getOperand(getIndexOfDynamicOffset(idx)); 322 }] 323 >, 324 InterfaceMethod< 325 /*desc=*/[{ 326 Assert the size `idx` is dynamic and return its value. 327 }], 328 /*retTy=*/"Value", 329 /*methodName=*/"getDynamicSize", 330 /*args=*/(ins "unsigned":$idx), 331 /*methodBody=*/"", 332 /*defaultImplementation=*/[{ 333 return $_op.getOperand(getIndexOfDynamicSize(idx)); 334 }] 335 >, 336 InterfaceMethod< 337 /*desc=*/[{ 338 Assert the stride `idx` is dynamic and return its value. 339 }], 340 /*retTy=*/"Value", 341 /*methodName=*/"getDynamicStride", 342 /*args=*/(ins "unsigned":$idx), 343 /*methodBody=*/"", 344 /*defaultImplementation=*/[{ 345 return $_op.getOperand(getIndexOfDynamicStride(idx)); 346 }] 347 >, 348 ]; 349 350 let extraClassDeclaration = [{ 351 static StringRef getStaticOffsetsAttrName() { 352 return "static_offsets"; 353 } 354 static StringRef getStaticSizesAttrName() { 355 return "static_sizes"; 356 } 357 static StringRef getStaticStridesAttrName() { 358 return "static_strides"; 359 } 360 static ArrayRef<StringRef> getSpecialAttrNames() { 361 static SmallVector<StringRef, 4> names{ 362 OffsetSizeAndStrideOpInterface::getStaticOffsetsAttrName(), 363 OffsetSizeAndStrideOpInterface::getStaticSizesAttrName(), 364 OffsetSizeAndStrideOpInterface::getStaticStridesAttrName(), 365 OpTrait::AttrSizedOperandSegments<void>::getOperandSegmentSizeAttr()}; 366 return names; 367 } 368 }]; 369 370 let verify = [{ 371 return mlir::verify(cast<OffsetSizeAndStrideOpInterface>($_op)); 372 }]; 373} 374 375#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE 376