1865 lines
102 KiB
C++
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
|