Files
gps/tools/local/circt/include/mlir/Dialect/Linalg/IR/LinalgInterfaces.h.inc
T
2026-07-12 11:01:51 +03:00

1865 lines
102 KiB
C++

/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* Interface Declarations *|
|* *|
|* Automatically generated file, do not edit! *|
|* *|
\*===----------------------------------------------------------------------===*/
namespace mlir::linalg {
/// A Linalg contraction is defined in general terms:
/// 1. Has 2 input and 1 output shapes.
/// 2. Has at least one reduction dimension.
/// 3. Has only projected permutation indexing maps.
/// 4. its body computes `u5(u1(c) + u2(u3(a) * u4(b)))` on some field
/// (AddOpType, MulOpType), where u1, u2, u3, u4 and u5 represent scalar unary
/// operations that may change the type (e.g. for mixed-precision).
/// As a consequence, when vectorization of such an op occurs, the only special
/// behavior is that the (unique) MulOpType is vectorized into a
/// `vector.contract`. All other ops are handled in a generic fashion.
/// In the future, we may wish to allow more input arguments and elementwise and
/// constant operations that do not involve the reduction dimension(s).
class ContractionOpInterface;
} // namespace mlir::linalg
namespace mlir::linalg {
/// A convolution is defined in general terms:
/// 1. Has an `image` and a `filter` operand.
/// 2. Has one `output` operand.
/// 3. The indexing maps of the input have expressions that satisfy
/// ```
/// AffineExpr ::== AffineDimExpr | ConvolvedExpr
/// ConvolvedExpr ::== MulExpr (`+` MulExpr)+
/// MulExpr ::== AffineDimExpr (`*` (AffineConstantExpr | AffineSymbolExpr))?
/// ```
/// 4. The filter and the output have projected permutation maps.
/// 5. Each of the loops can be qualified as one of,
/// - Loop over batch dimension,
/// - Loop over output image dimensions,
/// - Loop over output channel dimensions,
/// - Loop over convolved filter dimensions,
/// - Loop over input channel dimension.
class ConvolutionOpInterface;
} // namespace mlir::linalg
namespace mlir::linalg {
/// A fill operation is defined in general terms:
/// 1. Has a scalar `value` operand.
/// 2. Has one `output` operand.
class FillOpInterface;
} // namespace mlir::linalg
namespace mlir::linalg {
class LinalgOp;
} // namespace mlir::linalg
namespace mlir::linalg {
/// Interface for decomposing aggregated operations into a sequence of simpler
/// ops.
class AggregatedOpInterface;
} // namespace mlir::linalg
namespace mlir::linalg {
/// A Linalg contraction is defined in general terms:
/// 1. Has 2 input and 1 output shapes.
/// 2. Has at least one reduction dimension.
/// 3. Has only projected permutation indexing maps.
/// 4. its body computes `u5(u1(c) + u2(u3(a) * u4(b)))` on some field
/// (AddOpType, MulOpType), where u1, u2, u3, u4 and u5 represent scalar unary
/// operations that may change the type (e.g. for mixed-precision).
/// As a consequence, when vectorization of such an op occurs, the only special
/// behavior is that the (unique) MulOpType is vectorized into a
/// `vector.contract`. All other ops are handled in a generic fashion.
/// In the future, we may wish to allow more input arguments and elementwise and
/// constant operations that do not involve the reduction dimension(s).
namespace detail {
struct ContractionOpInterfaceInterfaceTraits {
struct Concept {
/// The methods defined by the interface.
Value (*lhs)(const Concept *impl, ::mlir::Operation *);
Value (*rhs)(const Concept *impl, ::mlir::Operation *);
bool (*isRowMajorMatmul)(const Concept *impl, ::mlir::Operation *);
bool (*isColumnMajorMatmul)(const Concept *impl, ::mlir::Operation *);
bool (*isRowMajorBatchMatmul)(const Concept *impl, ::mlir::Operation *);
bool (*isVecmat)(const Concept *impl, ::mlir::Operation *);
bool (*isBatchVecmat)(const Concept *impl, ::mlir::Operation *);
bool (*isMatvec)(const Concept *impl, ::mlir::Operation *);
bool (*isBatchMatvec)(const Concept *impl, ::mlir::Operation *);
};
template<typename ConcreteOp>
class Model : public Concept {
public:
using Interface = ::mlir::linalg::ContractionOpInterface;
Model() : Concept{lhs, rhs, isRowMajorMatmul, isColumnMajorMatmul, isRowMajorBatchMatmul, isVecmat, isBatchVecmat, isMatvec, isBatchMatvec} {}
static inline Value lhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value rhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isRowMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isColumnMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isRowMajorBatchMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isBatchVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isBatchMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteOp>
class FallbackModel : public Concept {
public:
using Interface = ::mlir::linalg::ContractionOpInterface;
FallbackModel() : Concept{lhs, rhs, isRowMajorMatmul, isColumnMajorMatmul, isRowMajorBatchMatmul, isVecmat, isBatchVecmat, isMatvec, isBatchMatvec} {}
static inline Value lhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value rhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isRowMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isColumnMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isRowMajorBatchMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isBatchVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isBatchMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteModel, typename ConcreteOp>
class ExternalModel : public FallbackModel<ConcreteModel> {
public:
using ConcreteEntity = ConcreteOp;
};
};
template <typename ConcreteOp>
struct ContractionOpInterfaceTrait;
} // namespace detail
class ContractionOpInterface : public ::mlir::OpInterface<ContractionOpInterface, detail::ContractionOpInterfaceInterfaceTraits> {
public:
using ::mlir::OpInterface<ContractionOpInterface, detail::ContractionOpInterfaceInterfaceTraits>::OpInterface;
template <typename ConcreteOp>
struct Trait : public detail::ContractionOpInterfaceTrait<ConcreteOp> {};
/// Returns the left-hand side operand.
Value lhs();
/// Returns the right-hand side operand.
Value rhs();
/// Returns whether the given op has indexing maps that correspond to a
/// row-major matmul operation.
bool isRowMajorMatmul();
/// Returns whether the given op has indexing maps that correspond to a
/// column-major matmul operation.
bool isColumnMajorMatmul();
/// Returns whether the given op has indexing maps that correspond to a
/// row-major batch matmul operation.
bool isRowMajorBatchMatmul();
/// Returns whether the given op has indexing maps that correspond to a
/// vector-matrix multiplication.
bool isVecmat();
/// Returns whether the given op has indexing maps that correspond to a
/// batched vector-matrix multiplication.
bool isBatchVecmat();
/// Returns whether the given op has indexing maps that correspond to a
/// matrix-vector multiplication.
bool isMatvec();
/// Returns whether the given op has indexing maps that correspond to a
/// batched matrix-vector multiplication.
bool isBatchMatvec();
};
} // namespace mlir::linalg
namespace mlir::linalg {
/// A convolution is defined in general terms:
/// 1. Has an `image` and a `filter` operand.
/// 2. Has one `output` operand.
/// 3. The indexing maps of the input have expressions that satisfy
/// ```
/// AffineExpr ::== AffineDimExpr | ConvolvedExpr
/// ConvolvedExpr ::== MulExpr (`+` MulExpr)+
/// MulExpr ::== AffineDimExpr (`*` (AffineConstantExpr | AffineSymbolExpr))?
/// ```
/// 4. The filter and the output have projected permutation maps.
/// 5. Each of the loops can be qualified as one of,
/// - Loop over batch dimension,
/// - Loop over output image dimensions,
/// - Loop over output channel dimensions,
/// - Loop over convolved filter dimensions,
/// - Loop over input channel dimension.
namespace detail {
struct ConvolutionOpInterfaceInterfaceTraits {
struct Concept {
/// The methods defined by the interface.
Value (*image)(const Concept *impl, ::mlir::Operation *);
Value (*filter)(const Concept *impl, ::mlir::Operation *);
};
template<typename ConcreteOp>
class Model : public Concept {
public:
using Interface = ::mlir::linalg::ConvolutionOpInterface;
Model() : Concept{image, filter} {}
static inline Value image(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value filter(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteOp>
class FallbackModel : public Concept {
public:
using Interface = ::mlir::linalg::ConvolutionOpInterface;
FallbackModel() : Concept{image, filter} {}
static inline Value image(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value filter(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteModel, typename ConcreteOp>
class ExternalModel : public FallbackModel<ConcreteModel> {
public:
using ConcreteEntity = ConcreteOp;
Value image(::mlir::Operation *tablegen_opaque_val) const;
Value filter(::mlir::Operation *tablegen_opaque_val) const;
};
};
template <typename ConcreteOp>
struct ConvolutionOpInterfaceTrait;
} // namespace detail
class ConvolutionOpInterface : public ::mlir::OpInterface<ConvolutionOpInterface, detail::ConvolutionOpInterfaceInterfaceTraits> {
public:
using ::mlir::OpInterface<ConvolutionOpInterface, detail::ConvolutionOpInterfaceInterfaceTraits>::OpInterface;
template <typename ConcreteOp>
struct Trait : public detail::ConvolutionOpInterfaceTrait<ConcreteOp> {};
/// Return the image operand.
Value image();
/// Return the filter operand.
Value filter();
};
} // namespace mlir::linalg
namespace mlir::linalg {
/// A fill operation is defined in general terms:
/// 1. Has a scalar `value` operand.
/// 2. Has one `output` operand.
namespace detail {
struct FillOpInterfaceInterfaceTraits {
struct Concept {
/// The methods defined by the interface.
Value (*value)(const Concept *impl, ::mlir::Operation *);
Value (*output)(const Concept *impl, ::mlir::Operation *);
Value (*result)(const Concept *impl, ::mlir::Operation *);
};
template<typename ConcreteOp>
class Model : public Concept {
public:
using Interface = ::mlir::linalg::FillOpInterface;
Model() : Concept{value, output, result} {}
static inline Value value(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value output(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value result(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteOp>
class FallbackModel : public Concept {
public:
using Interface = ::mlir::linalg::FillOpInterface;
FallbackModel() : Concept{value, output, result} {}
static inline Value value(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value output(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Value result(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteModel, typename ConcreteOp>
class ExternalModel : public FallbackModel<ConcreteModel> {
public:
using ConcreteEntity = ConcreteOp;
Value value(::mlir::Operation *tablegen_opaque_val) const;
Value output(::mlir::Operation *tablegen_opaque_val) const;
Value result(::mlir::Operation *tablegen_opaque_val) const;
};
};
template <typename ConcreteOp>
struct FillOpInterfaceTrait;
} // namespace detail
class FillOpInterface : public ::mlir::OpInterface<FillOpInterface, detail::FillOpInterfaceInterfaceTraits> {
public:
using ::mlir::OpInterface<FillOpInterface, detail::FillOpInterfaceInterfaceTraits>::OpInterface;
template <typename ConcreteOp>
struct Trait : public detail::FillOpInterfaceTrait<ConcreteOp> {};
/// Return the fill value.
Value value();
/// Return the output operand.
Value output();
/// Return the result.
Value result();
};
} // namespace mlir::linalg
namespace mlir::linalg {
namespace detail {
struct LinalgOpInterfaceTraits {
struct Concept {
/// The methods defined by the interface.
unsigned (*getNumParallelLoops)(const Concept *impl, ::mlir::Operation *);
bool (*isAllParallelLoops)(const Concept *impl, ::mlir::Operation *);
void (*getParallelDims)(const Concept *impl, ::mlir::Operation *, SmallVectorImpl<unsigned> &);
unsigned (*getNumReductionLoops)(const Concept *impl, ::mlir::Operation *);
void (*getReductionDims)(const Concept *impl, ::mlir::Operation *, SmallVectorImpl<unsigned> &);
unsigned (*getNumLoops)(const Concept *impl, ::mlir::Operation *);
bool (*hasSingleReductionLoop)(const Concept *impl, ::mlir::Operation *);
bool (*payloadUsesValueFromOperand)(const Concept *impl, ::mlir::Operation *, OpOperand *);
bool (*isSingleInputOutput)(const Concept *impl, ::mlir::Operation *);
bool (*isInitTensor)(const Concept *impl, ::mlir::Operation *, OpOperand *);
int64_t (*getRank)(const Concept *impl, ::mlir::Operation *, OpOperand*);
Block::BlockArgListType (*getRegionInputArgs)(const Concept *impl, ::mlir::Operation *);
Block::BlockArgListType (*getRegionOutputArgs)(const Concept *impl, ::mlir::Operation *);
BlockArgument (*getMatchingBlockArgument)(const Concept *impl, ::mlir::Operation *, OpOperand *);
OpOperand *(*getMatchingOpOperand)(const Concept *impl, ::mlir::Operation *, BlockArgument);
AffineMap (*getIndexingMapMatchingResult)(const Concept *impl, ::mlir::Operation *, OpResult);
OpOperand *(*getMatchingYieldValue)(const Concept *impl, ::mlir::Operation *, OpOperand*);
Block*(*getBlock)(const Concept *impl, ::mlir::Operation *);
SmallVector<utils::IteratorType> (*getIteratorTypesArray)(const Concept *impl, ::mlir::Operation *);
bool (*hasDynamicIndexingMaps)(const Concept *impl, ::mlir::Operation *);
LogicalResult (*verifyIndexingMapRequiredAttributes)(const Concept *impl, ::mlir::Operation *);
bool (*hasDynamicShape)(const Concept *impl, ::mlir::Operation *);
std::string (*getLibraryCallName)(const Concept *impl, ::mlir::Operation *);
bool (*hasIndexSemantics)(const Concept *impl, ::mlir::Operation *);
::llvm::SmallVector<OpOperand *> (*getOpOperandsMatchingBBargs)(const Concept *impl, ::mlir::Operation *);
LogicalResult (*mapIterationSpaceDimToOperandDim)(const Concept *impl, ::mlir::Operation *, unsigned, ::mlir::Value &, unsigned &);
void (*mapIterationSpaceDimToAllOperandDims)(const Concept *impl, ::mlir::Operation *, unsigned, mlir::SmallVectorImpl<std::pair<Value, unsigned>>&);
bool (*hasUserDefinedMaps)(const Concept *impl, ::mlir::Operation *);
bool (*canOpOperandsBeDropped)(const Concept *impl, ::mlir::Operation *, ArrayRef<OpOperand *>);
ArrayRef<int64_t> (*getShape)(const Concept *impl, ::mlir::Operation *, OpOperand*);
std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> (*getRegionBuilder)();
bool (*hasOnlyProjectedPermutations)(const Concept *impl, ::mlir::Operation *);
/// The base classes of this interface.
const ::mlir::DestinationStyleOpInterface::Concept *implDestinationStyleOpInterface = nullptr;
const ::mlir::IndexingMapOpInterface::Concept *implIndexingMapOpInterface = nullptr;
void initializeInterfaceConcept(::mlir::detail::InterfaceMap &interfaceMap) {
implDestinationStyleOpInterface = interfaceMap.lookup<::mlir::DestinationStyleOpInterface>();
assert(implDestinationStyleOpInterface && "`::mlir::linalg::LinalgOp` expected its base interface `::mlir::DestinationStyleOpInterface` to be registered");
implIndexingMapOpInterface = interfaceMap.lookup<::mlir::IndexingMapOpInterface>();
assert(implIndexingMapOpInterface && "`::mlir::linalg::LinalgOp` expected its base interface `::mlir::IndexingMapOpInterface` to be registered");
}
};
template<typename ConcreteOp>
class Model : public Concept {
public:
using Interface = ::mlir::linalg::LinalgOp;
Model() : Concept{getNumParallelLoops, isAllParallelLoops, getParallelDims, getNumReductionLoops, getReductionDims, getNumLoops, hasSingleReductionLoop, payloadUsesValueFromOperand, isSingleInputOutput, isInitTensor, getRank, getRegionInputArgs, getRegionOutputArgs, getMatchingBlockArgument, getMatchingOpOperand, getIndexingMapMatchingResult, getMatchingYieldValue, getBlock, getIteratorTypesArray, hasDynamicIndexingMaps, verifyIndexingMapRequiredAttributes, hasDynamicShape, getLibraryCallName, hasIndexSemantics, getOpOperandsMatchingBBargs, mapIterationSpaceDimToOperandDim, mapIterationSpaceDimToAllOperandDims, hasUserDefinedMaps, canOpOperandsBeDropped, getShape, getRegionBuilder, hasOnlyProjectedPermutations} {}
static inline unsigned getNumParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isAllParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline void getParallelDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res);
static inline unsigned getNumReductionLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline void getReductionDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res);
static inline unsigned getNumLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasSingleReductionLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool payloadUsesValueFromOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline bool isSingleInputOutput(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isInitTensor(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline int64_t getRank(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline Block::BlockArgListType getRegionInputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Block::BlockArgListType getRegionOutputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline BlockArgument getMatchingBlockArgument(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline OpOperand *getMatchingOpOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument);
static inline AffineMap getIndexingMapMatchingResult(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpResult result);
static inline OpOperand *getMatchingYieldValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline Block*getBlock(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline SmallVector<utils::IteratorType> getIteratorTypesArray(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasDynamicIndexingMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline LogicalResult verifyIndexingMapRequiredAttributes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasDynamicShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline std::string getLibraryCallName(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasIndexSemantics(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline ::llvm::SmallVector<OpOperand *> getOpOperandsMatchingBBargs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline LogicalResult mapIterationSpaceDimToOperandDim(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos);
static inline void mapIterationSpaceDimToAllOperandDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs);
static inline bool hasUserDefinedMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool canOpOperandsBeDropped(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands);
static inline ArrayRef<int64_t> getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> getRegionBuilder();
static inline bool hasOnlyProjectedPermutations(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteOp>
class FallbackModel : public Concept {
public:
using Interface = ::mlir::linalg::LinalgOp;
FallbackModel() : Concept{getNumParallelLoops, isAllParallelLoops, getParallelDims, getNumReductionLoops, getReductionDims, getNumLoops, hasSingleReductionLoop, payloadUsesValueFromOperand, isSingleInputOutput, isInitTensor, getRank, getRegionInputArgs, getRegionOutputArgs, getMatchingBlockArgument, getMatchingOpOperand, getIndexingMapMatchingResult, getMatchingYieldValue, getBlock, getIteratorTypesArray, hasDynamicIndexingMaps, verifyIndexingMapRequiredAttributes, hasDynamicShape, getLibraryCallName, hasIndexSemantics, getOpOperandsMatchingBBargs, mapIterationSpaceDimToOperandDim, mapIterationSpaceDimToAllOperandDims, hasUserDefinedMaps, canOpOperandsBeDropped, getShape, getRegionBuilder, hasOnlyProjectedPermutations} {}
static inline unsigned getNumParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isAllParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline void getParallelDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res);
static inline unsigned getNumReductionLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline void getReductionDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res);
static inline unsigned getNumLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasSingleReductionLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool payloadUsesValueFromOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline bool isSingleInputOutput(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool isInitTensor(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline int64_t getRank(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline Block::BlockArgListType getRegionInputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline Block::BlockArgListType getRegionOutputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline BlockArgument getMatchingBlockArgument(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand);
static inline OpOperand *getMatchingOpOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument);
static inline AffineMap getIndexingMapMatchingResult(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpResult result);
static inline OpOperand *getMatchingYieldValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline Block*getBlock(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline SmallVector<utils::IteratorType> getIteratorTypesArray(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasDynamicIndexingMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline LogicalResult verifyIndexingMapRequiredAttributes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasDynamicShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline std::string getLibraryCallName(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool hasIndexSemantics(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline ::llvm::SmallVector<OpOperand *> getOpOperandsMatchingBBargs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline LogicalResult mapIterationSpaceDimToOperandDim(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos);
static inline void mapIterationSpaceDimToAllOperandDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs);
static inline bool hasUserDefinedMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
static inline bool canOpOperandsBeDropped(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands);
static inline ArrayRef<int64_t> getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand);
static inline std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> getRegionBuilder();
static inline bool hasOnlyProjectedPermutations(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
};
template<typename ConcreteModel, typename ConcreteOp>
class ExternalModel : public FallbackModel<ConcreteModel> {
public:
using ConcreteEntity = ConcreteOp;
unsigned getNumParallelLoops(::mlir::Operation *tablegen_opaque_val) const;
bool isAllParallelLoops(::mlir::Operation *tablegen_opaque_val) const;
void getParallelDims(::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> &res) const;
unsigned getNumReductionLoops(::mlir::Operation *tablegen_opaque_val) const;
void getReductionDims(::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> &res) const;
unsigned getNumLoops(::mlir::Operation *tablegen_opaque_val) const;
bool hasSingleReductionLoop(::mlir::Operation *tablegen_opaque_val) const;
bool payloadUsesValueFromOperand(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const;
bool isSingleInputOutput(::mlir::Operation *tablegen_opaque_val) const;
bool isInitTensor(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const;
int64_t getRank(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const;
Block::BlockArgListType getRegionInputArgs(::mlir::Operation *tablegen_opaque_val) const;
Block::BlockArgListType getRegionOutputArgs(::mlir::Operation *tablegen_opaque_val) const;
BlockArgument getMatchingBlockArgument(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const;
OpOperand *getMatchingOpOperand(::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument) const;
AffineMap getIndexingMapMatchingResult(::mlir::Operation *tablegen_opaque_val, OpResult result) const;
OpOperand *getMatchingYieldValue(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const;
Block*getBlock(::mlir::Operation *tablegen_opaque_val) const;
SmallVector<utils::IteratorType> getIteratorTypesArray(::mlir::Operation *tablegen_opaque_val) const;
bool hasDynamicIndexingMaps(::mlir::Operation *tablegen_opaque_val) const;
LogicalResult verifyIndexingMapRequiredAttributes(::mlir::Operation *tablegen_opaque_val) const;
bool hasDynamicShape(::mlir::Operation *tablegen_opaque_val) const;
std::string getLibraryCallName(::mlir::Operation *tablegen_opaque_val) const;
::llvm::SmallVector<OpOperand *> getOpOperandsMatchingBBargs(::mlir::Operation *tablegen_opaque_val) const;
LogicalResult mapIterationSpaceDimToOperandDim(::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value &operand, unsigned &operandDimPos) const;
void mapIterationSpaceDimToAllOperandDims(::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>&operandDimPairs) const;
bool hasUserDefinedMaps(::mlir::Operation *tablegen_opaque_val) const;
bool canOpOperandsBeDropped(::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands) const;
ArrayRef<int64_t> getShape(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const;
};
};
template <typename ConcreteOp>
struct LinalgOpTrait;
} // namespace detail
class LinalgOp : public ::mlir::OpInterface<LinalgOp, detail::LinalgOpInterfaceTraits> {
public:
using ::mlir::OpInterface<LinalgOp, detail::LinalgOpInterfaceTraits>::OpInterface;
template <typename ConcreteOp>
struct Trait : public detail::LinalgOpTrait<ConcreteOp> {};
/// Return the number of parallel loops.
unsigned getNumParallelLoops();
/// Return true if all loops are parallel.
bool isAllParallelLoops();
/// Return the dims that are parallel loops.
void getParallelDims(SmallVectorImpl<unsigned> & res);
/// Return the number of reduction loops.
unsigned getNumReductionLoops();
/// Return the dims that are reduction loops.
void getReductionDims(SmallVectorImpl<unsigned> & res);
/// Return the total number of loops within the current operation.
unsigned getNumLoops();
/// Returns true if the current operation has only one loop and it's a
/// reduction loop.
bool hasSingleReductionLoop();
/// Return true if the payload uses the value loaded from `opOperand`. This
/// is useful to avoid loading from "write-only" memory that may be
/// uninitialized, as well as properly cloning "read-write" operands.
bool payloadUsesValueFromOperand(OpOperand * opOperand);
/// Returns true only if linalgOp takes one input and produces one result.
bool isSingleInputOutput();
/// Return true if `opOperand` is an init tensor. This is true when it is
/// an output tensor operand whose value is used in the payload region.
bool isInitTensor(OpOperand * opOperand);
/// Return the `opOperand` rank or zero for scalars or vectors not wrapped within a tensor or a memref.
int64_t getRank(OpOperand* opOperand);
/// Return the input block arguments of the region.
Block::BlockArgListType getRegionInputArgs();
/// Return the output block arguments of the region.
Block::BlockArgListType getRegionOutputArgs();
/// Return the block argument for an `opOperand`.
BlockArgument getMatchingBlockArgument(OpOperand * opOperand);
/// Return the operand for a `blockArgument`.
OpOperand *getMatchingOpOperand(BlockArgument blockArgument);
/// Return the indexing map for a `result`.
AffineMap getIndexingMapMatchingResult(OpResult result);
/// Return the value yielded by the region corresponding to an output
/// `opOperand`.
OpOperand *getMatchingYieldValue(OpOperand* opOperand);
/// Return the single block constituting the body of the operation by
/// calling the getBody method on the concrete operation.
Block*getBlock();
/// Return iterator types in the current operation.
///
/// Default implementation assumes that the operation has an attribute
/// `iterator_types`, but it's not always the case. Sometimes iterator types
/// can be infered from other parameters and in such cases default
/// getIteratorTypesArray should be overriden.
SmallVector<utils::IteratorType> getIteratorTypesArray();
/// Return true if the indexing map is depending on the current op instance.
/// This means that the indexing map is dynamically synthesized by using the
/// op instance's concrete attributes, instead of being static for all
/// instances of the same op kind.
bool hasDynamicIndexingMaps();
/// Verify all attributes used by indexing maps are valid.
LogicalResult verifyIndexingMapRequiredAttributes();
/// Return true if any of the operands has a dynamic shape.
bool hasDynamicShape();
/// Return the name registered for this op when lowering to an external
/// library call.
std::string getLibraryCallName();
/// Return whether the op accesses the iteration indices.
bool hasIndexSemantics();
/// Return op operands that have a corresponding argument in the basic block.
/// By default, the block should have an argument for each operand, but there
/// are expection. For example, in `map` output operand isn't used in
/// the block.
::llvm::SmallVector<OpOperand *> getOpOperandsMatchingBBargs();
/// Given a dimension of the iteration space of a Linalg operation, finds an
/// operand in the operation that is defined on such dimension. Returns
/// whether such operand was found or not. If found, also returns the
/// operand value and the dimension position within the operand.
LogicalResult mapIterationSpaceDimToOperandDim(unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos);
/// Given a dimension of the iteration space of a Linalg operation, finds
/// all the operands in the operation that are defined on such dimension.
/// Returns all the operand values found and their dimension positions in
/// `operandDimPairs`.
void mapIterationSpaceDimToAllOperandDims(unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs);
/// Returns true if the user has supplied explicit indexing maps that are
/// different from default indexing maps for this op. Returns `false` otherwise.
/// Note, if the user define maps that are identical to the default maps,
/// this method returns `false`.
bool hasUserDefinedMaps();
/// Checks if the given operands can be dropped, and the remaining
/// operands can still compute the bounds of the op.
bool canOpOperandsBeDropped(ArrayRef<OpOperand *> droppedOperands);
/// Return the `opOperand` shape or an empty vector for scalars or vectors
/// not wrapped within a tensor or a memref.
ArrayRef<int64_t> getShape(OpOperand* opOperand);
/// Returns the region builder for constructing the body for linalg.generic.
/// Returns a null function if this named op does not define a region
/// builder.
std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> getRegionBuilder();
/// Return true if all the indexing maps are projected permutations.
/// Otherwise return false.
bool hasOnlyProjectedPermutations();
/// Return the flat list of all operand dimension sizes in the order they
/// appear in the operands.
SmallVector<OpFoldResult> createFlatListOfOperandDims(OpBuilder &, Location);
/// Return the flat list of all operands' static dimension sizes in the
/// order they appear in the operands. All operand dimension sizes have to
/// be statically known.
SmallVector<int64_t, 4> createFlatListOfOperandStaticDims();
/// Create the loop ranges to materialize the computation over the current
/// operands. This is done by applying `getShapesToLoopsMap` to
/// `createFlatListOfOperandDims`.
SmallVector<Range, 4> createLoopRanges(OpBuilder &b, Location loc);
/// Returns the value that expresses the shape of the output in terms of
/// shape of the input operands where possible
LogicalResult reifyResultShapes(OpBuilder &b,
ReifiedRankedShapedTypeDims &reifiedReturnShapes);
/// Return the index in the indexingMaps vector that corresponds to this `opOperand`
int64_t getIndexingMapIndex(OpOperand *opOperand);
//===----------------------------------------------------------------===//
// Inherited from ::mlir::DestinationStyleOpInterface
//===----------------------------------------------------------------===//
operator ::mlir::DestinationStyleOpInterface () const {
if (!*this) return nullptr;
return ::mlir::DestinationStyleOpInterface(*this, getImpl()->implDestinationStyleOpInterface);
}
/// Return start and end indices of the init operands range.
::mlir::MutableOperandRange getDpsInitsMutable();
::mlir::OperandRange getDpsInits() {
return (*this).getDpsInitsMutable();
}
/// Return the number of DPS inits.
int64_t getNumDpsInits() { return (*this).getDpsInits().size(); }
/// Return the `i`-th DPS init.
::mlir::OpOperand *getDpsInitOperand(int64_t i) {
return &(*this).getDpsInitsMutable()[i];
}
/// Set the `i`-th DPS init.
void setDpsInitOperand(int64_t i, Value value) {
assert(i >= 0 && i < (*this).getNumDpsInits() && "invalid index");
(*this)->setOperand((*this).getDpsInits().getBeginOperandIndex() + i, value);
}
/// Return the number of DPS inputs.
int64_t getNumDpsInputs() {
return (*this)->getNumOperands() - (*this).getNumDpsInits();
}
/// Return the DPS input operands.
::llvm::SmallVector<::mlir::OpOperand *> getDpsInputOperands() {
::llvm::SmallVector<::mlir::OpOperand *> result;
int64_t numOperands = (*this)->getNumOperands();
::mlir::OperandRange range = (*this).getDpsInits();
if (range.empty()) {
result.reserve(numOperands);
for (int64_t i = 0; i < numOperands; ++i)
result.push_back(&(*this)->getOpOperand(i));
return result;
}
int64_t firstInitPos = range.getBeginOperandIndex();
int64_t numInits = range.size();
result.reserve(numOperands - numInits);
for (int64_t i = 0; i < firstInitPos; ++i)
result.push_back(&(*this)->getOpOperand(i));
for (int64_t i = firstInitPos + numInits; i < numOperands; ++i)
result.push_back(&(*this)->getOpOperand(i));
return result;
}
/// Return the DPS input operands.
::llvm::SmallVector<::mlir::Value> getDpsInputs() {
return ::llvm::to_vector(::llvm::map_range(
(*this).getDpsInputOperands(), [](OpOperand *o) { return o->get(); }));
}
/// Return the `i`-th DPS input operand.
::mlir::OpOperand *getDpsInputOperand(int64_t i) {
::mlir::OperandRange range = (*this).getDpsInits();
if (range.empty())
return &(*this)->getOpOperand(i);
int64_t firstInitPos = range.getBeginOperandIndex();
int64_t numInits = range.size();
assert(i >= 0 && i < (*this)->getNumOperands() - numInits
&& "invalid index");
return &(*this)->getOpOperand(
i < firstInitPos ? i : i + firstInitPos + numInits);
}
/// Return "true" if `opOperand` is an "input".
bool isDpsInput(::mlir::OpOperand *opOperand) {
assert(opOperand->getOwner() == (*this) && "invalid operand");
return !(*this).isDpsInit(opOperand);
}
/// Return "true" if `opOperand` is an "init".
bool isDpsInit(::mlir::OpOperand *opOperand) {
assert(opOperand->getOwner() == (*this) && "invalid operand");
::mlir::OperandRange range = (*this).getDpsInits();
if (range.empty())
return false;
auto operandNumber = opOperand->getOperandNumber();
return operandNumber >= range.getBeginOperandIndex()
&& operandNumber < range.getBeginOperandIndex() + range.size();
}
/// Return "true" if `opOperand` is a scalar value. A sclar is defined as
/// neither a MemRef nor a tensor value.
bool isScalar(::mlir::OpOperand *opOperand) {
assert(opOperand->getOwner() == (*this) && "invalid operand");
return !::llvm::isa<BaseMemRefType, TensorType>(
opOperand->get().getType());
}
/// Return the OpResult that is tied to the given OpOperand.
::mlir::OpResult getTiedOpResult(::mlir::OpOperand *opOperand) {
assert(opOperand->getOwner() == (*this) && "invalid operand");
::mlir::OperandRange range = (*this).getDpsInits();
assert(!range.empty() && "op has no inits");
int64_t resultIndex =
opOperand->getOperandNumber() - range.getBeginOperandIndex();
assert(resultIndex >= 0 &&
resultIndex < (*this)->getNumResults());
return (*this)->getResult(resultIndex);
}
/// Return the OpOperand that is tied to the given OpResult.
::mlir::OpOperand *getTiedOpOperand(::mlir::OpResult opResult) {
assert(opResult.getDefiningOp() == (*this) && "invalid opresult");
return (*this).getDpsInitOperand(opResult.getResultNumber());
}
/// Return whether the op has pure buffer semantics. That is the case if the
/// op has no tensor operands and at least one memref operand.
bool hasPureBufferSemantics() {
// No tensors.
auto isTensor = [](Value v){
return ::llvm::isa<::mlir::TensorType>(v.getType());
};
if (::llvm::any_of((*this)->getOperands(), isTensor))
return false;
// At least one memref.
auto isMemref = [](Value v){
return ::llvm::isa<::mlir::BaseMemRefType>(v.getType());
};
return llvm::any_of((*this)->getOperands(), isMemref);
}
/// Return whether the op has pure tensor semantics. That is the case if the
/// op has no memref operands and at least one tensor operand.
bool hasPureTensorSemantics() {
// No memrefs.
auto isMemref = [](Value v){
return ::llvm::isa<::mlir::BaseMemRefType>(v.getType());
};
if (::llvm::any_of((*this)->getOperands(), isMemref))
return false;
// At least one tensor.
auto isTensor = [](Value v){
return ::llvm::isa<::mlir::TensorType>(v.getType());
};
return llvm::any_of((*this)->getOperands(), isTensor); }
//===----------------------------------------------------------------===//
// Inherited from ::mlir::IndexingMapOpInterface
//===----------------------------------------------------------------===//
operator ::mlir::IndexingMapOpInterface () const {
if (!*this) return nullptr;
return ::mlir::IndexingMapOpInterface(*this, getImpl()->implIndexingMapOpInterface);
}
/// Return the indexing maps attribute within the current operation.
ArrayAttr getIndexingMaps();
/// Return the indexing maps within the current operation.
SmallVector<AffineMap> getIndexingMapsArray();
/// Return the input or output indexing map for `opOperand`.
AffineMap getMatchingIndexingMap(OpOperand* opOperand);
/// 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.
AffineMap getLoopsToShapesMap();
/// 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.
AffineMap getShapesToLoopsMap();
/// Returns the static shape of the underlying operand (note this is
/// op-specific behavior).
/// Returns ShapedType::kDynamic for non-statically-known loop ranges.
SmallVector<int64_t> getStaticOperandShape(OpOperand* opOperand);
/// Returns loop ranges by composing `getShapesToLoopsMap()` with the
/// flattened list of operand shapes.
/// Returns ShapedType::kDynamic for non-statically-known loop ranges.
SmallVector<int64_t> getStaticLoopRanges();
// 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();
};
} // namespace mlir::linalg
namespace mlir::linalg {
/// Interface for decomposing aggregated operations into a sequence of simpler
/// ops.
namespace detail {
struct AggregatedOpInterfaceInterfaceTraits {
struct Concept {
/// The methods defined by the interface.
FailureOr<SmallVector<Value>> (*decomposeOperation)(const Concept *impl, ::mlir::Operation *, OpBuilder &);
};
template<typename ConcreteOp>
class Model : public Concept {
public:
using Interface = ::mlir::linalg::AggregatedOpInterface;
Model() : Concept{decomposeOperation} {}
static inline FailureOr<SmallVector<Value>> decomposeOperation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpBuilder & b);
};
template<typename ConcreteOp>
class FallbackModel : public Concept {
public:
using Interface = ::mlir::linalg::AggregatedOpInterface;
FallbackModel() : Concept{decomposeOperation} {}
static inline FailureOr<SmallVector<Value>> decomposeOperation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpBuilder & b);
};
template<typename ConcreteModel, typename ConcreteOp>
class ExternalModel : public FallbackModel<ConcreteModel> {
public:
using ConcreteEntity = ConcreteOp;
FailureOr<SmallVector<Value>> decomposeOperation(::mlir::Operation *tablegen_opaque_val, OpBuilder &b) const;
};
};
template <typename ConcreteOp>
struct AggregatedOpInterfaceTrait;
} // namespace detail
class AggregatedOpInterface : public ::mlir::OpInterface<AggregatedOpInterface, detail::AggregatedOpInterfaceInterfaceTraits> {
public:
using ::mlir::OpInterface<AggregatedOpInterface, detail::AggregatedOpInterfaceInterfaceTraits>::OpInterface;
template <typename ConcreteOp>
struct Trait : public detail::AggregatedOpInterfaceTrait<ConcreteOp> {};
/// Method to decompose the operation into simpler operations.
///
/// On success, this method returns one `Value` per result in the
/// original operation.
/// The order of the returned values must match the order of the
/// original values.
/// In other words, the returned vector can be used directly with
/// `RewriterBase::replaceOp(this, returnedValues)`.
FailureOr<SmallVector<Value>> decomposeOperation(OpBuilder & b);
};
} // namespace mlir::linalg
namespace mlir::linalg::detail {
template <typename ConcreteOp>
struct ContractionOpInterfaceTrait : public ::mlir::OpInterface<ContractionOpInterface, detail::ContractionOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
static ::llvm::LogicalResult verifyRegionTrait(::mlir::Operation *op) {
return detail::verifyContractionInterface(op);
}
};
} // namespace mlir::linalg::detail
namespace mlir::linalg::detail {
template <typename ConcreteOp>
struct ConvolutionOpInterfaceTrait : public ::mlir::OpInterface<ConvolutionOpInterface, detail::ConvolutionOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
/// Return the image operand.
Value image() {
return (*static_cast<ConcreteOp *>(this)).getOperation()->getOperand(0);
}
/// Return the filter operand.
Value filter() {
return (*static_cast<ConcreteOp *>(this)).getOperation()->getOperand(1);
}
static ::llvm::LogicalResult verifyTrait(::mlir::Operation *op) {
return detail::verifyConvolutionInterface(op);
}
};
} // namespace mlir::linalg::detail
namespace mlir::linalg::detail {
template <typename ConcreteOp>
struct FillOpInterfaceTrait : public ::mlir::OpInterface<FillOpInterface, detail::FillOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
/// Return the fill value.
Value value() {
return (*static_cast<ConcreteOp *>(this)).getOperation()->getOperand(0);
}
/// Return the output operand.
Value output() {
return (*static_cast<ConcreteOp *>(this)).getOperation()->getOperand(1);
}
/// Return the result.
Value result() {
if ((*static_cast<ConcreteOp *>(this)).getOperation()->getResults().empty())
return nullptr;
return (*static_cast<ConcreteOp *>(this)).getOperation()->getResults().front();
}
static ::llvm::LogicalResult verifyTrait(::mlir::Operation *op) {
return detail::verifyFillInterface(op);
}
};
} // namespace mlir::linalg::detail
namespace mlir::linalg::detail {
template <typename ConcreteOp>
struct LinalgOpTrait : public ::mlir::OpInterface<LinalgOp, detail::LinalgOpInterfaceTraits>::Trait<ConcreteOp> {
/// Return the number of parallel loops.
unsigned getNumParallelLoops() {
return llvm::count((*static_cast<ConcreteOp *>(this)).getIteratorTypesArray(),
utils::IteratorType::parallel);
}
/// Return true if all loops are parallel.
bool isAllParallelLoops() {
return getNumParallelLoops() == getNumLoops();
}
/// Return the dims that are parallel loops.
void getParallelDims(SmallVectorImpl<unsigned> & res) {
return findPositionsOfType((*static_cast<ConcreteOp *>(this)).getIteratorTypesArray(),
utils::IteratorType::parallel, res);
}
/// Return the number of reduction loops.
unsigned getNumReductionLoops() {
return llvm::count((*static_cast<ConcreteOp *>(this)).getIteratorTypesArray(),
utils::IteratorType::reduction);
}
/// Return the dims that are reduction loops.
void getReductionDims(SmallVectorImpl<unsigned> & res) {
return findPositionsOfType((*static_cast<ConcreteOp *>(this)).getIteratorTypesArray(),
utils::IteratorType::reduction, res);
}
/// Return the total number of loops within the current operation.
unsigned getNumLoops() {
return (*static_cast<ConcreteOp *>(this)).getIteratorTypesArray().size();
}
/// Returns true if the current operation has only one loop and it's a
/// reduction loop.
bool hasSingleReductionLoop() {
auto iters = (*static_cast<ConcreteOp *>(this)).getIteratorTypesArray();
return iters.size() == 1 &&
llvm::count(iters, utils::IteratorType::reduction) == 1;
}
/// Return true if the payload uses the value loaded from `opOperand`. This
/// is useful to avoid loading from "write-only" memory that may be
/// uninitialized, as well as properly cloning "read-write" operands.
bool payloadUsesValueFromOperand(OpOperand * opOperand) {
unsigned bbArgNumber = opOperand->getOperandNumber();
// Init tensors have uses.
return !getBlock()->getArgument(bbArgNumber).use_empty();
}
/// Returns true only if linalgOp takes one input and produces one result.
bool isSingleInputOutput() {
return (*static_cast<ConcreteOp *>(this)).getNumDpsInputs() == 1 && (*static_cast<ConcreteOp *>(this)).getNumDpsInits() == 1;
}
/// Return true if `opOperand` is an init tensor. This is true when it is
/// an output tensor operand whose value is used in the payload region.
bool isInitTensor(OpOperand * opOperand) {
if (!(*static_cast<ConcreteOp *>(this)).isDpsInit(opOperand))
return false;
return payloadUsesValueFromOperand(opOperand);
}
/// Return the `opOperand` rank or zero for scalars or vectors not wrapped within a tensor or a memref.
int64_t getRank(OpOperand* opOperand) {
assert(opOperand->getOwner() == this->getOperation());
Type t = opOperand->get().getType();
// A VectorType is an elemental type, do not consider its rank for the operand.
if (isa<VectorType>(t))
return 0;
// Tensor and Memref container types have a rank.
if (auto shapedType = ::llvm::dyn_cast<ShapedType>(t)) {
// Failsafe.
assert((isa<MemRefType>(t) || isa<RankedTensorType>(t)) &&
"expected a ranked tensor or memref in LinalgInterface::getRank");
return shapedType.getRank();
}
return 0;
}
/// Return the input block arguments of the region.
Block::BlockArgListType getRegionInputArgs() {
return getBlock()->getArguments().take_front((*static_cast<ConcreteOp *>(this)).getNumDpsInputs());
}
/// Return the output block arguments of the region.
Block::BlockArgListType getRegionOutputArgs() {
return getBlock()->getArguments().take_back((*static_cast<ConcreteOp *>(this)).getNumDpsInits());
}
/// Return the block argument for an `opOperand`.
BlockArgument getMatchingBlockArgument(OpOperand * opOperand) {
assert(opOperand->getOwner() == this->getOperation());
return getBlock()->getArgument(opOperand->getOperandNumber());
}
/// Return the operand for a `blockArgument`.
OpOperand *getMatchingOpOperand(BlockArgument blockArgument) {
assert(blockArgument.getOwner() == getBlock());
return &this->getOperation()->getOpOperand(
blockArgument.getArgNumber());
}
/// Return the indexing map for a `result`.
AffineMap getIndexingMapMatchingResult(OpResult result) {
assert(result.getOwner() == this->getOperation());
auto indexingMaps =
(*static_cast<ConcreteOp *>(this)).getIndexingMaps().template getAsValueRange<AffineMapAttr>();
return *(indexingMaps.begin() + (*static_cast<ConcreteOp *>(this)).getNumDpsInputs() +
result.getResultNumber());
}
/// Return the value yielded by the region corresponding to an output
/// `opOperand`.
OpOperand *getMatchingYieldValue(OpOperand* opOperand) {
assert(opOperand->getOwner() == this->getOperation());
int64_t resultIndex =
opOperand->getOperandNumber() - (*static_cast<ConcreteOp *>(this)).getNumDpsInputs();
assert(resultIndex >= 0 &&
resultIndex < (*static_cast<ConcreteOp *>(this)).getNumDpsInits());
Operation *yieldOp = getBlock()->getTerminator();
return &yieldOp->getOpOperand(resultIndex);
}
/// Return the single block constituting the body of the operation by
/// calling the getBody method on the concrete operation.
Block*getBlock() {
// Assume the concrete operation implements the
// SingleBlockImplicitTerminator trait.
return (*static_cast<ConcreteOp *>(this)).getBody();
}
/// Return iterator types in the current operation.
///
/// Default implementation assumes that the operation has an attribute
/// `iterator_types`, but it's not always the case. Sometimes iterator types
/// can be infered from other parameters and in such cases default
/// getIteratorTypesArray should be overriden.
SmallVector<utils::IteratorType> getIteratorTypesArray() {
auto range = (*static_cast<ConcreteOp *>(this)).getIteratorTypes()
.template getAsValueRange<IteratorTypeAttr,
utils::IteratorType>();
return {range.begin(), range.end()};
}
/// Return true if the indexing map is depending on the current op instance.
/// This means that the indexing map is dynamically synthesized by using the
/// op instance's concrete attributes, instead of being static for all
/// instances of the same op kind.
bool hasDynamicIndexingMaps() {
return false;
}
/// Verify all attributes used by indexing maps are valid.
LogicalResult verifyIndexingMapRequiredAttributes() {
return success();
}
/// Return true if any of the operands has a dynamic shape.
bool hasDynamicShape() {
for (OpOperand &opOperand : this->getOperation()->getOpOperands()) {
if (auto shapedType = dyn_cast<ShapedType>(opOperand.get().getType())) {
if (ShapedType::isDynamicShape(shapedType.getShape())) return true;
}
}
return false;
}
/// Return the name registered for this op when lowering to an external
/// library call.
std::string getLibraryCallName() {
return (*static_cast<ConcreteOp *>(this)).getLibraryCallName();
}
/// Return op operands that have a corresponding argument in the basic block.
/// By default, the block should have an argument for each operand, but there
/// are expection. For example, in `map` output operand isn't used in
/// the block.
::llvm::SmallVector<OpOperand *> getOpOperandsMatchingBBargs() {
::llvm::SmallVector<OpOperand *> result;
result.reserve((*static_cast<ConcreteOp *>(this))->getNumOperands());
llvm::transform(
this->getOperation()->getOpOperands(),
std::back_inserter(result),
[](OpOperand &opOperand) { return &opOperand; });
return result;
}
/// Given a dimension of the iteration space of a Linalg operation, finds an
/// operand in the operation that is defined on such dimension. Returns
/// whether such operand was found or not. If found, also returns the
/// operand value and the dimension position within the operand.
LogicalResult mapIterationSpaceDimToOperandDim(unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos) {
// Retrieve the operand and its dimension position from the first
// operand with a permutation map that is defined on such dimension.
for (auto [i, idxMap] : llvm::enumerate((*static_cast<ConcreteOp *>(this)).getIndexingMapsArray())) {
if (idxMap.isProjectedPermutation()) {
if (auto mayOperandDim = idxMap.getResultPosition(
getAffineDimExpr(dimPos, idxMap.getContext()))) {
operand = (*static_cast<ConcreteOp *>(this))->getOperand(i);
operandDimPos = *mayOperandDim;
return success();
}
}
}
return failure();
}
/// Given a dimension of the iteration space of a Linalg operation, finds
/// all the operands in the operation that are defined on such dimension.
/// Returns all the operand values found and their dimension positions in
/// `operandDimPairs`.
void mapIterationSpaceDimToAllOperandDims(unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs) {
for (auto [i, idxMap] : llvm::enumerate((*static_cast<ConcreteOp *>(this)).getIndexingMapsArray())) {
if (idxMap.isProjectedPermutation()) {
if (auto mayOperandDim = idxMap.getResultPosition(
getAffineDimExpr(dimPos, idxMap.getContext()))) {
operandDimPairs.push_back({(*static_cast<ConcreteOp *>(this))->getOperand(i), *mayOperandDim});
}
}
}
return;
}
/// Returns true if the user has supplied explicit indexing maps that are
/// different from default indexing maps for this op. Returns `false` otherwise.
/// Note, if the user define maps that are identical to the default maps,
/// this method returns `false`.
bool hasUserDefinedMaps() {
return false;
}
/// Checks if the given operands can be dropped, and the remaining
/// operands can still compute the bounds of the op.
bool canOpOperandsBeDropped(ArrayRef<OpOperand *> droppedOperands) {
return detail::canOpOperandsBeDroppedImpl((*static_cast<ConcreteOp *>(this)), droppedOperands);
}
/// Return the `opOperand` shape or an empty vector for scalars or vectors
/// not wrapped within a tensor or a memref.
ArrayRef<int64_t> getShape(OpOperand* opOperand) {
Type t = opOperand->get().getType();
// A VectorType is an elemental type, do not consider its rank for the operand.
if (isa<VectorType>(t))
return {};
if (auto shapedType = ::llvm::dyn_cast<ShapedType>(t)) {
// Failsafe.
assert((isa<MemRefType>(t) || isa<RankedTensorType>(t)) &&
"expected a ranked tensor or memref in LinalgInterface::getRank");
return shapedType.getShape();
}
return {};
}
static ::llvm::LogicalResult verifyRegionTrait(::mlir::Operation *op) {
return detail::verifyStructuredOpInterface(op);
}
};
} // namespace mlir::linalg::detail
namespace mlir::linalg::detail {
template <typename ConcreteOp>
struct AggregatedOpInterfaceTrait : public ::mlir::OpInterface<AggregatedOpInterface, detail::AggregatedOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
/// Method to decompose the operation into simpler operations.
///
/// On success, this method returns one `Value` per result in the
/// original operation.
/// The order of the returned values must match the order of the
/// original values.
/// In other words, the returned vector can be used directly with
/// `RewriterBase::replaceOp(this, returnedValues)`.
FailureOr<SmallVector<Value>> decomposeOperation(OpBuilder & b) {
return {};
}
};
} // namespace mlir::linalg::detail
namespace mlir::linalg {
template<typename ConcreteOp>
Value detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::lhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(0);
}
template<typename ConcreteOp>
Value detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::rhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(1);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isRowMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isRowMajorMatmul((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isColumnMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isColumnMajorMatmul((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isRowMajorBatchMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isRowMajorBatchMatmul((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isVecmat((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isBatchVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isBatchVecmat((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isMatvec((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::Model<ConcreteOp>::isBatchMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return mlir::isBatchMatvec((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps());
}
template<typename ConcreteOp>
Value detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::lhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->lhs(tablegen_opaque_val);
}
template<typename ConcreteOp>
Value detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::rhs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->rhs(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isRowMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isRowMajorMatmul(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isColumnMajorMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isColumnMajorMatmul(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isRowMajorBatchMatmul(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isRowMajorBatchMatmul(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isVecmat(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isBatchVecmat(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isBatchVecmat(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isMatvec(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::ContractionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::isBatchMatvec(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isBatchMatvec(tablegen_opaque_val);
}
} // namespace mlir::linalg
namespace mlir::linalg {
template<typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::Model<ConcreteOp>::image(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).image();
}
template<typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::Model<ConcreteOp>::filter(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).filter();
}
template<typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::image(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->image(tablegen_opaque_val);
}
template<typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::filter(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->filter(tablegen_opaque_val);
}
template<typename ConcreteModel, typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::image(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(0);
}
template<typename ConcreteModel, typename ConcreteOp>
Value detail::ConvolutionOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::filter(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(1);
}
} // namespace mlir::linalg
namespace mlir::linalg {
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::Model<ConcreteOp>::value(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).value();
}
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::Model<ConcreteOp>::output(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).output();
}
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::Model<ConcreteOp>::result(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).result();
}
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::value(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->value(tablegen_opaque_val);
}
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::output(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->output(tablegen_opaque_val);
}
template<typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::result(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->result(tablegen_opaque_val);
}
template<typename ConcreteModel, typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::value(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(0);
}
template<typename ConcreteModel, typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::output(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getOperand(1);
}
template<typename ConcreteModel, typename ConcreteOp>
Value detail::FillOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::result(::mlir::Operation *tablegen_opaque_val) const {
if ((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getResults().empty())
return nullptr;
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOperation()->getResults().front();
}
} // namespace mlir::linalg
namespace mlir::linalg {
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getNumParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumParallelLoops();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::isAllParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).isAllParallelLoops();
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getParallelDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getParallelDims(res);
}
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getNumReductionLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumReductionLoops();
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getReductionDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getReductionDims(res);
}
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getNumLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumLoops();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasSingleReductionLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).hasSingleReductionLoop();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::payloadUsesValueFromOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).payloadUsesValueFromOperand(opOperand);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::isSingleInputOutput(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).isSingleInputOutput();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::isInitTensor(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).isInitTensor(opOperand);
}
template<typename ConcreteOp>
int64_t detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getRank(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getRank(opOperand);
}
template<typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getRegionInputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getRegionInputArgs();
}
template<typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getRegionOutputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getRegionOutputArgs();
}
template<typename ConcreteOp>
BlockArgument detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getMatchingBlockArgument(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getMatchingBlockArgument(opOperand);
}
template<typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getMatchingOpOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getMatchingOpOperand(blockArgument);
}
template<typename ConcreteOp>
AffineMap detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getIndexingMapMatchingResult(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpResult result) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMapMatchingResult(result);
}
template<typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getMatchingYieldValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getMatchingYieldValue(opOperand);
}
template<typename ConcreteOp>
Block*detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getBlock(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getBlock();
}
template<typename ConcreteOp>
SmallVector<utils::IteratorType> detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getIteratorTypesArray(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasDynamicIndexingMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).hasDynamicIndexingMaps();
}
template<typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::verifyIndexingMapRequiredAttributes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).verifyIndexingMapRequiredAttributes();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasDynamicShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).hasDynamicShape();
}
template<typename ConcreteOp>
std::string detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getLibraryCallName(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLibraryCallName();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasIndexSemantics(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).hasIndexSemantics();
}
template<typename ConcreteOp>
::llvm::SmallVector<OpOperand *> detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getOpOperandsMatchingBBargs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getOpOperandsMatchingBBargs();
}
template<typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::mapIterationSpaceDimToOperandDim(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).mapIterationSpaceDimToOperandDim(dimPos, operand, operandDimPos);
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::mapIterationSpaceDimToAllOperandDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).mapIterationSpaceDimToAllOperandDims(dimPos, operandDimPairs);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasUserDefinedMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).hasUserDefinedMaps();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::canOpOperandsBeDropped(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).canOpOperandsBeDropped(droppedOperands);
}
template<typename ConcreteOp>
ArrayRef<int64_t> detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getShape(opOperand);
}
template<typename ConcreteOp>
std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::getRegionBuilder() {
return ConcreteOp::getRegionBuilder();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::Model<ConcreteOp>::hasOnlyProjectedPermutations(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return llvm::all_of((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMapsArray(),
[](AffineMap map) { return map.isProjectedPermutation(); });
}
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getNumParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getNumParallelLoops(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::isAllParallelLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isAllParallelLoops(tablegen_opaque_val);
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getParallelDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res) {
return static_cast<const ConcreteOp *>(impl)->getParallelDims(tablegen_opaque_val, res);
}
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getNumReductionLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getNumReductionLoops(tablegen_opaque_val);
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getReductionDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> & res) {
return static_cast<const ConcreteOp *>(impl)->getReductionDims(tablegen_opaque_val, res);
}
template<typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getNumLoops(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getNumLoops(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasSingleReductionLoop(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasSingleReductionLoop(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::payloadUsesValueFromOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return static_cast<const ConcreteOp *>(impl)->payloadUsesValueFromOperand(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::isSingleInputOutput(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->isSingleInputOutput(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::isInitTensor(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return static_cast<const ConcreteOp *>(impl)->isInitTensor(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
int64_t detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getRank(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return static_cast<const ConcreteOp *>(impl)->getRank(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getRegionInputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getRegionInputArgs(tablegen_opaque_val);
}
template<typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getRegionOutputArgs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getRegionOutputArgs(tablegen_opaque_val);
}
template<typename ConcreteOp>
BlockArgument detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getMatchingBlockArgument(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand * opOperand) {
return static_cast<const ConcreteOp *>(impl)->getMatchingBlockArgument(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getMatchingOpOperand(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument) {
return static_cast<const ConcreteOp *>(impl)->getMatchingOpOperand(tablegen_opaque_val, blockArgument);
}
template<typename ConcreteOp>
AffineMap detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getIndexingMapMatchingResult(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpResult result) {
return static_cast<const ConcreteOp *>(impl)->getIndexingMapMatchingResult(tablegen_opaque_val, result);
}
template<typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getMatchingYieldValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return static_cast<const ConcreteOp *>(impl)->getMatchingYieldValue(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
Block*detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getBlock(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getBlock(tablegen_opaque_val);
}
template<typename ConcreteOp>
SmallVector<utils::IteratorType> detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getIteratorTypesArray(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getIteratorTypesArray(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasDynamicIndexingMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasDynamicIndexingMaps(tablegen_opaque_val);
}
template<typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::verifyIndexingMapRequiredAttributes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->verifyIndexingMapRequiredAttributes(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasDynamicShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasDynamicShape(tablegen_opaque_val);
}
template<typename ConcreteOp>
std::string detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getLibraryCallName(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getLibraryCallName(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasIndexSemantics(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasIndexSemantics(tablegen_opaque_val);
}
template<typename ConcreteOp>
::llvm::SmallVector<OpOperand *> detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getOpOperandsMatchingBBargs(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->getOpOperandsMatchingBBargs(tablegen_opaque_val);
}
template<typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::mapIterationSpaceDimToOperandDim(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value & operand, unsigned & operandDimPos) {
return static_cast<const ConcreteOp *>(impl)->mapIterationSpaceDimToOperandDim(tablegen_opaque_val, dimPos, operand, operandDimPos);
}
template<typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::mapIterationSpaceDimToAllOperandDims(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>& operandDimPairs) {
return static_cast<const ConcreteOp *>(impl)->mapIterationSpaceDimToAllOperandDims(tablegen_opaque_val, dimPos, operandDimPairs);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasUserDefinedMaps(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasUserDefinedMaps(tablegen_opaque_val);
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::canOpOperandsBeDropped(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands) {
return static_cast<const ConcreteOp *>(impl)->canOpOperandsBeDropped(tablegen_opaque_val, droppedOperands);
}
template<typename ConcreteOp>
ArrayRef<int64_t> detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getShape(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpOperand* opOperand) {
return static_cast<const ConcreteOp *>(impl)->getShape(tablegen_opaque_val, opOperand);
}
template<typename ConcreteOp>
std::function<void(ImplicitLocOpBuilder &, Block &, ArrayRef<NamedAttribute>, function_ref<InFlightDiagnostic()>)> detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::getRegionBuilder() {
return ConcreteOp::getRegionBuilder();
}
template<typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::FallbackModel<ConcreteOp>::hasOnlyProjectedPermutations(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
return static_cast<const ConcreteOp *>(impl)->hasOnlyProjectedPermutations(tablegen_opaque_val);
}
template<typename ConcreteModel, typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getNumParallelLoops(::mlir::Operation *tablegen_opaque_val) const {
return llvm::count((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray(),
utils::IteratorType::parallel);
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::isAllParallelLoops(::mlir::Operation *tablegen_opaque_val) const {
return getNumParallelLoops() == getNumLoops();
}
template<typename ConcreteModel, typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getParallelDims(::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> &res) const {
return findPositionsOfType((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray(),
utils::IteratorType::parallel, res);
}
template<typename ConcreteModel, typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getNumReductionLoops(::mlir::Operation *tablegen_opaque_val) const {
return llvm::count((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray(),
utils::IteratorType::reduction);
}
template<typename ConcreteModel, typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getReductionDims(::mlir::Operation *tablegen_opaque_val, SmallVectorImpl<unsigned> &res) const {
return findPositionsOfType((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray(),
utils::IteratorType::reduction, res);
}
template<typename ConcreteModel, typename ConcreteOp>
unsigned detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getNumLoops(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray().size();
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::hasSingleReductionLoop(::mlir::Operation *tablegen_opaque_val) const {
auto iters = (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypesArray();
return iters.size() == 1 &&
llvm::count(iters, utils::IteratorType::reduction) == 1;
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::payloadUsesValueFromOperand(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const {
unsigned bbArgNumber = opOperand->getOperandNumber();
// Init tensors have uses.
return !getBlock()->getArgument(bbArgNumber).use_empty();
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::isSingleInputOutput(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInputs() == 1 && (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInits() == 1;
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::isInitTensor(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const {
if (!(llvm::cast<ConcreteOp>(tablegen_opaque_val)).isDpsInit(opOperand))
return false;
return payloadUsesValueFromOperand(opOperand);
}
template<typename ConcreteModel, typename ConcreteOp>
int64_t detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getRank(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const {
assert(opOperand->getOwner() == this->getOperation());
Type t = opOperand->get().getType();
// A VectorType is an elemental type, do not consider its rank for the operand.
if (isa<VectorType>(t))
return 0;
// Tensor and Memref container types have a rank.
if (auto shapedType = ::llvm::dyn_cast<ShapedType>(t)) {
// Failsafe.
assert((isa<MemRefType>(t) || isa<RankedTensorType>(t)) &&
"expected a ranked tensor or memref in LinalgInterface::getRank");
return shapedType.getRank();
}
return 0;
}
template<typename ConcreteModel, typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getRegionInputArgs(::mlir::Operation *tablegen_opaque_val) const {
return getBlock()->getArguments().take_front((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInputs());
}
template<typename ConcreteModel, typename ConcreteOp>
Block::BlockArgListType detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getRegionOutputArgs(::mlir::Operation *tablegen_opaque_val) const {
return getBlock()->getArguments().take_back((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInits());
}
template<typename ConcreteModel, typename ConcreteOp>
BlockArgument detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getMatchingBlockArgument(::mlir::Operation *tablegen_opaque_val, OpOperand *opOperand) const {
assert(opOperand->getOwner() == this->getOperation());
return getBlock()->getArgument(opOperand->getOperandNumber());
}
template<typename ConcreteModel, typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getMatchingOpOperand(::mlir::Operation *tablegen_opaque_val, BlockArgument blockArgument) const {
assert(blockArgument.getOwner() == getBlock());
return &this->getOperation()->getOpOperand(
blockArgument.getArgNumber());
}
template<typename ConcreteModel, typename ConcreteOp>
AffineMap detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getIndexingMapMatchingResult(::mlir::Operation *tablegen_opaque_val, OpResult result) const {
assert(result.getOwner() == this->getOperation());
auto indexingMaps =
(llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMaps().template getAsValueRange<AffineMapAttr>();
return *(indexingMaps.begin() + (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInputs() +
result.getResultNumber());
}
template<typename ConcreteModel, typename ConcreteOp>
OpOperand *detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getMatchingYieldValue(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const {
assert(opOperand->getOwner() == this->getOperation());
int64_t resultIndex =
opOperand->getOperandNumber() - (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInputs();
assert(resultIndex >= 0 &&
resultIndex < (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getNumDpsInits());
Operation *yieldOp = getBlock()->getTerminator();
return &yieldOp->getOpOperand(resultIndex);
}
template<typename ConcreteModel, typename ConcreteOp>
Block*detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getBlock(::mlir::Operation *tablegen_opaque_val) const {
// Assume the concrete operation implements the
// SingleBlockImplicitTerminator trait.
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getBody();
}
template<typename ConcreteModel, typename ConcreteOp>
SmallVector<utils::IteratorType> detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getIteratorTypesArray(::mlir::Operation *tablegen_opaque_val) const {
auto range = (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIteratorTypes()
.template getAsValueRange<IteratorTypeAttr,
utils::IteratorType>();
return {range.begin(), range.end()};
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::hasDynamicIndexingMaps(::mlir::Operation *tablegen_opaque_val) const {
return false;
}
template<typename ConcreteModel, typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::verifyIndexingMapRequiredAttributes(::mlir::Operation *tablegen_opaque_val) const {
return success();
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::hasDynamicShape(::mlir::Operation *tablegen_opaque_val) const {
for (OpOperand &opOperand : this->getOperation()->getOpOperands()) {
if (auto shapedType = dyn_cast<ShapedType>(opOperand.get().getType())) {
if (ShapedType::isDynamicShape(shapedType.getShape())) return true;
}
}
return false;
}
template<typename ConcreteModel, typename ConcreteOp>
std::string detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getLibraryCallName(::mlir::Operation *tablegen_opaque_val) const {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getLibraryCallName();
}
template<typename ConcreteModel, typename ConcreteOp>
::llvm::SmallVector<OpOperand *> detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getOpOperandsMatchingBBargs(::mlir::Operation *tablegen_opaque_val) const {
::llvm::SmallVector<OpOperand *> result;
result.reserve((llvm::cast<ConcreteOp>(tablegen_opaque_val))->getNumOperands());
llvm::transform(
this->getOperation()->getOpOperands(),
std::back_inserter(result),
[](OpOperand &opOperand) { return &opOperand; });
return result;
}
template<typename ConcreteModel, typename ConcreteOp>
LogicalResult detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::mapIterationSpaceDimToOperandDim(::mlir::Operation *tablegen_opaque_val, unsigned dimPos, ::mlir::Value &operand, unsigned &operandDimPos) const {
// Retrieve the operand and its dimension position from the first
// operand with a permutation map that is defined on such dimension.
for (auto [i, idxMap] : llvm::enumerate((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMapsArray())) {
if (idxMap.isProjectedPermutation()) {
if (auto mayOperandDim = idxMap.getResultPosition(
getAffineDimExpr(dimPos, idxMap.getContext()))) {
operand = (llvm::cast<ConcreteOp>(tablegen_opaque_val))->getOperand(i);
operandDimPos = *mayOperandDim;
return success();
}
}
}
return failure();
}
template<typename ConcreteModel, typename ConcreteOp>
void detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::mapIterationSpaceDimToAllOperandDims(::mlir::Operation *tablegen_opaque_val, unsigned dimPos, mlir::SmallVectorImpl<std::pair<Value, unsigned>>&operandDimPairs) const {
for (auto [i, idxMap] : llvm::enumerate((llvm::cast<ConcreteOp>(tablegen_opaque_val)).getIndexingMapsArray())) {
if (idxMap.isProjectedPermutation()) {
if (auto mayOperandDim = idxMap.getResultPosition(
getAffineDimExpr(dimPos, idxMap.getContext()))) {
operandDimPairs.push_back({(llvm::cast<ConcreteOp>(tablegen_opaque_val))->getOperand(i), *mayOperandDim});
}
}
}
return;
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::hasUserDefinedMaps(::mlir::Operation *tablegen_opaque_val) const {
return false;
}
template<typename ConcreteModel, typename ConcreteOp>
bool detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::canOpOperandsBeDropped(::mlir::Operation *tablegen_opaque_val, ArrayRef<OpOperand *> droppedOperands) const {
return detail::canOpOperandsBeDroppedImpl((llvm::cast<ConcreteOp>(tablegen_opaque_val)), droppedOperands);
}
template<typename ConcreteModel, typename ConcreteOp>
ArrayRef<int64_t> detail::LinalgOpInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::getShape(::mlir::Operation *tablegen_opaque_val, OpOperand*opOperand) const {
Type t = opOperand->get().getType();
// A VectorType is an elemental type, do not consider its rank for the operand.
if (isa<VectorType>(t))
return {};
if (auto shapedType = ::llvm::dyn_cast<ShapedType>(t)) {
// Failsafe.
assert((isa<MemRefType>(t) || isa<RankedTensorType>(t)) &&
"expected a ranked tensor or memref in LinalgInterface::getRank");
return shapedType.getShape();
}
return {};
}
} // namespace mlir::linalg
namespace mlir::linalg {
template<typename ConcreteOp>
FailureOr<SmallVector<Value>> detail::AggregatedOpInterfaceInterfaceTraits::Model<ConcreteOp>::decomposeOperation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpBuilder & b) {
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).decomposeOperation(b);
}
template<typename ConcreteOp>
FailureOr<SmallVector<Value>> detail::AggregatedOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::decomposeOperation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, OpBuilder & b) {
return static_cast<const ConcreteOp *>(impl)->decomposeOperation(tablegen_opaque_val, b);
}
template<typename ConcreteModel, typename ConcreteOp>
FailureOr<SmallVector<Value>> detail::AggregatedOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::decomposeOperation(::mlir::Operation *tablegen_opaque_val, OpBuilder &b) const {
return {};
}
} // namespace mlir::linalg