Files
gps/tools/local/circt/include/mlir/Interfaces/IndexingMapOpInterface.td
T
2026-07-12 11:01:51 +03:00

154 lines
5.9 KiB
TableGen

//===- IndexingMapOpInterface.td - Interface Declaration -*- 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
//
//===----------------------------------------------------------------------===//
//
// This is the definition file for the IndexingMapOpInterface.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_INTERFACES_INDEXING_MAP_OP_INTERFACE
#define MLIR_INTERFACES_INDEXING_MAP_OP_INTERFACE
include "mlir/IR/OpBase.td"
def IndexingMapOpInterface : OpInterface<"IndexingMapOpInterface"> {
let description = [{
Interface for operations that connect an iteration domain to operands via
affine maps. Provides methods to access indexing maps between iteration
domain and operand index spaces.
}];
let cppNamespace = "::mlir";
let methods = [
InterfaceMethod<
/*desc=*/[{
Return the indexing maps attribute within the current operation.
}],
/*retTy=*/"ArrayAttr",
/*methodName=*/"getIndexingMaps"
>,
InterfaceMethod<
/*desc=*/[{
Return the indexing maps within the current operation.
}],
/*retTy=*/"SmallVector<AffineMap>",
/*methodName=*/"getIndexingMapsArray",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
auto range = $_op.getIndexingMaps()
.template getAsValueRange<AffineMapAttr>();
return {range.begin(), range.end()};
}]
>,
InterfaceMethod<
/*desc=*/[{
Return the input or output indexing map for `opOperand`.
}],
/*retTy=*/"AffineMap",
/*methodName=*/"getMatchingIndexingMap",
/*args=*/(ins "OpOperand*":$opOperand),
/*methodBody=*/"",
/*defaultImplementation=*/[{
assert(opOperand->getOwner() == this->getOperation());
auto indexingMaps =
$_op.getIndexingMaps().template getAsValueRange<AffineMapAttr>();
return *(indexingMaps.begin() + opOperand->getOperandNumber());
}]
>,
InterfaceMethod<
/*desc=*/[{
Hook to provide a custom AffineMap used to compute all the operand
subshapes given loop bounds. This is used to answer the question: "given
an iteration space over the codomain, what are the subshapes of the
operands involved in the computation".
The default behavior is to just concatenate all the indexing maps.
A custom AffineMap allows providing a map that can be used to
compute subshapes even in cases where the concatenation of indexing maps
(i.e. the data traversal order) is not a simple permutation of the loop
traversal order. It is then possible to define ops with skewed data
traversal order for which we can still easily compute hyperrectangular
loop bounds and subviews.
}],
/*retTy=*/"AffineMap",
/*methodName=*/"getLoopsToShapesMap",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
auto maps = $_op.getIndexingMapsArray();
return concatAffineMaps(maps, $_op.getContext());
}]
>,
InterfaceMethod<
/*desc=*/[{
Hook to provide a custom AffineMap used to construct the
hyperrectangular loop iteration space given all the operand subshapes.
This is used to answer the question:
"Given a list of operand ranges, what is the subportion of the iteration
space involved in the computation".
This is the inverse problem of `getLoopsToShapesMap`.
Return the empty AffineMap when such an AffineMap cannot be constructed.
The default behavior is based on a very simple inference procedure that
only works with permutation affine maps.
A more advanced Tensor-Comprehension like inference is possible but has
proven to be ambiguous in unfavorable case.
A safer and more robust alternative is to allow each op to define
its own AffineMap.
}],
/*retTy=*/"AffineMap",
/*methodName=*/"getShapesToLoopsMap",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
return inversePermutation($_op.getLoopsToShapesMap());
}]
>,
InterfaceMethod<
/*desc=*/[{
Returns the static shape of the underlying operand (note this is
op-specific behavior).
Returns ShapedType::kDynamic for non-statically-known loop ranges.
}],
/*retTy=*/"SmallVector<int64_t>",
/*methodName=*/"getStaticOperandShape",
/*args=*/(ins "OpOperand*":$opOperand),
/*methodBody=*/"",
/*defaultImplementation=*/[{
SmallVector<int64_t> res;
llvm::append_range(res, $_op.getShape(opOperand));
return res;
}]
>,
InterfaceMethod<
/*desc=*/[{
Returns loop ranges by composing `getShapesToLoopsMap()` with the
flattened list of operand shapes.
Returns ShapedType::kDynamic for non-statically-known loop ranges.
}],
/*retTy=*/"SmallVector<int64_t>",
/*methodName=*/"getStaticLoopRanges",
/*args=*/(ins),
/*methodBody=*/"",
/*defaultImplementation=*/[{
SmallVector<int64_t> allShapesSizes;
for (OpOperand &opOperand : this->getOperation()->getOpOperands())
llvm::append_range(allShapesSizes, $_op.getShape(&opOperand));
AffineMap invertedMap = $_op.getShapesToLoopsMap();
assert(invertedMap && "expected a valid op");
return invertedMap.compose(allShapesSizes);
}]
>
];
let extraClassDeclaration = [{
// Verifier implementation for IndexingMapOpInterface.
// This must be called manually as part of other verifiers so that the
// verification order, and meaningful error messages, are not preempted.
LogicalResult verifyImpl();
}];
}
#endif // MLIR_INTERFACES_INDEXING_MAP_OP_INTERFACE