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::kDynamic`, then the corresponding entry is a dynamic 54 offset (resp. size, stride). 55 4. a variadic `offset` (resp. `sizes`, `strides`) operand must be present 56 for each dynamic offset (resp. size, stride). 57 5. `offsets`, `sizes` and `strides` operands are specified in this order 58 at operand index starting at `getOffsetSizeAndStrideStartOperandIndex`. 59 6. `offsets` and `sizes` operands are non-negative. 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=*/"getOffsets", 93 /*args=*/(ins), 94 /*methodBody=*/"", 95 /*defaultImplementation=*/[{ 96 return $_op.getOffsets(); 97 }] 98 >, 99 InterfaceMethod< 100 /*desc=*/[{ 101 Return the dynamic size operands. 102 }], 103 /*retTy=*/"::mlir::OperandRange", 104 /*methodName=*/"getSizes", 105 /*args=*/(ins), 106 /*methodBody=*/"", 107 /*defaultImplementation=*/[{ 108 return $_op.getSizes(); 109 }] 110 >, 111 InterfaceMethod< 112 /*desc=*/[{ 113 Return the dynamic stride operands. 114 }], 115 /*retTy=*/"::mlir::OperandRange", 116 /*methodName=*/"getStrides", 117 /*args=*/(ins), 118 /*methodBody=*/"", 119 /*defaultImplementation=*/[{ 120 return $_op.getStrides(); 121 }] 122 >, 123 InterfaceMethod< 124 /*desc=*/[{ 125 Return the static offset attributes. 126 }], 127 /*retTy=*/"::llvm::ArrayRef<int64_t>", 128 /*methodName=*/"getStaticOffsets", 129 /*args=*/(ins), 130 /*methodBody=*/"", 131 /*defaultImplementation=*/[{ 132 return $_op.getStaticOffsets(); 133 }] 134 >, 135 InterfaceMethod< 136 /*desc=*/[{ 137 Return the static size attributes. 138 }], 139 /*retTy=*/"::llvm::ArrayRef<int64_t>", 140 /*methodName=*/"getStaticSizes", 141 /*args=*/(ins), 142 /*methodBody=*/"", 143 /*defaultImplementation=*/[{ 144 return $_op.getStaticSizes(); 145 }] 146 >, 147 InterfaceMethod< 148 /*desc=*/[{ 149 Return the dynamic stride attributes. 150 }], 151 /*retTy=*/"::llvm::ArrayRef<int64_t>", 152 /*methodName=*/"getStaticStrides", 153 /*args=*/(ins), 154 /*methodBody=*/"", 155 /*defaultImplementation=*/[{ 156 return $_op.getStaticStrides(); 157 }] 158 >, 159 InterfaceMethod< 160 /*desc=*/[{ 161 Return a vector of all the static or dynamic offsets of the op. 162 }], 163 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 164 /*methodName=*/"getMixedOffsets", 165 /*args=*/(ins), 166 /*methodBody=*/"", 167 /*defaultImplementation=*/[{ 168 Builder b($_op->getContext()); 169 return ::mlir::getMixedValues($_op.getStaticOffsets(), 170 $_op.getOffsets(), b); 171 }] 172 >, 173 InterfaceMethod< 174 /*desc=*/[{ 175 Return a vector of all the static or dynamic sizes of the op. 176 }], 177 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 178 /*methodName=*/"getMixedSizes", 179 /*args=*/(ins), 180 /*methodBody=*/"", 181 /*defaultImplementation=*/[{ 182 Builder b($_op->getContext()); 183 return 184 ::mlir::getMixedValues($_op.getStaticSizes(), $_op.getSizes(), b); 185 }] 186 >, 187 InterfaceMethod< 188 /*desc=*/[{ 189 Return a vector of all the static or dynamic strides of the op. 190 }], 191 /*retTy=*/"::llvm::SmallVector<::mlir::OpFoldResult, 4>", 192 /*methodName=*/"getMixedStrides", 193 /*args=*/(ins), 194 /*methodBody=*/"", 195 /*defaultImplementation=*/[{ 196 Builder b($_op->getContext()); 197 return ::mlir::getMixedValues($_op.getStaticStrides(), 198 $_op.getStrides(), b); 199 }] 200 >, 201 202 InterfaceMethod< 203 /*desc=*/"Return true if the offset `idx` is dynamic.", 204 /*retTy=*/"bool", 205 /*methodName=*/"isDynamicOffset", 206 /*args=*/(ins "unsigned":$idx), 207 /*methodBody=*/"", 208 /*defaultImplementation=*/[{ 209 return ::mlir::ShapedType::isDynamic(getStaticOffsets()[idx]); 210 }] 211 >, 212 InterfaceMethod< 213 /*desc=*/"Return true if the size `idx` is dynamic.", 214 /*retTy=*/"bool", 215 /*methodName=*/"isDynamicSize", 216 /*args=*/(ins "unsigned":$idx), 217 /*methodBody=*/"", 218 /*defaultImplementation=*/[{ 219 return ::mlir::ShapedType::isDynamic(getStaticSizes()[idx]); 220 }] 221 >, 222 InterfaceMethod< 223 /*desc=*/"Return true if the stride `idx` is dynamic.", 224 /*retTy=*/"bool", 225 /*methodName=*/"isDynamicStride", 226 /*args=*/(ins "unsigned":$idx), 227 /*methodBody=*/"", 228 /*defaultImplementation=*/[{ 229 return ::mlir::ShapedType::isDynamic(getStaticStrides()[idx]); 230 }] 231 >, 232 InterfaceMethod< 233 /*desc=*/[{ 234 Assert the offset `idx` is a static constant and return its value. 235 }], 236 /*retTy=*/"int64_t", 237 /*methodName=*/"getStaticOffset", 238 /*args=*/(ins "unsigned":$idx), 239 /*methodBody=*/"", 240 /*defaultImplementation=*/[{ 241 assert(!$_op.isDynamicOffset(idx) && "expected static offset"); 242 return getStaticOffsets()[idx]; 243 }] 244 >, 245 InterfaceMethod< 246 /*desc=*/[{ 247 Assert the size `idx` is a static constant and return its value. 248 }], 249 /*retTy=*/"int64_t", 250 /*methodName=*/"getStaticSize", 251 /*args=*/(ins "unsigned":$idx), 252 /*methodBody=*/"", 253 /*defaultImplementation=*/[{ 254 assert(!$_op.isDynamicSize(idx) && "expected static size"); 255 return getStaticSizes()[idx]; 256 }] 257 >, 258 InterfaceMethod< 259 /*desc=*/[{ 260 Assert the stride `idx` is a static constant and return its value. 261 }], 262 /*retTy=*/"int64_t", 263 /*methodName=*/"getStaticStride", 264 /*args=*/(ins "unsigned":$idx), 265 /*methodBody=*/"", 266 /*defaultImplementation=*/[{ 267 assert(!$_op.isDynamicStride(idx) && "expected static stride"); 268 return getStaticStrides()[idx]; 269 }] 270 >, 271 272 InterfaceMethod< 273 /*desc=*/[{ 274 Assert the offset `idx` is dynamic and return the position of the 275 corresponding operand. 276 }], 277 /*retTy=*/"unsigned", 278 /*methodName=*/"getIndexOfDynamicOffset", 279 /*args=*/(ins "unsigned":$idx), 280 /*methodBody=*/"", 281 /*defaultImplementation=*/[{ 282 assert($_op.isDynamicOffset(idx) && "expected dynamic offset"); 283 auto numDynamic = ::mlir::detail::getNumDynamicEntriesUpToIdx( 284 getStaticOffsets(), idx); 285 return $_op.getOffsetSizeAndStrideStartOperandIndex() + numDynamic; 286 }] 287 >, 288 InterfaceMethod< 289 /*desc=*/[{ 290 Assert the size `idx` is dynamic and return the position of the 291 corresponding operand. 292 }], 293 /*retTy=*/"unsigned", 294 /*methodName=*/"getIndexOfDynamicSize", 295 /*args=*/(ins "unsigned":$idx), 296 /*methodBody=*/"", 297 /*defaultImplementation=*/[{ 298 assert($_op.isDynamicSize(idx) && "expected dynamic size"); 299 auto numDynamic = ::mlir::detail::getNumDynamicEntriesUpToIdx( 300 getStaticSizes(), idx); 301 return $_op.getOffsetSizeAndStrideStartOperandIndex() + 302 getOffsets().size() + numDynamic; 303 }] 304 >, 305 InterfaceMethod< 306 /*desc=*/[{ 307 Assert the stride `idx` is dynamic and return the position of the 308 corresponding operand. 309 }], 310 /*retTy=*/"unsigned", 311 /*methodName=*/"getIndexOfDynamicStride", 312 /*args=*/(ins "unsigned":$idx), 313 /*methodBody=*/"", 314 /*defaultImplementation=*/[{ 315 assert($_op.isDynamicStride(idx) && "expected dynamic stride"); 316 auto numDynamic = ::mlir::detail::getNumDynamicEntriesUpToIdx( 317 getStaticStrides(), idx); 318 return $_op.getOffsetSizeAndStrideStartOperandIndex() + 319 getOffsets().size() + getSizes().size() + numDynamic; 320 }] 321 >, 322 InterfaceMethod< 323 /*desc=*/[{ 324 Assert the offset `idx` is dynamic and return its value. 325 }], 326 /*retTy=*/"::mlir::Value", 327 /*methodName=*/"getDynamicOffset", 328 /*args=*/(ins "unsigned":$idx), 329 /*methodBody=*/"", 330 /*defaultImplementation=*/[{ 331 return $_op.getOperand(getIndexOfDynamicOffset(idx)); 332 }] 333 >, 334 InterfaceMethod< 335 /*desc=*/[{ 336 Assert the size `idx` is dynamic and return its value. 337 }], 338 /*retTy=*/"::mlir::Value", 339 /*methodName=*/"getDynamicSize", 340 /*args=*/(ins "unsigned":$idx), 341 /*methodBody=*/"", 342 /*defaultImplementation=*/[{ 343 return $_op.getOperand(getIndexOfDynamicSize(idx)); 344 }] 345 >, 346 InterfaceMethod< 347 /*desc=*/[{ 348 Assert the stride `idx` is dynamic and return its value. 349 }], 350 /*retTy=*/"::mlir::Value", 351 /*methodName=*/"getDynamicStride", 352 /*args=*/(ins "unsigned":$idx), 353 /*methodBody=*/"", 354 /*defaultImplementation=*/[{ 355 return $_op.getOperand(getIndexOfDynamicStride(idx)); 356 }] 357 >, 358 InterfaceMethod< 359 /*desc=*/[{ 360 Return true if all `other`'s offsets, sizes and strides are the same. 361 Takes a custom `cmp` comparison function on OpFoldResult to avoid taking 362 a dialect dependence. 363 }], 364 /*retTy=*/"bool", 365 /*methodName=*/"isSameAs", 366 /*args=*/(ins "::mlir::OffsetSizeAndStrideOpInterface":$other, 367 "::llvm::function_ref<bool(::mlir::OpFoldResult, ::mlir::OpFoldResult)>":$cmp), 368 /*methodBody=*/"", 369 /*defaultImplementation=*/[{ 370 return ::mlir::detail::sameOffsetsSizesAndStrides( 371 ::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>( 372 $_op.getOperation()), other, cmp); 373 }] 374 >, 375 InterfaceMethod< 376 /*desc=*/[{ Return true if all strides are guaranteed to be 1. }], 377 /*retTy=*/"bool", 378 /*methodName=*/"hasUnitStride", 379 /*args=*/(ins), 380 /*methodBody=*/"", 381 /*defaultImplementation=*/[{ 382 return ::llvm::all_of(getMixedStrides(), [](::mlir::OpFoldResult ofr) { 383 return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(1); 384 }); 385 }] 386 >, 387 InterfaceMethod< 388 /*desc=*/[{ Return true if all offsets are guaranteed to be 0. }], 389 /*retTy=*/"bool", 390 /*methodName=*/"hasZeroOffset", 391 /*args=*/(ins), 392 /*methodBody=*/"", 393 /*defaultImplementation=*/[{ 394 return ::llvm::all_of(getMixedOffsets(), [](::mlir::OpFoldResult ofr) { 395 return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(0); 396 }); 397 }] 398 >, 399 ]; 400 401 let verify = [{ 402 return ::mlir::detail::verifyOffsetSizeAndStrideOp( 403 ::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>($_op)); 404 }]; 405} 406 407#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE 408