blob: 50ebeaa44a5c3d704b959dd3e3c04437b0736036 [file] [log] [blame]
//===- ViewLikeInterface.td - ViewLike interface -----------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines the interface for view-like operations.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_INTERFACES_VIEWLIKEINTERFACE
#define MLIR_INTERFACES_VIEWLIKEINTERFACE
include "mlir/IR/OpBase.td"
def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> {
let description = [{
A view-like operation "views" a buffer in a potentially different way. It
takes in a (view of) buffer (and potentially some other operands) and returns
another view of buffer.
}];
let cppNamespace = "::mlir";
let methods = [
InterfaceMethod<
"Returns the source buffer from which the view is created.",
"::mlir::Value", "getViewSource">
];
}
def OffsetSizeAndStrideOpInterface : OpInterface<"OffsetSizeAndStrideOpInterface"> {
let description = [{
Common interface for ops that allow specifying mixed dynamic and static
offsets, sizes and strides variadic operands.
Ops that implement this interface need to expose the following methods:
1. `getArrayAttrMaxRanks` to specify the length of static integer
attributes.
2. `offsets`, `sizes` and `strides` variadic operands.
3. `static_offsets`, resp. `static_sizes` and `static_strides` integer
array attributes.
4. `getOffsetSizeAndStrideStartOperandIndex` method that specifies the
starting index of the OffsetSizeAndStrideOpInterface operands
The invariants of this interface are:
1. `static_offsets`, `static_sizes` and `static_strides` have length
exactly `getArrayAttrMaxRanks()`[0] (resp. [1], [2]).
2. `offsets`, `sizes` and `strides` have each length at most
`getArrayAttrMaxRanks()`[0] (resp. [1], [2]).
3. if an entry of `static_offsets` (resp. `static_sizes`,
`static_strides`) is equal to a special sentinel value, namely
`ShapedType::kDynamicStrideOrOffset` (resp. `ShapedType::kDynamicSize`,
`ShapedType::kDynamicStrideOrOffset`), then the corresponding entry is
a dynamic offset (resp. size, stride).
4. a variadic `offset` (resp. `sizes`, `strides`) operand must be present
for each dynamic offset (resp. size, stride).
5. `offsets`, `sizes` and `strides` operands are specified in this order
at operand index starting at `getOffsetSizeAndStrideStartOperandIndex`.
This interface is useful to factor out common behavior and provide support
for carrying or injecting static behavior through the use of the static
attributes.
}];
let cppNamespace = "::mlir";
let methods = [
StaticInterfaceMethod<
/*desc=*/[{
Return the number of leading operands before the `offsets`, `sizes` and
and `strides` operands.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getOffsetSizeAndStrideStartOperandIndex",
/*args=*/(ins)
>,
InterfaceMethod<
/*desc=*/[{
Return the expected rank of each of the`static_offsets`, `static_sizes`
and `static_strides` attributes.
}],
/*retTy=*/"std::array<unsigned, 3>",
/*methodName=*/"getArrayAttrMaxRanks",
/*args=*/(ins)
>,
InterfaceMethod<
/*desc=*/[{
Return the dynamic offset operands.
}],
/*retTy=*/"::mlir::OperandRange",
/*methodName=*/"offsets",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.offsets();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the dynamic size operands.
}],
/*retTy=*/"::mlir::OperandRange",
/*methodName=*/"sizes",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.sizes();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the dynamic stride operands.
}],
/*retTy=*/"::mlir::OperandRange",
/*methodName=*/"strides",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.strides();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the static offset attributes.
}],
/*retTy=*/"::mlir::ArrayAttr",
/*methodName=*/"static_offsets",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.static_offsets();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the static size attributes.
}],
/*retTy=*/"::mlir::ArrayAttr",
/*methodName=*/"static_sizes",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.static_sizes();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the dynamic stride attributes.
}],
/*retTy=*/"::mlir::ArrayAttr",
/*methodName=*/"static_strides",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.static_strides();
}]
>,
InterfaceMethod<
/*desc=*/[{
Return a vector of all the static or dynamic sizes of the op.
}],
/*retTy=*/"::mlir::SmallVector<::mlir::OpFoldResult, 4>",
/*methodName=*/"getMixedOffsets",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::mlir::SmallVector<::mlir::OpFoldResult, 4> res;
unsigned numDynamic = 0;
unsigned count = $_op.static_offsets().size();
for (unsigned idx = 0; idx < count; ++idx) {
if (isDynamicOffset(idx))
res.push_back($_op.offsets()[numDynamic++]);
else
res.push_back($_op.static_offsets()[idx]);
}
return res;
}]
>,
InterfaceMethod<
/*desc=*/[{
Return a vector of all the static or dynamic sizes of the op.
}],
/*retTy=*/"::mlir::SmallVector<::mlir::OpFoldResult, 4>",
/*methodName=*/"getMixedSizes",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::mlir::SmallVector<::mlir::OpFoldResult, 4> res;
unsigned numDynamic = 0;
unsigned count = $_op.static_sizes().size();
for (unsigned idx = 0; idx < count; ++idx) {
if (isDynamicSize(idx))
res.push_back($_op.sizes()[numDynamic++]);
else
res.push_back($_op.static_sizes()[idx]);
}
return res;
}]
>,
InterfaceMethod<
/*desc=*/[{
Return a vector of all the static or dynamic strides of the op.
}],
/*retTy=*/"::mlir::SmallVector<::mlir::OpFoldResult, 4>",
/*methodName=*/"getMixedStrides",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::mlir::SmallVector<::mlir::OpFoldResult, 4> res;
unsigned numDynamic = 0;
unsigned count = $_op.static_strides().size();
for (unsigned idx = 0; idx < count; ++idx) {
if (isDynamicStride(idx))
res.push_back($_op.strides()[numDynamic++]);
else
res.push_back($_op.static_strides()[idx]);
}
return res;
}]
>,
InterfaceMethod<
/*desc=*/[{
Return true if the offset `idx` is dynamic.
}],
/*retTy=*/"bool",
/*methodName=*/"isDynamicOffset",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::llvm::APInt v = *(static_offsets()
.template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return ::mlir::ShapedType::isDynamicStrideOrOffset(v.getSExtValue());
}]
>,
InterfaceMethod<
/*desc=*/[{
Return true if the size `idx` is dynamic.
}],
/*retTy=*/"bool",
/*methodName=*/"isDynamicSize",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::llvm::APInt v = *(static_sizes()
.template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return ::mlir::ShapedType::isDynamic(v.getSExtValue());
}]
>,
InterfaceMethod<
/*desc=*/[{
Return true if the stride `idx` is dynamic.
}],
/*retTy=*/"bool",
/*methodName=*/"isDynamicStride",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
::llvm::APInt v = *(static_strides()
.template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return ::mlir::ShapedType::isDynamicStrideOrOffset(v.getSExtValue());
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the offset `idx` is a static constant and return its value.
}],
/*retTy=*/"int64_t",
/*methodName=*/"getStaticOffset",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert(!$_op.isDynamicOffset(idx) && "expected static offset");
::llvm::APInt v = *(static_offsets().
template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return v.getSExtValue();
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the size `idx` is a static constant and return its value.
}],
/*retTy=*/"int64_t",
/*methodName=*/"getStaticSize",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert(!$_op.isDynamicSize(idx) && "expected static size");
::llvm::APInt v = *(static_sizes().
template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return v.getSExtValue();
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the stride `idx` is a static constant and return its value.
}],
/*retTy=*/"int64_t",
/*methodName=*/"getStaticStride",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert(!$_op.isDynamicStride(idx) && "expected static stride");
::llvm::APInt v = *(static_strides().
template getAsValueRange<::mlir::IntegerAttr>().begin() + idx);
return v.getSExtValue();
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the offset `idx` is dynamic and return the position of the
corresponding operand.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getIndexOfDynamicOffset",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert($_op.isDynamicOffset(idx) && "expected dynamic offset");
auto numDynamic = getNumDynamicEntriesUpToIdx(
static_offsets().template cast<::mlir::ArrayAttr>(),
::mlir::ShapedType::isDynamicStrideOrOffset,
idx);
return $_op.getOffsetSizeAndStrideStartOperandIndex() + numDynamic;
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the size `idx` is dynamic and return the position of the
corresponding operand.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getIndexOfDynamicSize",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert($_op.isDynamicSize(idx) && "expected dynamic size");
auto numDynamic = getNumDynamicEntriesUpToIdx(
static_sizes().template cast<::mlir::ArrayAttr>(), ::mlir::ShapedType::isDynamic, idx);
return $_op.getOffsetSizeAndStrideStartOperandIndex() +
offsets().size() + numDynamic;
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the stride `idx` is dynamic and return the position of the
corresponding operand.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getIndexOfDynamicStride",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert($_op.isDynamicStride(idx) && "expected dynamic stride");
auto numDynamic = getNumDynamicEntriesUpToIdx(
static_strides().template cast<::mlir::ArrayAttr>(),
::mlir::ShapedType::isDynamicStrideOrOffset,
idx);
return $_op.getOffsetSizeAndStrideStartOperandIndex() +
offsets().size() + sizes().size() + numDynamic;
}]
>,
InterfaceMethod<
/*desc=*/[{
Helper method to compute the number of dynamic entries of `attr`, up to
`idx` using `isDynamic` to determine whether an entry is dynamic.
}],
/*retTy=*/"unsigned",
/*methodName=*/"getNumDynamicEntriesUpToIdx",
/*args=*/(ins "::mlir::ArrayAttr":$attr,
"::llvm::function_ref<bool(int64_t)>":$isDynamic,
"unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return std::count_if(
attr.getValue().begin(), attr.getValue().begin() + idx,
[&](::mlir::Attribute attr) {
return isDynamic(attr.cast<::mlir::IntegerAttr>().getInt());
});
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the offset `idx` is dynamic and return its value.
}],
/*retTy=*/"::mlir::Value",
/*methodName=*/"getDynamicOffset",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.getOperand(getIndexOfDynamicOffset(idx));
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the size `idx` is dynamic and return its value.
}],
/*retTy=*/"::mlir::Value",
/*methodName=*/"getDynamicSize",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.getOperand(getIndexOfDynamicSize(idx));
}]
>,
InterfaceMethod<
/*desc=*/[{
Assert the stride `idx` is dynamic and return its value.
}],
/*retTy=*/"::mlir::Value",
/*methodName=*/"getDynamicStride",
/*args=*/(ins "unsigned":$idx),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return $_op.getOperand(getIndexOfDynamicStride(idx));
}]
>,
InterfaceMethod<
/*desc=*/[{
Return true if all `other`'s offsets, sizes and strides are the same.
Takes a custom `cmp` comparison function on OpFoldResult to avoid taking
a dialect dependence.
}],
/*retTy=*/"bool",
/*methodName=*/"isSameAs",
/*args=*/(ins "::mlir::OffsetSizeAndStrideOpInterface":$other,
"::llvm::function_ref<bool(::mlir::OpFoldResult, ::mlir::OpFoldResult)>":$cmp),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return ::mlir::detail::sameOffsetsSizesAndStrides(
::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>(
$_op.getOperation()), other, cmp);
}]
>,
InterfaceMethod<
/*desc=*/[{ Return true if all strides are guaranteed to be 1. }],
/*retTy=*/"bool",
/*methodName=*/"hasUnitStride",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return ::llvm::all_of(getMixedStrides(), [](::mlir::OpFoldResult ofr) {
return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(1);
});
}]
>,
InterfaceMethod<
/*desc=*/[{ Return true if all offsets are guaranteed to be 0. }],
/*retTy=*/"bool",
/*methodName=*/"hasZeroOffset",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return ::llvm::all_of(getMixedOffsets(), [](::mlir::OpFoldResult ofr) {
return ::mlir::getConstantIntValue(ofr) == static_cast<int64_t>(0);
});
}]
>,
];
let extraClassDeclaration = [{
static unsigned getOffsetOperandGroupPosition() { return 0; }
static unsigned getSizeOperandGroupPosition() { return 1; }
static unsigned getStrideOperandGroupPosition() { return 2; }
static ::llvm::StringRef getStaticOffsetsAttrName() {
return "static_offsets";
}
static ::llvm::StringRef getStaticSizesAttrName() {
return "static_sizes";
}
static ::llvm::StringRef getStaticStridesAttrName() {
return "static_strides";
}
static ::llvm::ArrayRef<::llvm::StringRef> getSpecialAttrNames() {
static ::llvm::SmallVector<::llvm::StringRef, 4> names{
::mlir::OffsetSizeAndStrideOpInterface::getStaticOffsetsAttrName(),
::mlir::OffsetSizeAndStrideOpInterface::getStaticSizesAttrName(),
::mlir::OffsetSizeAndStrideOpInterface::getStaticStridesAttrName(),
::mlir::OpTrait::AttrSizedOperandSegments<void>::getOperandSegmentSizeAttr()};
return names;
}
}];
let verify = [{
return ::mlir::detail::verifyOffsetSizeAndStrideOp(
::mlir::cast<::mlir::OffsetSizeAndStrideOpInterface>($_op));
}];
}
#endif // MLIR_INTERFACES_VIEWLIKEINTERFACE