/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ |* *| |* Interface Declarations *| |* *| |* Automatically generated file, do not edit! *| |* *| \*===----------------------------------------------------------------------===*/ namespace mlir { /// This interface allows operations to expose information needed to tile them. /// /// The intent of this interface is to separate the generation of the loop /// structure (and constructs used for it) from the information needed from /// the operation to be able to tile them. As a result an implementation of /// the tiling algorithm (like `scf::tileUsingSCF`) can generate the inter-tile /// loop structure, and call into the methods of the interface to be able to /// tile any operation that implements the interface. /// /// This interface is also meant to help with "tile and fuse", i.e. the process /// of fusing a producer with a consumer by /// a) Tiling the consumer /// b) Based on the tile of the producer used by the tiled consumer, /// materialize the tiled implementation of a producer to generate that /// tile (and use it immediately in the consumer) /// You could also fuse a consumer with a producer by /// a) Tiling the producer /// b) Based on the tile produced, materialize the tiled implementation of /// a consumer that uses this tile. /// Note that the tile and fuse does not make any calculation on whether it /// is "profitable to do this", but simply provides a mechansim to implement /// the transformation when such a fusion is needed by the caller. /// /// For any operation to be tilable, an operation has to implement the /// following two methods (see description below) /// - `getLoopIteratorTypes` /// - `getIterationDomain` /// - `getTiledImplementation` /// - `getResultTilePosition` /// /// For an operation to be "tiled and fused" with its (already tiled) consumer, /// an operation has to implement the following additional method (see /// description below): /// - `generateResultTileValue` /// - `getIterationDomainTileFromResultTile` /// /// For an operation to be "tiled and fused" with its (already tiled) producer, /// an operation has to implement the following additional methods (see /// description below): /// - `getTiledImplementationFromOperandTiles` /// - `getIterationDomainTileFromOperandTiles`. class TilingInterface; } // namespace mlir namespace mlir { /// Interface for allowing operations to expose information needed to /// tile reductions using partial reduction followed by merge. This /// extends the `TilingInterface` to allow splitting a reduction /// dimension into a parallel dimension and reduction dimension. /// The materialized inter-tile loop could either be the reduction dimension /// (i.e. `ReductionTilingStrategy::PartialReductionOuterReduction`) or /// the parallel dimension (i.e /// `ReductionTilingStrategy::PartialReductionOuterReduction`). class PartialReductionOpInterface; } // namespace mlir namespace mlir { /// This interface allows operations to expose information needed to tile them. /// /// The intent of this interface is to separate the generation of the loop /// structure (and constructs used for it) from the information needed from /// the operation to be able to tile them. As a result an implementation of /// the tiling algorithm (like `scf::tileUsingSCF`) can generate the inter-tile /// loop structure, and call into the methods of the interface to be able to /// tile any operation that implements the interface. /// /// This interface is also meant to help with "tile and fuse", i.e. the process /// of fusing a producer with a consumer by /// a) Tiling the consumer /// b) Based on the tile of the producer used by the tiled consumer, /// materialize the tiled implementation of a producer to generate that /// tile (and use it immediately in the consumer) /// You could also fuse a consumer with a producer by /// a) Tiling the producer /// b) Based on the tile produced, materialize the tiled implementation of /// a consumer that uses this tile. /// Note that the tile and fuse does not make any calculation on whether it /// is "profitable to do this", but simply provides a mechansim to implement /// the transformation when such a fusion is needed by the caller. /// /// For any operation to be tilable, an operation has to implement the /// following two methods (see description below) /// - `getLoopIteratorTypes` /// - `getIterationDomain` /// - `getTiledImplementation` /// - `getResultTilePosition` /// /// For an operation to be "tiled and fused" with its (already tiled) consumer, /// an operation has to implement the following additional method (see /// description below): /// - `generateResultTileValue` /// - `getIterationDomainTileFromResultTile` /// /// For an operation to be "tiled and fused" with its (already tiled) producer, /// an operation has to implement the following additional methods (see /// description below): /// - `getTiledImplementationFromOperandTiles` /// - `getIterationDomainTileFromOperandTiles`. namespace detail { struct TilingInterfaceInterfaceTraits { struct Concept { /// The methods defined by the interface. ::mlir::SmallVector<::mlir::utils::IteratorType> (*getLoopIteratorTypes)(const Concept *impl, ::mlir::Operation *); ::mlir::SmallVector<::mlir::Range> (*getIterationDomain)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &); ::mlir::FailureOr<::mlir::TilingResult> (*getTiledImplementation)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::ArrayRef<::mlir::OpFoldResult> ); ::llvm::LogicalResult (*getResultTilePosition)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, unsigned, ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::SmallVector<::mlir::OpFoldResult> &, ::mlir::SmallVector<::mlir::OpFoldResult> &); ::mlir::FailureOr<::mlir::TilingResult> (*generateResultTileValue)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, unsigned, ::mlir::ArrayRef<::mlir::OpFoldResult>, ::mlir::ArrayRef<::mlir::OpFoldResult>); ::mlir::FailureOr<::mlir::TilingResult> (*getTiledImplementationFromOperandTiles)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, ::mlir::ArrayRef, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>>, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>>); ::llvm::LogicalResult (*getIterationDomainTileFromOperandTiles)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, ::mlir::ArrayRef, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> , ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> , ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &); ::llvm::LogicalResult (*getIterationDomainTileFromResultTile)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, unsigned, ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &); ::llvm::LogicalResult (*generateScalarImplementation)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, ::mlir::Location , ::mlir::ValueRange ); bool (*isOpFusableWithConsumerSlice)(const Concept *impl, ::mlir::Operation *, unsigned, ::mlir::ArrayRef<::mlir::OpFoldResult>, ::mlir::ArrayRef<::mlir::OpFoldResult>); bool (*isOpFusableWithProducerSlices)(const Concept *impl, ::mlir::Operation *, ::mlir::ArrayRef, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>>, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>>); }; template class Model : public Concept { public: using Interface = ::mlir::TilingInterface; Model() : Concept{getLoopIteratorTypes, getIterationDomain, getTiledImplementation, getResultTilePosition, generateResultTileValue, getTiledImplementationFromOperandTiles, getIterationDomainTileFromOperandTiles, getIterationDomainTileFromResultTile, generateScalarImplementation, isOpFusableWithConsumerSlice, isOpFusableWithProducerSlices} {} static inline ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val); static inline ::mlir::SmallVector<::mlir::Range> getIterationDomain(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b); static inline ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline ::llvm::LogicalResult getResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); static inline ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); static inline ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); static inline ::llvm::LogicalResult getIterationDomainTileFromResultTile(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); static inline ::llvm::LogicalResult generateScalarImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs); static inline bool isOpFusableWithConsumerSlice(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline bool isOpFusableWithProducerSlices(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::TilingInterface; FallbackModel() : Concept{getLoopIteratorTypes, getIterationDomain, getTiledImplementation, getResultTilePosition, generateResultTileValue, getTiledImplementationFromOperandTiles, getIterationDomainTileFromOperandTiles, getIterationDomainTileFromResultTile, generateScalarImplementation, isOpFusableWithConsumerSlice, isOpFusableWithProducerSlices} {} static inline ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val); static inline ::mlir::SmallVector<::mlir::Range> getIterationDomain(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b); static inline ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline ::llvm::LogicalResult getResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); static inline ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); static inline ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); static inline ::llvm::LogicalResult getIterationDomainTileFromResultTile(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); static inline ::llvm::LogicalResult generateScalarImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs); static inline bool isOpFusableWithConsumerSlice(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); static inline bool isOpFusableWithProducerSlices(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteOp; ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes(::mlir::Operation *tablegen_opaque_val) const; ::mlir::SmallVector<::mlir::Range> getIterationDomain(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b) const; ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const; ::llvm::LogicalResult getResultTilePosition(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> &resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> &resultSizes) const; ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const; ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) const; ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainSizes) const; ::llvm::LogicalResult getIterationDomainTileFromResultTile(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainSizes) const; ::llvm::LogicalResult generateScalarImplementation(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::Location loc, ::mlir::ValueRange ivs) const; bool isOpFusableWithConsumerSlice(::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const; bool isOpFusableWithProducerSlices(::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) const; }; }; template struct TilingInterfaceTrait; } // namespace detail class TilingInterface : public ::mlir::OpInterface { public: using ::mlir::OpInterface::OpInterface; template struct Trait : public detail::TilingInterfaceTrait {}; /// Returns a list of iterator types that describe the number of loops. ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes(); /// Returns a list of ranges that describe the loop bounds and /// step for the loops of the operation. ::mlir::SmallVector<::mlir::Range> getIterationDomain(::mlir::OpBuilder & b); /// Method to generate the tiled implementation of an operation. /// /// Given a tile of the iteration space (as returned by /// `getIterationDomain`), generate in-place the code that represents /// the computation corresponding to that tile of the iteration space. /// It is the responsibility of the implementation of this method in /// the operation to generate the slices of the operands needed for the /// tiled implementation. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// /// The returned `TilingResult` must return for each result of the /// untiled operation, a `Value` that is the result of the tiled /// operation. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Method to return the position of the result tile computed by the /// tiled operation. /// /// For operations that return a value (typically a value of type /// `RankedTensorType`), the generated tiled computation has to also /// recompute a replacement for the results of the original operation. /// The tiled implementation of the operation returns a tile of the /// result(s). This methods returns information about what part of the /// result tensor is computed by the tiled implementation. The manner in /// which these tiles get put together to get the final result is upto /// the surrounding loop construct. If an operation has no results, (for /// example an operation that operates only on memrefs), then this method /// need not be implemented by the operation. /// - `resultNumber` is the result number of the original operation /// being processed. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// - `resultOffsets` is the offsets of the tile of the result generated /// by the tiled implementation (returned by value). /// - `resultSizes` is the size of the tile of the result generated /// by the tiled implementation (returned by value). /// /// Note: It is undefined behaviour if there is overlap between the /// tiles of the result generated by the tiled implementation. ::llvm::LogicalResult getResultTilePosition(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); /// Method to generate the code that produces a tile of the result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Typically, for two operations with /// producer -> consumer relation ship, to compute a tile of the /// consumer a `slice` of the producer is needed. This method allows /// computing that slice of the producer in-place, thereby "fusing" /// the operations at tile-granularity. This method is different from /// `getTiledImplementation`, which produces a tiled implementation /// for a tile of the iteration space. This method produces a tiled /// implementation based on the tile of producer required. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// operation/result, this method should return failure. /// /// Note: This method only deals with the mechanism of implementing the /// fusion. In general the fusion might result in recomputation (based on /// the way the result is produced by the producer and the access pattern /// used in the consumer to access). This is upto the caller to handle /// appropriately. ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Method to generate the tiled implementation of an operation that uses /// the exact tiles of the given operands. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of the producer, this /// method generates the tile of the consumer that uses exactly these /// produced tiles. In some sense it is the "reverse" of /// `generateResultTileValue`. /// - `operandNumbers` is the list of operands whose tiles are "producers". /// - `allOffsets` is the offset of the slice of the producer used by the /// tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producer used by the /// consumer. /// If it is illegal to fuse with a producer along the given operand tiles for /// an operation, the implementation should return a failure. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); /// Method to return the tile of the iteration domain that uses a given /// tile of the operand. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of operands, /// returns the tile of the iteration space that uses these tiles. /// - `operandNumbers` is the list of operands whose tiles are "produced" /// by the producer(s). /// - `allOffsets` is the offset of the slice of the producers used by /// the tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producers used by the /// consumer. /// If it is illegal to fuse with the producer slices for an operation, /// or if this mapping cannot be computed, the implementation should /// return a failure. /// /// Note that unlike the "tile consumer and fuse producer" case, the /// "tile producer and fuse consumer" requires an additional method to get /// the iteration tile space that encompasses all uses of the given operand /// tile. The reason for this is, consider /// ```mlir /// %1 = scf.for... { /// %2 = /// %3 = tensor.insert_slice %2 into ... /// scf.yield %3 /// } /// %4 = )(... %1... ) /// ... (... %4 ...) /// ``` /// /// when fused this becomes /// ``` /// %1 = scf.for... { /// %2 = /// %3 = (... %2...) /// %4 = tensor.insert_slice %3 into ... /// scf.yield %4 /// } /// ... (... %1 ...) /// ``` /// /// i.e, when fusing the consumer, the replacement for the result of the /// consumer needs to be returned to replace the uses of the consumer. /// For the tile+fuse algorithm to do this it needs information about /// which tile of the iteration space encompasses all uses of the tile /// produced and use that to compute what are the results produced. Note /// that this iteration space might be the entire iteration space of the /// operation, or multiple operand tiles might map to intersecting /// iteration spaces. It is upto the caller to make sure that it is still /// fusable with producer in this scenario, or it must return a failure. /// /// Note that this method is only used as a way to implement the /// transformation. It does not provide guarantees on whether such a /// transformation is profitable. /// /// For most cases `getTiledImplementationFromOperandTiles` could be a /// implemented using `getIterationDomainTileFromOperandTiles` + /// `getTiledImplementation` methods. ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); /// Method to return the tile of the iteration domain based /// on the given tile of the certain result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Given a tile of an result, /// returns the tile of the iteration space that uses this tile. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// result, or if this mapping cannot be computed, the implementation /// should return a failure. /// /// For most cases `generateResultTileValue` could be a implemented using /// `getIterationDomainTileFromResultTile` + `getTiledImplementation` /// methods. ::llvm::LogicalResult getIterationDomainTileFromResultTile(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); /// Generates the scalar implementation of the operation. /// /// Given the list `ivs` that represent points in the iteration space /// (as specified by `getIterationDomain()`) returns the scalar operations /// that represent the computation at that point in the iteration space. /// This method is typically used as the "exit path", i.e. once all /// transformations are done, this method can be used to lower to scalar /// code that can then be lowered to LLVM or SPIR-V dialects. ::llvm::LogicalResult generateScalarImplementation(::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs); /// Indicates whether it is possible to fuse this operation with the given /// result slice. This method is not allowed to generate any IR. bool isOpFusableWithConsumerSlice(unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Indicates whether it is possible to fuse this operation with the given /// list of operand slices. This method is not allowed to generate any IR. bool isOpFusableWithProducerSlices(::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); }; } // namespace mlir namespace mlir { /// Interface for allowing operations to expose information needed to /// tile reductions using partial reduction followed by merge. This /// extends the `TilingInterface` to allow splitting a reduction /// dimension into a parallel dimension and reduction dimension. /// The materialized inter-tile loop could either be the reduction dimension /// (i.e. `ReductionTilingStrategy::PartialReductionOuterReduction`) or /// the parallel dimension (i.e /// `ReductionTilingStrategy::PartialReductionOuterReduction`). namespace detail { struct PartialReductionOpInterfaceInterfaceTraits { struct Concept { /// The methods defined by the interface. ::mlir::FailureOr> (*generateInitialTensorForPartialReduction)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, Location, ::mlir::ArrayRef<::mlir::OpFoldResult>, const ::mlir::SetVector &); ::mlir::FailureOr (*tileToPartialReduction)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, Location , ::mlir::ReductionTilingStrategy, ValueRange, ::mlir::ArrayRef<::mlir::OpFoldResult>, ::mlir::ArrayRef<::mlir::OpFoldResult>, const ::llvm::SetVector &, ::mlir::ArrayRef<::mlir::OpFoldResult>); ::mlir::FailureOr (*mergeReductions)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, Location , ValueRange, const ::mlir::SetVector &); ::llvm::LogicalResult (*getPartialResultTilePosition)(const Concept *impl, ::mlir::Operation *, ::mlir::OpBuilder &, unsigned, ReductionTilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> , ::mlir::ArrayRef<::mlir::OpFoldResult> , const ::mlir::SetVector &, ::mlir::ArrayRef<::mlir::OpFoldResult>, ::mlir::SmallVector<::mlir::OpFoldResult> &, ::mlir::SmallVector<::mlir::OpFoldResult> &); /// The base classes of this interface. const ::mlir::TilingInterface::Concept *implTilingInterface = nullptr; void initializeInterfaceConcept(::mlir::detail::InterfaceMap &interfaceMap) { implTilingInterface = interfaceMap.lookup<::mlir::TilingInterface>(); assert(implTilingInterface && "`::mlir::PartialReductionOpInterface` expected its base interface `::mlir::TilingInterface` to be registered"); } }; template class Model : public Concept { public: using Interface = ::mlir::PartialReductionOpInterface; Model() : Concept{generateInitialTensorForPartialReduction, tileToPartialReduction, mergeReductions, getPartialResultTilePosition} {} static inline ::mlir::FailureOr> generateInitialTensorForPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims); static inline ::mlir::FailureOr tileToPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs); static inline ::mlir::FailureOr mergeReductions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims); static inline ::llvm::LogicalResult getPartialResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::PartialReductionOpInterface; FallbackModel() : Concept{generateInitialTensorForPartialReduction, tileToPartialReduction, mergeReductions, getPartialResultTilePosition} {} static inline ::mlir::FailureOr> generateInitialTensorForPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims); static inline ::mlir::FailureOr tileToPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs); static inline ::mlir::FailureOr mergeReductions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims); static inline ::llvm::LogicalResult getPartialResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteOp; ::mlir::FailureOr> generateInitialTensorForPartialReduction(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector &reductionDims) const; ::mlir::FailureOr tileToPartialReduction(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector &reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs) const; ::mlir::FailureOr mergeReductions(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ValueRange partialReduce, const ::mlir::SetVector &reductionDims) const; ::llvm::LogicalResult getPartialResultTilePosition(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector &reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> &resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> &resultSizes) const; }; }; template struct PartialReductionOpInterfaceTrait; } // namespace detail class PartialReductionOpInterface : public ::mlir::OpInterface { public: using ::mlir::OpInterface::OpInterface; template struct Trait : public detail::PartialReductionOpInterfaceTrait {}; /// Method to generate a tensor initalized with the identity value of the /// reduction operator. The tensor shape is equal to operation result /// shape with new dimension for each non zero tile size. ::mlir::FailureOr> generateInitialTensorForPartialReduction(::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims); /// Method to generate a tiled version of the operation where the tiled /// reduction dimension are converted to parallel dimensions with a size /// less or equal to the tile size. This is meant to be used with /// `mergeReductions` method which will combine the partial reductions. /// The method receives the `offset` and `sizes` for all iteration space /// dimensions, as well as the iteration number of the tiled reduction /// dimensions (which is the induction variable of the inter-tile loop /// for the reduction dimension divided by the step of the loop) in /// `splitReductionIvs`. ::mlir::FailureOr tileToPartialReduction(::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs); /// Method to merge partial reductions for an operation that has been /// tiled along the reduction dimensions. This will only apply the /// reduction the operation. ::mlir::FailureOr mergeReductions(::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims); /// Method to return the position of the partial result tile computed by /// the tiled operation. This is same as /// TilingInterface:::getResultTilePosition, but determines the result /// tile position for partial reduction. /// The method receives the `offset` and `sizes` for all iteration space /// dimensions, as well as the iteration number of the tiled reduction /// dimensions (which is the induction variable of the inter-tile loop /// for the reduction dimension divided by the tile size specified) in /// `splitReductionIvs`. ::llvm::LogicalResult getPartialResultTilePosition(::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); //===----------------------------------------------------------------===// // Inherited from ::mlir::TilingInterface //===----------------------------------------------------------------===// operator ::mlir::TilingInterface () const { if (!*this) return nullptr; return ::mlir::TilingInterface(*this, getImpl()->implTilingInterface); } /// Returns a list of iterator types that describe the number of loops. ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes(); /// Returns a list of ranges that describe the loop bounds and /// step for the loops of the operation. ::mlir::SmallVector<::mlir::Range> getIterationDomain(::mlir::OpBuilder & b); /// Method to generate the tiled implementation of an operation. /// /// Given a tile of the iteration space (as returned by /// `getIterationDomain`), generate in-place the code that represents /// the computation corresponding to that tile of the iteration space. /// It is the responsibility of the implementation of this method in /// the operation to generate the slices of the operands needed for the /// tiled implementation. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// /// The returned `TilingResult` must return for each result of the /// untiled operation, a `Value` that is the result of the tiled /// operation. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Method to return the position of the result tile computed by the /// tiled operation. /// /// For operations that return a value (typically a value of type /// `RankedTensorType`), the generated tiled computation has to also /// recompute a replacement for the results of the original operation. /// The tiled implementation of the operation returns a tile of the /// result(s). This methods returns information about what part of the /// result tensor is computed by the tiled implementation. The manner in /// which these tiles get put together to get the final result is upto /// the surrounding loop construct. If an operation has no results, (for /// example an operation that operates only on memrefs), then this method /// need not be implemented by the operation. /// - `resultNumber` is the result number of the original operation /// being processed. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// - `resultOffsets` is the offsets of the tile of the result generated /// by the tiled implementation (returned by value). /// - `resultSizes` is the size of the tile of the result generated /// by the tiled implementation (returned by value). /// /// Note: It is undefined behaviour if there is overlap between the /// tiles of the result generated by the tiled implementation. ::llvm::LogicalResult getResultTilePosition(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes); /// Method to generate the code that produces a tile of the result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Typically, for two operations with /// producer -> consumer relation ship, to compute a tile of the /// consumer a `slice` of the producer is needed. This method allows /// computing that slice of the producer in-place, thereby "fusing" /// the operations at tile-granularity. This method is different from /// `getTiledImplementation`, which produces a tiled implementation /// for a tile of the iteration space. This method produces a tiled /// implementation based on the tile of producer required. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// operation/result, this method should return failure. /// /// Note: This method only deals with the mechanism of implementing the /// fusion. In general the fusion might result in recomputation (based on /// the way the result is produced by the producer and the access pattern /// used in the consumer to access). This is upto the caller to handle /// appropriately. ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Method to generate the tiled implementation of an operation that uses /// the exact tiles of the given operands. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of the producer, this /// method generates the tile of the consumer that uses exactly these /// produced tiles. In some sense it is the "reverse" of /// `generateResultTileValue`. /// - `operandNumbers` is the list of operands whose tiles are "producers". /// - `allOffsets` is the offset of the slice of the producer used by the /// tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producer used by the /// consumer. /// If it is illegal to fuse with a producer along the given operand tiles for /// an operation, the implementation should return a failure. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); /// Method to return the tile of the iteration domain that uses a given /// tile of the operand. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of operands, /// returns the tile of the iteration space that uses these tiles. /// - `operandNumbers` is the list of operands whose tiles are "produced" /// by the producer(s). /// - `allOffsets` is the offset of the slice of the producers used by /// the tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producers used by the /// consumer. /// If it is illegal to fuse with the producer slices for an operation, /// or if this mapping cannot be computed, the implementation should /// return a failure. /// /// Note that unlike the "tile consumer and fuse producer" case, the /// "tile producer and fuse consumer" requires an additional method to get /// the iteration tile space that encompasses all uses of the given operand /// tile. The reason for this is, consider /// ```mlir /// %1 = scf.for... { /// %2 = /// %3 = tensor.insert_slice %2 into ... /// scf.yield %3 /// } /// %4 = )(... %1... ) /// ... (... %4 ...) /// ``` /// /// when fused this becomes /// ``` /// %1 = scf.for... { /// %2 = /// %3 = (... %2...) /// %4 = tensor.insert_slice %3 into ... /// scf.yield %4 /// } /// ... (... %1 ...) /// ``` /// /// i.e, when fusing the consumer, the replacement for the result of the /// consumer needs to be returned to replace the uses of the consumer. /// For the tile+fuse algorithm to do this it needs information about /// which tile of the iteration space encompasses all uses of the tile /// produced and use that to compute what are the results produced. Note /// that this iteration space might be the entire iteration space of the /// operation, or multiple operand tiles might map to intersecting /// iteration spaces. It is upto the caller to make sure that it is still /// fusable with producer in this scenario, or it must return a failure. /// /// Note that this method is only used as a way to implement the /// transformation. It does not provide guarantees on whether such a /// transformation is profitable. /// /// For most cases `getTiledImplementationFromOperandTiles` could be a /// implemented using `getIterationDomainTileFromOperandTiles` + /// `getTiledImplementation` methods. ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); /// Method to return the tile of the iteration domain based /// on the given tile of the certain result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Given a tile of an result, /// returns the tile of the iteration space that uses this tile. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// result, or if this mapping cannot be computed, the implementation /// should return a failure. /// /// For most cases `generateResultTileValue` could be a implemented using /// `getIterationDomainTileFromResultTile` + `getTiledImplementation` /// methods. ::llvm::LogicalResult getIterationDomainTileFromResultTile(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes); /// Generates the scalar implementation of the operation. /// /// Given the list `ivs` that represent points in the iteration space /// (as specified by `getIterationDomain()`) returns the scalar operations /// that represent the computation at that point in the iteration space. /// This method is typically used as the "exit path", i.e. once all /// transformations are done, this method can be used to lower to scalar /// code that can then be lowered to LLVM or SPIR-V dialects. ::llvm::LogicalResult generateScalarImplementation(::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs); /// Indicates whether it is possible to fuse this operation with the given /// result slice. This method is not allowed to generate any IR. bool isOpFusableWithConsumerSlice(unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes); /// Indicates whether it is possible to fuse this operation with the given /// list of operand slices. This method is not allowed to generate any IR. bool isOpFusableWithProducerSlices(::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes); }; } // namespace mlir namespace mlir::detail { template struct TilingInterfaceTrait : public ::mlir::OpInterface::Trait { /// Returns a list of iterator types that describe the number of loops. ::mlir::SmallVector<::mlir::utils::IteratorType> getLoopIteratorTypes() { return {}; } /// Returns a list of ranges that describe the loop bounds and /// step for the loops of the operation. ::mlir::SmallVector<::mlir::Range> getIterationDomain(::mlir::OpBuilder & b) { return {}; } /// Method to generate the tiled implementation of an operation. /// /// Given a tile of the iteration space (as returned by /// `getIterationDomain`), generate in-place the code that represents /// the computation corresponding to that tile of the iteration space. /// It is the responsibility of the implementation of this method in /// the operation to generate the slices of the operands needed for the /// tiled implementation. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// /// The returned `TilingResult` must return for each result of the /// untiled operation, a `Value` that is the result of the tiled /// operation. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementation(::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return {}; } /// Method to return the position of the result tile computed by the /// tiled operation. /// /// For operations that return a value (typically a value of type /// `RankedTensorType`), the generated tiled computation has to also /// recompute a replacement for the results of the original operation. /// The tiled implementation of the operation returns a tile of the /// result(s). This methods returns information about what part of the /// result tensor is computed by the tiled implementation. The manner in /// which these tiles get put together to get the final result is upto /// the surrounding loop construct. If an operation has no results, (for /// example an operation that operates only on memrefs), then this method /// need not be implemented by the operation. /// - `resultNumber` is the result number of the original operation /// being processed. /// - `offsets` provides the offset of the tile in the coordinate system /// of the original iteration space, i.e., if an iteration space /// dimension had non-zero offset, it will be included in the offset /// provided here (as opposed to zero-based offset "relative" to the /// iteration space). /// - `sizes` provides the size of the tile. /// - `resultOffsets` is the offsets of the tile of the result generated /// by the tiled implementation (returned by value). /// - `resultSizes` is the size of the tile of the result generated /// by the tiled implementation (returned by value). /// /// Note: It is undefined behaviour if there is overlap between the /// tiles of the result generated by the tiled implementation. ::llvm::LogicalResult getResultTilePosition(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return failure(); } /// Method to generate the code that produces a tile of the result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Typically, for two operations with /// producer -> consumer relation ship, to compute a tile of the /// consumer a `slice` of the producer is needed. This method allows /// computing that slice of the producer in-place, thereby "fusing" /// the operations at tile-granularity. This method is different from /// `getTiledImplementation`, which produces a tiled implementation /// for a tile of the iteration space. This method produces a tiled /// implementation based on the tile of producer required. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// operation/result, this method should return failure. /// /// Note: This method only deals with the mechanism of implementing the /// fusion. In general the fusion might result in recomputation (based on /// the way the result is produced by the producer and the access pattern /// used in the consumer to access). This is upto the caller to handle /// appropriately. ::mlir::FailureOr<::mlir::TilingResult> generateResultTileValue(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return failure(); } /// Method to generate the tiled implementation of an operation that uses /// the exact tiles of the given operands. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of the producer, this /// method generates the tile of the consumer that uses exactly these /// produced tiles. In some sense it is the "reverse" of /// `generateResultTileValue`. /// - `operandNumbers` is the list of operands whose tiles are "producers". /// - `allOffsets` is the offset of the slice of the producer used by the /// tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producer used by the /// consumer. /// If it is illegal to fuse with a producer along the given operand tiles for /// an operation, the implementation should return a failure. ::mlir::FailureOr<::mlir::TilingResult> getTiledImplementationFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return failure(); } /// Method to return the tile of the iteration domain that uses a given /// tile of the operand. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) producer. Given tiles of operands, /// returns the tile of the iteration space that uses these tiles. /// - `operandNumbers` is the list of operands whose tiles are "produced" /// by the producer(s). /// - `allOffsets` is the offset of the slice of the producers used by /// the tiled implementation of the consumer. /// - `allSizes` is the size of the slice of the producers used by the /// consumer. /// If it is illegal to fuse with the producer slices for an operation, /// or if this mapping cannot be computed, the implementation should /// return a failure. /// /// Note that unlike the "tile consumer and fuse producer" case, the /// "tile producer and fuse consumer" requires an additional method to get /// the iteration tile space that encompasses all uses of the given operand /// tile. The reason for this is, consider /// ```mlir /// %1 = scf.for... { /// %2 = /// %3 = tensor.insert_slice %2 into ... /// scf.yield %3 /// } /// %4 = )(... %1... ) /// ... (... %4 ...) /// ``` /// /// when fused this becomes /// ``` /// %1 = scf.for... { /// %2 = /// %3 = (... %2...) /// %4 = tensor.insert_slice %3 into ... /// scf.yield %4 /// } /// ... (... %1 ...) /// ``` /// /// i.e, when fusing the consumer, the replacement for the result of the /// consumer needs to be returned to replace the uses of the consumer. /// For the tile+fuse algorithm to do this it needs information about /// which tile of the iteration space encompasses all uses of the tile /// produced and use that to compute what are the results produced. Note /// that this iteration space might be the entire iteration space of the /// operation, or multiple operand tiles might map to intersecting /// iteration spaces. It is upto the caller to make sure that it is still /// fusable with producer in this scenario, or it must return a failure. /// /// Note that this method is only used as a way to implement the /// transformation. It does not provide guarantees on whether such a /// transformation is profitable. /// /// For most cases `getTiledImplementationFromOperandTiles` could be a /// implemented using `getIterationDomainTileFromOperandTiles` + /// `getTiledImplementation` methods. ::llvm::LogicalResult getIterationDomainTileFromOperandTiles(::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return failure(); } /// Method to return the tile of the iteration domain based /// on the given tile of the certain result. /// /// This method is required to allow operations to be "tiled and fused" /// with an (already tiled) consumer. Given a tile of an result, /// returns the tile of the iteration space that uses this tile. /// - `resultNumber` is the result of the producer used by the consumer. /// - `offsets` is the offset of the slice of the producer result used by /// the tiled implementation of the consumer. /// - `sizes` is the size of the slice of the producer result used by the /// consumer. /// If fusion of the producer with the consumer is not legal for the /// result, or if this mapping cannot be computed, the implementation /// should return a failure. /// /// For most cases `generateResultTileValue` could be a implemented using /// `getIterationDomainTileFromResultTile` + `getTiledImplementation` /// methods. ::llvm::LogicalResult getIterationDomainTileFromResultTile(::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return failure(); } /// Generates the scalar implementation of the operation. /// /// Given the list `ivs` that represent points in the iteration space /// (as specified by `getIterationDomain()`) returns the scalar operations /// that represent the computation at that point in the iteration space. /// This method is typically used as the "exit path", i.e. once all /// transformations are done, this method can be used to lower to scalar /// code that can then be lowered to LLVM or SPIR-V dialects. ::llvm::LogicalResult generateScalarImplementation(::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs) { return failure(); } /// Indicates whether it is possible to fuse this operation with the given /// result slice. This method is not allowed to generate any IR. bool isOpFusableWithConsumerSlice(unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return false; } /// Indicates whether it is possible to fuse this operation with the given /// list of operand slices. This method is not allowed to generate any IR. bool isOpFusableWithProducerSlices(::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return false; } }; } // namespace mlir::detail namespace mlir::detail { template struct PartialReductionOpInterfaceTrait : public ::mlir::OpInterface::Trait { /// Method to generate a tensor initalized with the identity value of the /// reduction operator. The tensor shape is equal to operation result /// shape with new dimension for each non zero tile size. ::mlir::FailureOr> generateInitialTensorForPartialReduction(::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims) { return failure(); } /// Method to generate a tiled version of the operation where the tiled /// reduction dimension are converted to parallel dimensions with a size /// less or equal to the tile size. This is meant to be used with /// `mergeReductions` method which will combine the partial reductions. /// The method receives the `offset` and `sizes` for all iteration space /// dimensions, as well as the iteration number of the tiled reduction /// dimensions (which is the induction variable of the inter-tile loop /// for the reduction dimension divided by the step of the loop) in /// `splitReductionIvs`. ::mlir::FailureOr tileToPartialReduction(::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs) { return failure(); } /// Method to merge partial reductions for an operation that has been /// tiled along the reduction dimensions. This will only apply the /// reduction the operation. ::mlir::FailureOr mergeReductions(::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims) { return failure(); } /// Method to return the position of the partial result tile computed by /// the tiled operation. This is same as /// TilingInterface:::getResultTilePosition, but determines the result /// tile position for partial reduction. /// The method receives the `offset` and `sizes` for all iteration space /// dimensions, as well as the iteration number of the tiled reduction /// dimensions (which is the induction variable of the inter-tile loop /// for the reduction dimension divided by the tile size specified) in /// `splitReductionIvs`. ::llvm::LogicalResult getPartialResultTilePosition(::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return failure(); } }; } // namespace mlir::detail namespace mlir { template ::mlir::SmallVector<::mlir::utils::IteratorType> detail::TilingInterfaceInterfaceTraits::Model::getLoopIteratorTypes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) { return (llvm::cast(tablegen_opaque_val)).getLoopIteratorTypes(); } template ::mlir::SmallVector<::mlir::Range> detail::TilingInterfaceInterfaceTraits::Model::getIterationDomain(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b) { return (llvm::cast(tablegen_opaque_val)).getIterationDomain(b); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::Model::getTiledImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return (llvm::cast(tablegen_opaque_val)).getTiledImplementation(b, offsets, sizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::Model::getResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return (llvm::cast(tablegen_opaque_val)).getResultTilePosition(b, resultNumber, offsets, sizes, resultOffsets, resultSizes); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::Model::generateResultTileValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return (llvm::cast(tablegen_opaque_val)).generateResultTileValue(b, resultNumber, offsets, sizes); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::Model::getTiledImplementationFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return (llvm::cast(tablegen_opaque_val)).getTiledImplementationFromOperandTiles(b, operandNumbers, allOffsets, allSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::Model::getIterationDomainTileFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return (llvm::cast(tablegen_opaque_val)).getIterationDomainTileFromOperandTiles(b, operandNumbers, allOffsets, allSizes, iterDomainOffsets, iterDomainSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::Model::getIterationDomainTileFromResultTile(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return (llvm::cast(tablegen_opaque_val)).getIterationDomainTileFromResultTile(b, resultNumber, offsets, sizes, iterDomainOffsets, iterDomainSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::Model::generateScalarImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs) { return (llvm::cast(tablegen_opaque_val)).generateScalarImplementation(b, loc, ivs); } template bool detail::TilingInterfaceInterfaceTraits::Model::isOpFusableWithConsumerSlice(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return (llvm::cast(tablegen_opaque_val)).isOpFusableWithConsumerSlice(resultNumber, offsets, sizes); } template bool detail::TilingInterfaceInterfaceTraits::Model::isOpFusableWithProducerSlices(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return (llvm::cast(tablegen_opaque_val)).isOpFusableWithProducerSlices(operandNumbers, allOffsets, allSizes); } template ::mlir::SmallVector<::mlir::utils::IteratorType> detail::TilingInterfaceInterfaceTraits::FallbackModel::getLoopIteratorTypes(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) { return static_cast(impl)->getLoopIteratorTypes(tablegen_opaque_val); } template ::mlir::SmallVector<::mlir::Range> detail::TilingInterfaceInterfaceTraits::FallbackModel::getIterationDomain(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b) { return static_cast(impl)->getIterationDomain(tablegen_opaque_val, b); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::FallbackModel::getTiledImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return static_cast(impl)->getTiledImplementation(tablegen_opaque_val, b, offsets, sizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::FallbackModel::getResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return static_cast(impl)->getResultTilePosition(tablegen_opaque_val, b, resultNumber, offsets, sizes, resultOffsets, resultSizes); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::FallbackModel::generateResultTileValue(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return static_cast(impl)->generateResultTileValue(tablegen_opaque_val, b, resultNumber, offsets, sizes); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::FallbackModel::getTiledImplementationFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return static_cast(impl)->getTiledImplementationFromOperandTiles(tablegen_opaque_val, b, operandNumbers, allOffsets, allSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::FallbackModel::getIterationDomainTileFromOperandTiles(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return static_cast(impl)->getIterationDomainTileFromOperandTiles(tablegen_opaque_val, b, operandNumbers, allOffsets, allSizes, iterDomainOffsets, iterDomainSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::FallbackModel::getIterationDomainTileFromResultTile(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> & iterDomainSizes) { return static_cast(impl)->getIterationDomainTileFromResultTile(tablegen_opaque_val, b, resultNumber, offsets, sizes, iterDomainOffsets, iterDomainSizes); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::FallbackModel::generateScalarImplementation(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, ::mlir::Location loc, ::mlir::ValueRange ivs) { return static_cast(impl)->generateScalarImplementation(tablegen_opaque_val, b, loc, ivs); } template bool detail::TilingInterfaceInterfaceTraits::FallbackModel::isOpFusableWithConsumerSlice(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) { return static_cast(impl)->isOpFusableWithConsumerSlice(tablegen_opaque_val, resultNumber, offsets, sizes); } template bool detail::TilingInterfaceInterfaceTraits::FallbackModel::isOpFusableWithProducerSlices(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) { return static_cast(impl)->isOpFusableWithProducerSlices(tablegen_opaque_val, operandNumbers, allOffsets, allSizes); } template ::mlir::SmallVector<::mlir::utils::IteratorType> detail::TilingInterfaceInterfaceTraits::ExternalModel::getLoopIteratorTypes(::mlir::Operation *tablegen_opaque_val) const { return {}; } template ::mlir::SmallVector<::mlir::Range> detail::TilingInterfaceInterfaceTraits::ExternalModel::getIterationDomain(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b) const { return {}; } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::ExternalModel::getTiledImplementation(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const { return {}; } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::ExternalModel::getResultTilePosition(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVector<::mlir::OpFoldResult> &resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> &resultSizes) const { return failure(); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::ExternalModel::generateResultTileValue(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const { return failure(); } template ::mlir::FailureOr<::mlir::TilingResult> detail::TilingInterfaceInterfaceTraits::ExternalModel::getTiledImplementationFromOperandTiles(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) const { return failure(); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::ExternalModel::getIterationDomainTileFromOperandTiles(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainSizes) const { return failure(); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::ExternalModel::getIterationDomainTileFromResultTile(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainOffsets, ::mlir::SmallVectorImpl<::mlir::OpFoldResult> &iterDomainSizes) const { return failure(); } template ::llvm::LogicalResult detail::TilingInterfaceInterfaceTraits::ExternalModel::generateScalarImplementation(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, ::mlir::Location loc, ::mlir::ValueRange ivs) const { return failure(); } template bool detail::TilingInterfaceInterfaceTraits::ExternalModel::isOpFusableWithConsumerSlice(::mlir::Operation *tablegen_opaque_val, unsigned resultNumber, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes) const { return false; } template bool detail::TilingInterfaceInterfaceTraits::ExternalModel::isOpFusableWithProducerSlices(::mlir::Operation *tablegen_opaque_val, ::mlir::ArrayRef operandNumbers, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allOffsets, ::mlir::ArrayRef<::mlir::SmallVector<::mlir::OpFoldResult>> allSizes) const { return false; } } // namespace mlir namespace mlir { template ::mlir::FailureOr> detail::PartialReductionOpInterfaceInterfaceTraits::Model::generateInitialTensorForPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims) { return (llvm::cast(tablegen_opaque_val)).generateInitialTensorForPartialReduction(b, loc, tileSizes, reductionDims); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::Model::tileToPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs) { return (llvm::cast(tablegen_opaque_val)).tileToPartialReduction(b, loc, tilingStrategy, init, offsets, sizes, reductionDims, splitReductionIvs); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::Model::mergeReductions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims) { return (llvm::cast(tablegen_opaque_val)).mergeReductions(b, loc, partialReduce, reductionDims); } template ::llvm::LogicalResult detail::PartialReductionOpInterfaceInterfaceTraits::Model::getPartialResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return (llvm::cast(tablegen_opaque_val)).getPartialResultTilePosition(b, resultNumber, tilingStrategy, offsets, sizes, reductionDims, splitReductionIvs, resultOffsets, resultSizes); } template ::mlir::FailureOr> detail::PartialReductionOpInterfaceInterfaceTraits::FallbackModel::generateInitialTensorForPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector & reductionDims) { return static_cast(impl)->generateInitialTensorForPartialReduction(tablegen_opaque_val, b, loc, tileSizes, reductionDims); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::FallbackModel::tileToPartialReduction(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs) { return static_cast(impl)->tileToPartialReduction(tablegen_opaque_val, b, loc, tilingStrategy, init, offsets, sizes, reductionDims, splitReductionIvs); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::FallbackModel::mergeReductions(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, Location loc, ValueRange partialReduce, const ::mlir::SetVector & reductionDims) { return static_cast(impl)->mergeReductions(tablegen_opaque_val, b, loc, partialReduce, reductionDims); } template ::llvm::LogicalResult detail::PartialReductionOpInterfaceInterfaceTraits::FallbackModel::getPartialResultTilePosition(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder & b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector & reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> & resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> & resultSizes) { return static_cast(impl)->getPartialResultTilePosition(tablegen_opaque_val, b, resultNumber, tilingStrategy, offsets, sizes, reductionDims, splitReductionIvs, resultOffsets, resultSizes); } template ::mlir::FailureOr> detail::PartialReductionOpInterfaceInterfaceTraits::ExternalModel::generateInitialTensorForPartialReduction(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ::mlir::ArrayRef<::mlir::OpFoldResult> tileSizes, const ::mlir::SetVector &reductionDims) const { return failure(); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::ExternalModel::tileToPartialReduction(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ::mlir::ReductionTilingStrategy tilingStrategy, ValueRange init, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::llvm::SetVector &reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs) const { return failure(); } template ::mlir::FailureOr detail::PartialReductionOpInterfaceInterfaceTraits::ExternalModel::mergeReductions(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, Location loc, ValueRange partialReduce, const ::mlir::SetVector &reductionDims) const { return failure(); } template ::llvm::LogicalResult detail::PartialReductionOpInterfaceInterfaceTraits::ExternalModel::getPartialResultTilePosition(::mlir::Operation *tablegen_opaque_val, ::mlir::OpBuilder &b, unsigned resultNumber, ReductionTilingStrategy tilingStrategy, ::mlir::ArrayRef<::mlir::OpFoldResult> offsets, ::mlir::ArrayRef<::mlir::OpFoldResult> sizes, const ::mlir::SetVector &reductionDims, ::mlir::ArrayRef<::mlir::OpFoldResult> splitReductionIvs, ::mlir::SmallVector<::mlir::OpFoldResult> &resultOffsets, ::mlir::SmallVector<::mlir::OpFoldResult> &resultSizes) const { return failure(); } } // namespace mlir