MLIR 23.0.0git
TileUsingInterface.h
Go to the documentation of this file.
1//===- TileUsingInterface.h - Tiling ops using TilingInterface --*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef MLIR_DIALECT_SCF_TRANSFORMS_TILEUSINGINTERFACE_H
10#define MLIR_DIALECT_SCF_TRANSFORMS_TILEUSINGINTERFACE_H
11
19
20#include <deque>
21
22namespace mlir {
23class Operation;
24class RewriterBase;
25class TilingInterface;
26} // namespace mlir
27
28namespace mlir {
29namespace scf {
30
32 std::function<SmallVector<OpFoldResult>(OpBuilder &, Operation *)>;
33
34/// Computation function returning, for the op currently being tiled or fused,
35/// the per-iteration-domain-dimension `InnerTileAlignment` array.
36///`tileSizes` holds the given tile sizes for pure tiling
37/// and is empty for fusion; `slices` holds the `tensor.extract_slice` (producer
38/// fusion) or `tensor.insert_slice`/`tensor.parallel_insert_slice`s (consumer
39/// fusion) being fused, and is empty for pure tiling. Only pack/unpack
40/// implementations consult the result; every other op ignores it.
41using InnerTileAlignmentFnTy = std::function<SmallVector<InnerTileAlignment>(
42 TilingInterface op, ArrayRef<OpFoldResult> tileSizes,
43 ArrayRef<Operation *> slices)>;
44
45/// Options to use to control tiling.
46struct SCFTilingOptions {
47 /// Specify which loop construct to use for tile and fuse.
48 enum class LoopType { ForOp, ForallOp, CustomOp };
49 LoopType loopType = LoopType::ForOp;
50 SCFTilingOptions &setLoopType(LoopType type) {
51 loopType = type;
52 return *this;
53 }
54
55 /// Computation function that returns the tile sizes to use for each loop.
56 /// Returning a tile size of zero implies no tiling for that loop. If the
57 /// size of the returned vector is smaller than the number of loops, the inner
58 /// loops are not tiled. If the size of the returned vector is larger, then
59 /// the vector is truncated to number of loops.
60 SCFTileSizeComputationFunction tileSizeComputationFunction = nullptr;
61
62 SCFTilingOptions &
63 setTileSizeComputationFunction(SCFTileSizeComputationFunction fun) {
64 tileSizeComputationFunction = std::move(fun);
65 return *this;
66 }
67 /// Convenience function to set the `tileSizeComputationFunction` to a
68 /// function that computes tile sizes at the point they are needed. Allows
69 /// proper interaction with folding.
70 SCFTilingOptions &setTileSizes(ArrayRef<OpFoldResult> tileSizes);
71
72 /// The interchange vector to reorder the tiled loops.
73 SmallVector<int64_t> interchangeVector = {};
74 SCFTilingOptions &setInterchange(ArrayRef<int64_t> interchange) {
75 interchangeVector = llvm::to_vector(interchange);
76 return *this;
77 }
78
79 /// Optional control function returning, per tiled/fused op, the inner tile
80 /// alignment hints.
81 InnerTileAlignmentFnTy innerTileAlignmentFn = nullptr;
82 SCFTilingOptions &setInnerTileAlignmentFn(InnerTileAlignmentFnTy fn) {
83 innerTileAlignmentFn = std::move(fn);
84 return *this;
85 }
86
87 /// Sets a constant `innerTileAlignmentFn` that returns `alignments` for every
88 /// op, ignoring which op is being tiled or fused. Use when a single fixed
89 /// array is correct for the whole tiling/fusion (e.g. tiling a single op).
90 SCFTilingOptions &
91 setInnerTileAlignments(ArrayRef<InnerTileAlignment> alignments) {
92 SmallVector<InnerTileAlignment> fixed = llvm::to_vector(alignments);
93 innerTileAlignmentFn =
94 [fixed = std::move(fixed)](TilingInterface, ArrayRef<OpFoldResult>,
95 ArrayRef<Operation *>) { return fixed; };
96 return *this;
97 }
98
99 //-------------------------------------------------------------------------//
100 // Options related to tiling using `scf.forall`.
101 //-------------------------------------------------------------------------//
102
103 /// Computation function that returns the number of threads to use for
104 /// each loop. Returning a num threads of zero implies no tiling for that
105 /// loop. If the size of the returned vector is smaller than the number of
106 /// loops, the inner loops are not tiled. If the size of the returned vector
107 /// is larger, then the vector is truncated to number of loops. Note: This
108 /// option is only supported with loopType set to `LoopType::ForallOp`. If the
109 /// tile size function is not specified while the num threads computation is,
110 /// then the tile size is determined automatically to map at most one tile per
111 /// thread.
112 SCFTileSizeComputationFunction numThreadsComputationFunction = nullptr;
113
114 SCFTilingOptions &
115 setNumThreadsComputationFunction(SCFTileSizeComputationFunction fun) {
116 numThreadsComputationFunction = std::move(fun);
117 return *this;
118 }
119 /// Convenience function to set the `numThreadsComputationFunction` to a
120 /// function that computes num threads at the point they are needed.
121 SCFTilingOptions &setNumThreads(ArrayRef<OpFoldResult> numThreads);
122
123 /// Specify mapping of loops to devices. This is only respected when the loop
124 /// constructs support such a mapping (like `scf.forall`). Will be ignored
125 /// when using loop constructs that dont support such a mapping (like
126 /// `scf.for`)
127 SmallVector<Attribute> mappingVector = {};
128 SCFTilingOptions &setMapping(ArrayRef<Attribute> mapping) {
129 mappingVector = llvm::to_vector(mapping);
130 return *this;
131 }
132
133 //-------------------------------------------------------------------------//
134 // Options related reduction tiling
135 //-------------------------------------------------------------------------//
136
137 /// Specify how reduction dimensions should be tiled.
138 ReductionTilingStrategy reductionStrategy =
140 SCFTilingOptions &
141 setReductionTilingStrategy(ReductionTilingStrategy strategy) {
142 reductionStrategy = strategy;
143 return *this;
144 }
145
146 /// Specify the reduction dimensions to be tiled. Note that this needs to be
147 /// specified. If left unspecified, then none of the reduction dimensions are
148 /// tiled.
149 SetVector<unsigned> reductionDims;
150 SCFTilingOptions &setReductionDims(ArrayRef<unsigned> dims) {
151 reductionDims.clear();
152 reductionDims.insert(dims.begin(), dims.end());
153 return *this;
154 }
155
156 //-------------------------------------------------------------------------//
157 // Options related to tiling using custom loop.
158 //-------------------------------------------------------------------------//
159
160 // For generating the inter-tile loops using a custom loop, two callback
161 // functions are needed
162 // 1. That generates the "loop header", i.e. the loop that iterates over the
163 // different tiles.
164 // 2. That generates the loop terminator
165 //
166 // For `scf.forall` case the call back to generate loop header would generate
167 //
168 // ```mlir
169 // scf.forall (...) = ... {
170 // ..
171 // }
172 // ```
173 //
174 // and the call back to generate the loop terminator would generate the
175 // `scf.in_parallel` region
176 //
177 // ```mlir
178 // scf.forall (...) = ... {
179 // scf.in_parallel {
180 // tensor.parallel_insert_slice ...
181 // }
182 // }
183 // ```
184 //
185
186 // Information that is to be returned by loop header callback needed for the
187 // rest of the tiled codegeneration.
188 // - `loops`: The generated loops
189 // - `tileOffset`: The values that represent the offset of the iteration space
190 // tile.
191 // - `tileSizes` : The values that represent the size of the iteration space
192 // tile.
193 // - `destinationTensors` : The tensors to use as destinations during tiling.
194 struct CustomLoopHeaderInfo {
196 SmallVector<OpFoldResult> tileOffset;
198 SmallVector<Value> destinationTensors;
199 };
200
201 // Type of the callback function that generates the loop headers.
202 // - `loopRanges` : Values that represent the full size of the iteration space
203 // being tiled.
204 // - `givenTileSizes` : The tile sizes that are to be used to tile the
205 // iteration space.
206 // - `destinationTensors` : The tensors to use as destinations for the results
207 // of the tiled loop for loops that implement
208 // `DestinationStyleOpInterface`.
209 // Returns the `CustomLoopHeaderInfo` object (described above). it is expected
210 // that this function sets the insertion point of `rewriter` to the program
211 // point where the intra-tile loop computation is to be generated.
212 using GenerateLoopHeaderFn = std::function<FailureOr<CustomLoopHeaderInfo>(
213 RewriterBase &rewriter, Location loc, ArrayRef<Range> loopRanges,
214 ArrayRef<OpFoldResult> givenTileSizes, ValueRange destinationTensors)>;
215
216 // Type of the callback function that generates the loop terminator.
217 // - `loops` : generated loops from the GenerateLoopHeaderFn callback
218 // - `tiledResults` : Tiles of the result computed for the iteration space
219 // tile.
220 // - `resultOffsets` : For each of the `tiledResults`, the offset at which
221 // the result tile is to be "inserted" back into the
222 // destination tensor.
223 // - `resultSizes` : For each of the `tiledResults`, the size of the result
224 // tile that is to be "inserted" back into the destination
225 // tensor.
226 // Returns the `CustomLoopHeaderInfo` object (described above)
227 using GenerateLoopTerminatorFn = std::function<LogicalResult(
229 ValueRange tiledResults,
230 ArrayRef<SmallVector<OpFoldResult>> resultOffsets,
232 ValueRange destinationTensors)>;
233
234 // Callback function to generate the inter-tile loop header.
235 GenerateLoopHeaderFn generateLoopHeaderFn = nullptr;
236 // Callback function to generate the inter-tile loop terminator.
237 GenerateLoopTerminatorFn generateLoopTerminatorFn = nullptr;
238 // Helper function to set the callbacks for inter-tile loop header and
239 // terminator functions when using a custom operation for the loop.
240 SCFTilingOptions &
241 setCustomLoopGenerationFns(GenerateLoopHeaderFn headerFn,
242 GenerateLoopTerminatorFn terminatorFn) {
243 generateLoopHeaderFn = std::move(headerFn);
244 generateLoopTerminatorFn = std::move(terminatorFn);
245 return *this;
246 }
247};
248
249/// Transformation information returned after tiling.
250struct SCFTilingResult {
251 /// Tiled operations that are generated during tiling. The order does not
252 /// matter except the last op. The replacements are expected to be the results
253 /// of the last op.
255 /// The initial destination values passed to the tiled operations.
256 SmallVector<Value> initialValues;
257 /// The `scf.for` operations that iterate over the tiles.
259 /// Values to use as replacements for the untiled op. Is the same size as the
260 /// number of results of the untiled op.
261 SmallVector<Value> replacements;
262 /// Slices generated after tiling that can be used for fusing with the tiled
263 /// producer.
264 SmallVector<Operation *> generatedSlices;
265 /// In cases where there as an additional merge step after tiling
266 /// return the merged ops after tiling. This list is empty when reduction
267 /// tiling strategy is
268 /// `scf::SCFTilingOptions::ReductionTilingStrategy::FullReduction.
270};
271
272/// Method to tile an op that implements the `TilingInterface` using
273/// `scf.for` for iterating over the tiles.
274FailureOr<SCFTilingResult> tileUsingSCF(RewriterBase &rewriter,
275 TilingInterface op,
276 const SCFTilingOptions &options);
277
278/// Options used to control tile + fuse.
280 /// The tiling options used to control the tiling of the consumer.
281 SCFTilingOptions tilingOptions;
284 return *this;
285 }
286
287 /// Control function to check if a slice needs to be fused or not,
288 /// The control function receives
289 /// 1) the slice along which fusion is to be done,
290 /// 2) the producer value that is to be fused
291 /// 3) a boolean value set to `true` if the fusion is from
292 /// a destination operand.
293 /// The control function returns an `std::optiona<ControlFnResult>`.
294 /// If the return value is `std::nullopt`, that implies no fusion
295 /// is to be performed along that slice.
297 /// Set to true if the loop nest has to return a replacement value
298 /// for the fused producer.
300 };
301 using ControlFnTy = std::function<std::optional<ControlFnResult>(
302 tensor::ExtractSliceOp candidateSliceOp, OpResult originalProducer,
303 bool isDestinationOperand)>;
304 /// The default control function implements greedy fusion without yielding
305 /// a replacement for any of the fused results.
306 ControlFnTy fusionControlFn = [](tensor::ExtractSliceOp, OpResult,
307 bool) -> std::optional<ControlFnResult> {
308 return ControlFnResult{};
309 };
311 fusionControlFn = controlFn;
312 return *this;
313 }
314
315 /// An optional set of rewrite patterns to apply to the results of tiling
316 /// before fusion. This will track deleted and newly inserted
317 /// `tensor.extract_slice` ops and update the worklist.
318 std::optional<FrozenRewritePatternSet> cleanupPatterns = std::nullopt;
319};
320
321/// Result of fusing the producer of the source of a `tensor.extract_slice`.
328/// Fuse the producer of the source of `candidateSliceOp` by computing the
329/// required slice of the producer in-place. Note that the method
330/// replaces the uses of `candidateSliceOp` with the tiled and fused producer
331/// value but does not delete the slice operation.
332///
333/// When the fused producer is a `linalg.pack`/`linalg.unpack`, `fn` (if
334/// non-null) is invoked with the producer and `candidateSliceOp` to obtain the
335/// inner-tile alignment hint in the producer's own iteration domain.
336std::optional<SCFFuseProducerOfSliceResult>
338 tensor::ExtractSliceOp candidateSliceOp,
340 const InnerTileAlignmentFnTy &fn = nullptr);
341
342/// Reconstruct the fused producer from within the tiled-and-fused code. Based
343/// on the slice of the producer computed in place it is possible that within
344/// the loop nest same slice of the producer is computed multiple times. It is
345/// in general not possible to recompute the value of the fused producer from
346/// the tiled loop code in such cases. For the cases where no slice of the
347/// producer is computed in a redundant fashion it is possible to reconstruct
348/// the value of the original producer from within the tiled loop. It is upto
349/// the caller to ensure that the producer is not computed redundantly within
350/// the tiled loop nest. For example, consider
351///
352/// ```mlir
353/// %0 = linalg.matmul ins(...) outs(...) -> tensor<?x?xf32>
354/// %1 = linalg.matmul ins(%0, ..) outs(...) -> tensor<?x?x?f32>
355/// ```
356///
357/// If `%1` is tiled in a 2D fashion and `%0` is fused with it, the resulting IR
358/// is,
359///
360/// ```mlir
361/// %t1_0 = scf.for .... iter_args(%arg0 = ...) {
362/// %t1_1 = scf.for ... iter_args(%arg1 = %arg0) {
363/// ...
364/// %t1_2 = linalg.matmul ins(...) outs(...) -> tensor<?x?xf32>
365/// %t1_3 = linalg.matmul ins(%t1_2, ...)
366/// %t1_4 = tensor.insert_slice %t1_3 into %arg1 ...
367/// scf.yield %t1_4
368/// }
369/// scf.yield %t1_1
370/// }
371/// ```
372///
373/// Here `%t1_2` is the same for all iterations of the inner `scf.for`. Instead
374/// if `%1` were tiled only along the rows, the resultant code would be
375///
376/// ```mlir
377/// %t2_0 = scf.for .... iter_args(%arg0 = ...) {
378/// ...
379/// %t2_1 = linalg.matmul ins(...) outs(...) -> tensor<?x?xf32>
380/// %t2_2 = linalg.matmul ins(%t2_1, ...)
381/// %t2_3 = tensor.insert_slice %t2_2 into %arg0 ...
382/// scf.yield %t2_3
383/// }
384/// ```
385///
386/// Here there is no intersection in the different slices of `%t2_1` computed
387/// across iterations of the `scf.for`. In such cases, the value of the original
388/// `%0` can be reconstructed from within the loop body. This is useful in cases
389/// where `%0` had other uses as well. If not reconstructed from within the loop
390/// body, uses of `%0` could not be replaced, making it still live and the
391/// fusion immaterial.
392///
393/// The @param `yieldResultNumber` decides which result would be yield. If not
394/// given, yield all `opResult` of fused producer.
395///
396/// The method returns the list of new slices added during the process (which
397/// can be used to fuse along).
398FailureOr<SmallVector<Operation *>> yieldReplacementForFusedProducer(
399 RewriterBase &rewriter, tensor::ExtractSliceOp sliceOp,
400 scf::SCFFuseProducerOfSliceResult fusedProducerInfo,
402 ArrayRef<unsigned> yieldResultNumber = ArrayRef<unsigned>{});
403
404/// Transformation information returned after tile and fuse.
406 /// List of untiled operations that were fused with the tiled consumer.
408 /// List of tiled and fused operations generated. The first element is always
409 /// the tiled version of the original consumer operation processed by
410 /// `tileConsumerAndFuseProducersUsingSCF`, followed by any operations that
411 /// were fused with it.
413 /// The `scf.for` operations that iterate over the tiles.
415 /// The replacement values to use for the tiled and fused operations.
417};
418
419/// Method to tile and fuse a sequence of operations, by tiling the consumer
420/// and fusing its producers. Note that this assumes that it is valid to
421/// tile+fuse the producer into the innermost tiled loop. Its up to the caller
422/// to ensure that the tile sizes provided make this fusion valid.
423///
424/// For example, for the following sequence
425///
426/// ```mlir
427/// %0 =
428/// %1 = linalg.fill ... outs(%0 : ... )
429/// %2 = linalg.matmul ... outs(%1 : ...) ...
430/// ```
431///
432/// it is legal to fuse the fill with the matmul only if the matmul is tiled
433/// along the parallel dimensions and not the reduction dimension, i.e. the tile
434/// size for the reduction dimension should be 0. The resulting fused
435/// transformation is
436///
437/// ```mlir
438/// %1 = scf.for ... iter_args(%arg0 = %0)
439/// %2 = tensor.extract_slice %arg0
440/// %3 = linalg.fill .. outs(%2 : ... )
441/// %4 = linalg.matmul .. outs(%3 : ...)
442/// }
443/// ```
444FailureOr<SCFTileAndFuseResult>
446 TilingInterface consumer,
448
449/// Fuse the consumer `candidateSlices` by computing the required slice of the
450/// consumer in-place. All the entries of `candidateSlices` are expected to map
451/// to the same consumer. The method returns an error if the consumer cannot be
452/// tiled in a manner that is consistent for all the passed slices. Note that
453/// the method replaces the uses of `candidateSlices` with the tiled and fused
454/// consumer value but does not delete the slice operations.
455/// TODO(MaheshRavishankar): A more natural way of exposing the consumer fusion
456/// is to take the consumer operation, and find the slices to use for fusion
457/// by walking its operands to the `loops` and then into the body to get the
458/// slices used for fusion.
466/// When the consumer is a `linalg.pack`/`linalg.unpack`, `fn` (if non-null) is
467/// invoked with the consumer and `candidateSlices` to obtain the inner-tile
468/// alignment hint in the consumer's own iteration domain.
469FailureOr<scf::SCFFuseConsumerOfSliceResult>
471 ArrayRef<Operation *> candidateSlices,
473 const InnerTileAlignmentFnTy &fn = nullptr);
474
475/// Fuse the `consumer` operation into the loop nest provided by `loops`.
476/// The transformation looks for operands in the `consumer` that are defined
477/// by the outermost loop of the loop nest in `loops`. The nested loop is
478/// expected to have the structure of the loops generated through tiling.
479///
480/// When the consumer is a `linalg.pack`/`linalg.unpack`, `fn` (if non-null) is
481/// invoked with the `consumer` and the fused slices to obtain the inner-tile
482/// alignment hint in the consumer's own iteration domain.
483FailureOr<scf::SCFFuseConsumerOfSliceResult>
484tileAndFuseConsumer(RewriterBase &rewriter, Operation *consumer,
486 const InnerTileAlignmentFnTy &fn = nullptr);
487
488/// Method to lower an `op` that implements the `TilingInterface` to
489/// loops/scalars.
490FailureOr<SmallVector<scf::ForOp>>
491lowerToLoopsUsingSCFForOp(RewriterBase &rewriter, TilingInterface op);
492
493/// Method to tile a reduction and generate a parallel op within a serial loop.
494/// Each of the partial reductions are calculated in parallel. Then after the
495/// loop all the partial reduction are merged into a final reduction.
496/// For example for the following sequence
497///
498/// ```mlir
499/// %0 = linalg.generic %in ["parallel", "reduction"]
500/// : tensor<7x9xf32> -> tensor<7xf32>
501/// ```
502///
503/// into:
504///
505/// ```mlir
506/// %0 = linalg.fill ... : tensor<7x4xf32>
507/// %1 = scf.for ... iter_args(%arg0 = %0)
508/// %2 = tensor.extract_slice %arg0 : tensor<7x4xf32> -> tensor<7x?xf32>
509/// %3 = tensor.extract_slice %in : tensor<7x9xf32> -> tensor<7x?xf32>
510/// %4 = linalg.generic %2, %3 ["parallel", "parallel"]
511/// : tensor<7x?xf32> -> tensor<7x?xf32>
512/// %5 = tensor.insert_slice %3, %0[0, 0] : tensor<7x4xf32>
513/// }
514/// %6 = linalg.generic %1 ["parallel", "reduction"]
515/// : tensor<7x4xf32> -> tensor<7xf32>
516/// ```
517FailureOr<scf::SCFTilingResult>
518tileReductionUsingScf(RewriterBase &b, PartialReductionOpInterface op,
519 ArrayRef<OpFoldResult> tileSizes);
520
521} // namespace scf
522} // namespace mlir
523
524#endif // MLIR_DIALECT_SCF_TRANSFORMS_TILEUSINGINTERFACE_H
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
static llvm::ManagedStatic< PassManagerOptions > options
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
This class helps build Operations.
Definition Builders.h:209
This is a value defined by a result of an operation.
Definition Value.h:454
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
This class provides an abstraction over the different types of ranges over Values.
Definition ValueRange.h:389
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
std::function< SmallVector< OpFoldResult >(OpBuilder &, Operation *)> SCFTileSizeComputationFunction
SmallVector< Operation * > mergeOps
Computation function returning, for the op currently being tiled or fused, the per-iteration-domain-d...
Include the generated interface declarations.
FailureOr< scf::SCFTilingResult > tileReductionUsingScf(RewriterBase &b, PartialReductionOpInterface op, ArrayRef< OpFoldResult > tileSizes)
Method to tile a reduction and generate a parallel op within a serial loop.
ReductionTilingStrategy
Tiling can be thought of as splitting a dimension into 2 and materializing the outer dimension as a l...
FailureOr< scf::SCFFuseConsumerOfSliceResult > tileAndFuseConsumerOfSlices(RewriterBase &rewriter, ArrayRef< Operation * > candidateSlices, MutableArrayRef< LoopLikeOpInterface > loops, const InnerTileAlignmentFnTy &fn=nullptr)
When the consumer is a linalg.pack/linalg.unpack, fn (if non-null) is invoked with the consumer and c...
FailureOr< scf::SCFFuseConsumerOfSliceResult > tileAndFuseConsumer(RewriterBase &rewriter, Operation *consumer, MutableArrayRef< LoopLikeOpInterface > loops, const InnerTileAlignmentFnTy &fn=nullptr)
Fuse the consumer operation into the loop nest provided by loops.
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:125
FailureOr< SCFTileAndFuseResult > tileConsumerAndFuseProducersUsingSCF(RewriterBase &rewriter, TilingInterface consumer, const SCFTileAndFuseOptions &options)
Method to tile and fuse a sequence of operations, by tiling the consumer and fusing its producers.
FailureOr< SmallVector< scf::ForOp > > lowerToLoopsUsingSCFForOp(RewriterBase &rewriter, TilingInterface op)
Method to lower an op that implements the TilingInterface to loops/scalars.
FailureOr< SmallVector< Operation * > > yieldReplacementForFusedProducer(RewriterBase &rewriter, tensor::ExtractSliceOp sliceOp, scf::SCFFuseProducerOfSliceResult fusedProducerInfo, MutableArrayRef< LoopLikeOpInterface > loops, ArrayRef< unsigned > yieldResultNumber=ArrayRef< unsigned >{})
Reconstruct the fused producer from within the tiled-and-fused code.
std::optional< SCFFuseProducerOfSliceResult > tileAndFuseProducerOfSlice(RewriterBase &rewriter, tensor::ExtractSliceOp candidateSliceOp, MutableArrayRef< LoopLikeOpInterface > loops, const InnerTileAlignmentFnTy &fn=nullptr)
Fuse the producer of the source of candidateSliceOp by computing the required slice of the producer i...
FailureOr< SCFTilingResult > tileUsingSCF(RewriterBase &rewriter, TilingInterface op, const SCFTilingOptions &options)
Method to tile an op that implements the TilingInterface using scf.for for iterating over the tiles.
Fuse the consumer candidateSlices by computing the required slice of the consumer in-place.
SmallVector< Operation * > tiledOps
SmallVector< OpOperand * > origConsumerOperands
SmallVector< OpOperand * > tiledAndFusedConsumerOperands
Result of fusing the producer of the source of a tensor.extract_slice.
SmallVector< Operation * > generatedSlices
SmallVector< Operation * > tiledOps
Control function to check if a slice needs to be fused or not, The control function receives 1) the s...
bool yieldProducerReplacement
Set to true if the loop nest has to return a replacement value for the fused producer.
Options used to control tile + fuse.
std::optional< FrozenRewritePatternSet > cleanupPatterns
An optional set of rewrite patterns to apply to the results of tiling before fusion.
std::function< std::optional< ControlFnResult >( tensor::ExtractSliceOp candidateSliceOp, OpResult originalProducer, bool isDestinationOperand)> ControlFnTy
SCFTileAndFuseOptions & setFusionControlFn(ControlFnTy controlFn)
SCFTileAndFuseOptions & setTilingOptions(SCFTilingOptions options)
SCFTilingOptions tilingOptions
The tiling options used to control the tiling of the consumer.
ControlFnTy fusionControlFn
The default control function implements greedy fusion without yielding a replacement for any of the f...
Transformation information returned after tile and fuse.
SmallVector< LoopLikeOpInterface > loops
The scf.for operations that iterate over the tiles.
llvm::SetVector< Operation * > tiledAndFusedOps
List of tiled and fused operations generated.
llvm::SetVector< Operation * > fusedProducers
List of untiled operations that were fused with the tiled consumer.
llvm::DenseMap< Value, Value > replacements
The replacement values to use for the tiled and fused operations.