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 "::mlir::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. `getArrayAttrMaxRanks` 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 4. `getOffsetSizeAndStrideStartOperandIndex` method that specifies the 44 starting index of the OffsetSizeAndStrideOpInterface operands 45 46 The invariants of this interface are: 47 1. `static_offsets`, `static_sizes` and `static_strides` have length 48 exactly `getArrayAttrMaxRanks()`[0] (resp. [1], [2]). 49 2. `offsets`, `sizes` and `strides` have each length at most 50 `getArrayAttrMaxRanks()`[0] (resp. [1], [2]). 51 3. if an entry of `static_offsets` (resp. `static_sizes`, 52 `static_strides`) is equal to a special sentinel value, namely 53 `ShapedType::kDynamicStrideOrOffset` (resp. `ShapedType::kDynamicSize`, 54 `ShapedType::kDynamicStrideOrOffset`), then the corresponding entry is 55 a dynamic offset (resp. size, stride). 56 4. a variadic `offset` (resp. `sizes`, `strides`) operand must be present 57 for each dynamic offset (resp. size, stride). 58 5. `offsets`, `sizes` and `strides` operands are specified in this order 59 at operand index starting at `getOffsetSizeAndStrideStartOperandIndex`. 60 61 This interface is useful to factor out common behavior and provide support 62 for carrying or injecting static behavior through the use of the static 63 attributes. 64 }]; 65 66 let cppNamespace = "::mlir"; 67 68 let methods = [ 69 StaticInterfaceMethod< 70 /*desc=*/[{ 71 Return the number of leading operands before the `offsets`, `sizes` and 72 and `strides` operands. 73 }], 74 /*retTy=*/"unsigned", 75 /*methodName=*/"getOffsetSizeAndStrideStartOperandIndex", 76 /*args=*/(ins) 77 >, 78 InterfaceMethod< 79 /*desc=*/[{ 80 Return the expected rank of each of the`static_offsets`, `static_sizes` 81 and `static_strides` attributes. 82 }], 83 /*retTy=*/"std::array<unsigned, 3>", 84 /*methodName=*/"getArrayAttrMaxRanks", 85 /*args=*/(ins) 86 >, 87 InterfaceMethod< 88 /*desc=*/[{ 89 Return the dynamic offset operands. 90 }], 91 /*retTy=*/"::mlir::OperandRange", 92 /*methodName=*/"offsets", 93 /*args=*/(ins), 94 /*methodBody=*/"", 95 /*defaultImplementation=*/[{ 96 return $_op.offsets(); 97 }] 98 >, 99 InterfaceMethod< 100 /*desc=*/[{ 101 Return the dynamic size operands. 102 }], 103 /*retTy=*/"::mlir::OperandRange", 104 /*methodName=*/"sizes", 105 /*args=*/(ins), 106 /*methodBody=*/"", 107 /*defaultImplementation=*/[{ 108 return $_op.sizes(); 109 }] 110 >, 111 InterfaceMethod< 112 /*desc=*/[{ 113 Return the dynamic stride operands. 114 }], 115 /*retTy=*/"::mlir::OperandRange", 116 /*methodName=*/"strides", 117 /*args=*/(ins), 118 /*methodBody=*/"", 119 /*defaultImplementation=*/[{ 120 return $_op.strides(); 121 }] 122 >, 123 InterfaceMethod< 124 /*desc=*/[{ 125 Return the static offset attributes. 126 }], 127 /*retTy=*/"::mlir::ArrayAttr", 128 /*methodName=*/"static_offsets", 129 /*args=*/(ins), 130 /*methodBody=*/"", 131 /*defaultImplementation=*/[{ 132 return $_op.static_offsets(); 133 }] 134 >, 135 InterfaceMethod< 136 /*desc=*/[{ 137 Return the static size attributes. 138 }], 139 /*retTy=*/"::mlir::ArrayAttr", 140 /*methodName=*/"static_sizes", 141 /*args=*/(ins), 142 /*methodBody=*/"", 143 /*defaultImplementation=*/[{ 144 return $_op.static_sizes(); 145 }] 146 >, 147 InterfaceMethod< 148 /*desc=*/[{ 149 Return the dynamic stride attributes. 150 }], 151 /*retTy=*/"::mlir::ArrayAttr", 152 /*methodName=*/"static_strides", 153 /*args=*/(ins), 154 /*methodBody=*/"", 155 /*defaultImplementation=*/[{ 156 return $_op.static_strides(); 157 }] 158 >, 159 InterfaceMethod< 160 /*desc=*/[{ 161 Return a vector of all the static or dynamic sizes of the op. 162 }], 163 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 164 /*methodName=*/"getMixedOffsets", 165 /*args=*/(ins), 166 /*methodBody=*/"", 167 /*defaultImplementation=*/[{ 168 return ::mlir::getMixedOffsets($_op, $_op.static_offsets(), 169 $_op.offsets()); 170 }] 171 >, 172 InterfaceMethod< 173 /*desc=*/[{ 174 Return a vector of all the static or dynamic sizes of the op. 175 }], 176 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 177 /*methodName=*/"getMixedSizes", 178 /*args=*/(ins), 179 /*methodBody=*/"", 180 /*defaultImplementation=*/[{ 181 return ::mlir::getMixedSizes($_op, $_op.static_sizes(), $_op.sizes()); 182 }] 183 >, 184 InterfaceMethod< 185 /*desc=*/[{ 186 Return a vector of all the static or dynamic strides of the op. 187 }], 188 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 189 /*methodName=*/"getMixedStrides", 190 /*args=*/(ins), 191 /*methodBody=*/"", 192 /*defaultImplementation=*/[{ 193 return ::mlir::getMixedStrides($_op, $_op.static_strides(), 194 $_op.strides()); 195 }] 196 >, 197 198 InterfaceMethod< 199 /*desc=*/[{ 200 Return true if the offset `idx` is dynamic. 201 }], 202 /*retTy=*/"bool", 203 /*methodName=*/"isDynamicOffset", 204 /*args=*/(ins "unsigned":$idx), 205 /*methodBody=*/"", 206 /*defaultImplementation=*/[{ 207 ::llvm::APInt v = *(static_offsets() 208 .template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 209 return ::mlir::ShapedType::isDynamicStrideOrOffset(v.getSExtValue()); 210 }] 211 >, 212 InterfaceMethod< 213 /*desc=*/[{ 214 Return true if the size `idx` is dynamic. 215 }], 216 /*retTy=*/"bool", 217 /*methodName=*/"isDynamicSize", 218 /*args=*/(ins "unsigned":$idx), 219 /*methodBody=*/"", 220 /*defaultImplementation=*/[{ 221 ::llvm::APInt v = *(static_sizes() 222 .template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 223 return ::mlir::ShapedType::isDynamic(v.getSExtValue()); 224 }] 225 >, 226 InterfaceMethod< 227 /*desc=*/[{ 228 Return true if the stride `idx` is dynamic. 229 }], 230 /*retTy=*/"bool", 231 /*methodName=*/"isDynamicStride", 232 /*args=*/(ins "unsigned":$idx), 233 /*methodBody=*/"", 234 /*defaultImplementation=*/[{ 235 ::llvm::APInt v = *(static_strides() 236 .template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 237 return ::mlir::ShapedType::isDynamicStrideOrOffset(v.getSExtValue()); 238 }] 239 >, 240 241 InterfaceMethod< 242 /*desc=*/[{ 243 Assert the offset `idx` is a static constant and return its value. 244 }], 245 /*retTy=*/"int64_t", 246 /*methodName=*/"getStaticOffset", 247 /*args=*/(ins "unsigned":$idx), 248 /*methodBody=*/"", 249 /*defaultImplementation=*/[{ 250 assert(!$_op.isDynamicOffset(idx) && "expected static offset"); 251 ::llvm::APInt v = *(static_offsets(). 252 template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 253 return v.getSExtValue(); 254 }] 255 >, 256 InterfaceMethod< 257 /*desc=*/[{ 258 Assert the size `idx` is a static constant and return its value. 259 }], 260 /*retTy=*/"int64_t", 261 /*methodName=*/"getStaticSize", 262 /*args=*/(ins "unsigned":$idx), 263 /*methodBody=*/"", 264 /*defaultImplementation=*/[{ 265 assert(!$_op.isDynamicSize(idx) && "expected static size"); 266 ::llvm::APInt v = *(static_sizes(). 267 template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 268 return v.getSExtValue(); 269 }] 270 >, 271 InterfaceMethod< 272 /*desc=*/[{ 273 Assert the stride `idx` is a static constant and return its value. 274 }], 275 /*retTy=*/"int64_t", 276 /*methodName=*/"getStaticStride", 277 /*args=*/(ins "unsigned":$idx), 278 /*methodBody=*/"", 279 /*defaultImplementation=*/[{ 280 assert(!$_op.isDynamicStride(idx) && "expected static stride"); 281 ::llvm::APInt v = *(static_strides(). 282 template getAsValueRange<::mlir::IntegerAttr>().begin() + idx); 283 return v.getSExtValue(); 284 }] 285 >, 286 287 InterfaceMethod< 288 /*desc=*/[{ 289 Assert the offset `idx` is dynamic and return the position of the 290 corresponding operand. 291 }], 292 /*retTy=*/"unsigned", 293 /*methodName=*/"getIndexOfDynamicOffset", 294 /*args=*/(ins "unsigned":$idx), 295 /*methodBody=*/"", 296 /*defaultImplementation=*/[{ 297 assert($_op.isDynamicOffset(idx) && "expected dynamic offset"); 298 auto numDynamic = getNumDynamicEntriesUpToIdx( 299 static_offsets().template cast<::mlir::ArrayAttr>(), 300 ::mlir::ShapedType::isDynamicStrideOrOffset, 301 idx); 302 return $_op.getOffsetSizeAndStrideStartOperandIndex() + numDynamic; 303 }] 304 >, 305 InterfaceMethod< 306 /*desc=*/[{ 307 Assert the size `idx` is dynamic and return the position of the 308 corresponding operand. 309 }], 310 /*retTy=*/"unsigned", 311 /*methodName=*/"getIndexOfDynamicSize", 312 /*args=*/(ins "unsigned":$idx), 313 /*methodBody=*/"", 314 /*defaultImplementation=*/[{ 315 assert($_op.isDynamicSize(idx) && "expected dynamic size"); 316 auto numDynamic = getNumDynamicEntriesUpToIdx( 317 static_sizes().template cast<::mlir::ArrayAttr>(), ::mlir::ShapedType::isDynamic, idx); 318 return $_op.getOffsetSizeAndStrideStartOperandIndex() + 319 offsets().size() + numDynamic; 320 }] 321 >, 322 InterfaceMethod< 323 /*desc=*/[{ 324 Assert the stride `idx` is dynamic and return the position of the 325 corresponding operand. 326 }], 327 /*retTy=*/"unsigned", 328 /*methodName=*/"getIndexOfDynamicStride", 329 /*args=*/(ins "unsigned":$idx), 330 /*methodBody=*/"", 331 /*defaultImplementation=*/[{ 332 assert($_op.isDynamicStride(idx) && "expected dynamic stride"); 333 auto numDynamic = getNumDynamicEntriesUpToIdx( 334 static_strides().template cast<::mlir::ArrayAttr>(), 335 ::mlir::ShapedType::isDynamicStrideOrOffset, 336 idx); 337 return $_op.getOffsetSizeAndStrideStartOperandIndex() + 338 offsets().size() + sizes().size() + numDynamic; 339 }] 340 >, 341 InterfaceMethod< 342 /*desc=*/[{ 343 Helper method to compute the number of dynamic entries of `attr`, up to 344 `idx` using `isDynamic` to determine whether an entry is dynamic. 345 }], 346 /*retTy=*/"unsigned", 347 /*methodName=*/"getNumDynamicEntriesUpToIdx", 348 /*args=*/(ins "::mlir::ArrayAttr":$attr, 349 "::llvm::function_ref<bool(int64_t)>":$isDynamic, 350 "unsigned":$idx), 351 /*methodBody=*/"", 352 /*defaultImplementation=*/[{ 353 return std::count_if( 354 attr.getValue().begin(), attr.getValue().begin() + idx, 355 [&](::mlir::Attribute attr) { 356 return isDynamic(attr.cast<::mlir::IntegerAttr>().getInt()); 357 }); 358 }] 359 >, 360 361 InterfaceMethod< 362 /*desc=*/[{ 363 Assert the offset `idx` is dynamic and return its value. 364 }], 365 /*retTy=*/"::mlir::Value", 366 /*methodName=*/"getDynamicOffset", 367 /*args=*/(ins "unsigned":$idx), 368 /*methodBody=*/"", 369 /*defaultImplementation=*/[{ 370 return $_op.getOperand(getIndexOfDynamicOffset(idx)); 371 }] 372 >, 373 InterfaceMethod< 374 /*desc=*/[{ 375 Assert the size `idx` is dynamic and return its value. 376 }], 377 /*retTy=*/"::mlir::Value", 378 /*methodName=*/"getDynamicSize", 379 /*args=*/(ins "unsigned":$idx), 380 /*methodBody=*/"", 381 /*defaultImplementation=*/[{ 382 return $_op.getOperand(getIndexOfDynamicSize(idx)); 383 }] 384 >, 385 InterfaceMethod< 386 /*desc=*/[{ 387 Assert the stride `idx` is dynamic and return its value. 388 }], 389 /*retTy=*/"::mlir::Value", 390 /*methodName=*/"getDynamicStride", 391 /*args=*/(ins "unsigned":$idx), 392 /*methodBody=*/"", 393 /*defaultImplementation=*/[{ 394 return $_op.getOperand(getIndexOfDynamicStride(idx)); 395 }] 396 >, 397 InterfaceMethod< 398 /*desc=*/[{ 399 Return true if all `other`'s offsets, sizes and strides are the same. 400 Takes a custom `cmp` comparison function on OpFoldResult to avoid taking 401 a dialect dependence. 402 }], 403 /*retTy=*/"bool", 404 /*methodName=*/"isSameAs", 405 /*args=*/(ins "::mlir::OffsetSizeAndStrideOpInterface":$other, 406 "::llvm::function_ref<bool(::mlir::OpFoldResult, ::mlir::OpFoldResult)>":$cmp), 407 /*methodBody=*/"", 408 /*defaultImplementation=*/[{ 409 return ::mlir::detail::sameOffsetsSizesAndStrides( 410 ::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>( 411 $_op.getOperation()), other, cmp); 412 }] 413 >, 414 InterfaceMethod< 415 /*desc=*/[{ Return true if all strides are guaranteed to be 1. }], 416 /*retTy=*/"bool", 417 /*methodName=*/"hasUnitStride", 418 /*args=*/(ins), 419 /*methodBody=*/"", 420 /*defaultImplementation=*/[{ 421 return ::llvm::all_of(getMixedStrides(), [](::mlir::OpFoldResult ofr) { 422 return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(1); 423 }); 424 }] 425 >, 426 InterfaceMethod< 427 /*desc=*/[{ Return true if all offsets are guaranteed to be 0. }], 428 /*retTy=*/"bool", 429 /*methodName=*/"hasZeroOffset", 430 /*args=*/(ins), 431 /*methodBody=*/"", 432 /*defaultImplementation=*/[{ 433 return ::llvm::all_of(getMixedOffsets(), [](::mlir::OpFoldResult ofr) { 434 return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(0); 435 }); 436 }] 437 >, 438 ]; 439 440 let extraClassDeclaration = [{ 441 static unsigned getOffsetOperandGroupPosition() { return 0; } 442 static unsigned getSizeOperandGroupPosition() { return 1; } 443 static unsigned getStrideOperandGroupPosition() { return 2; } 444 static ::llvm::StringRef getStaticOffsetsAttrName() { 445 return "static_offsets"; 446 } 447 static ::llvm::StringRef getStaticSizesAttrName() { 448 return "static_sizes"; 449 } 450 static ::llvm::StringRef getStaticStridesAttrName() { 451 return "static_strides"; 452 } 453 static ::llvm::ArrayRef<::llvm::StringRef> getSpecialAttrNames() { 454 static ::llvm::SmallVector<::llvm::StringRef, 4> names{ 455 ::mlir::OffsetSizeAndStrideOpInterface::getStaticOffsetsAttrName(), 456 ::mlir::OffsetSizeAndStrideOpInterface::getStaticSizesAttrName(), 457 ::mlir::OffsetSizeAndStrideOpInterface::getStaticStridesAttrName(), 458 ::mlir::OpTrait::AttrSizedOperandSegments<void>::getOperandSegmentSizeAttr()}; 459 return names; 460 } 461 }]; 462 463 let verify = [{ 464 return ::mlir::detail::verifyOffsetSizeAndStrideOp( 465 ::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>($_op)); 466 }]; 467} 468 469#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE 470