xref: /llvm-project/mlir/include/mlir/Dialect/Linalg/Transforms/Hoisting.h (revision 2bff9d9ffe3a4813961c1cf3af2e9ac5a20190bd)
1 //===- Hoisting.h - Linalg hoisting transformations -------------*- 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_LINALG_TRANSFORMS_HOISTING_H_
10 #define MLIR_DIALECT_LINALG_TRANSFORMS_HOISTING_H_
11 
12 namespace mlir {
13 class Operation;
14 class RewriterBase;
15 namespace scf {
16 class ForOp;
17 } // namespace scf
18 
19 namespace linalg {
20 
21 /// Hoist vector.transfer_read/vector.transfer_write on buffers pairs out of
22 /// immediately enclosing scf::ForOp iteratively, if the following conditions
23 /// are true:
24 ///   1. The two ops access the same memref with the same indices.
25 ///   2. All operands are invariant under the enclosing scf::ForOp.
26 ///   3. No uses of the memref either dominate the transfer_read or are
27 ///   dominated by the transfer_write (i.e. no aliasing between the write and
28 ///   the read across the loop)
29 ///   4. The source operands for vector.transfer_{read|write} do not originate
30 ///   from Ops implementing ViewLikeOpInterface (to reduce the risk of
31 ///   aliasing).
32 ///   5. If `verifyNonZeroTrip` is true, then the lower bound of the loop must
33 ///   be statically smaller than the upper bound of the loop, guaranteeing that
34 ///   the loop body will execute at least once.
35 /// To improve hoisting opportunities, call the `moveLoopInvariantCode` helper
36 /// function on the candidate loop above which to hoist. Hoisting the transfers
37 /// results in scf::ForOp yielding the value that originally transited through
38 /// memory.
39 ///
40 /// TODO: To further improve hoisting opportunities, fold aliasing memref
41 /// operations into respective vector.transfer{read|write} operations and
42 /// avoid using ops implementing ViewLikeOpInterface as the source for transfer
43 /// Ops.
44 ///
45 /// WARNING: This hoisting does not model parallelism and is generally incorrect
46 /// when used on distributed loops with memref semantics!
47 /// NOTE: Setting `verifyNonZeroTrip = true` makes this more stable for
48 /// distributed loops with memref semantics, but there could still be some
49 /// issues when loops are executed a different number of times for different
50 /// threads.
51 void hoistRedundantVectorTransfers(Operation *root,
52                                    bool verifyNonZeroTrip = false);
53 
54 /// Hoist vector.extract/vector.broadcast pairs out of immediately enclosing
55 /// scf::ForOp iteratively, if the following conditions are met:
56 ///   1. The vector.extract operation is applied on an iter_argument, and no
57 ///   other operator is using this argument in the body of the loop.
58 ///   2. The position of the vector.extract is either a static value, or defined
59 ///   outside of the loop.
60 ///   3. The vector.broadcast operation is yielded by the loop.
61 /// To improve hoisting opportunities, call the `moveLoopInvariantCode` helper
62 /// function on the candidate loop above which to hoist.
63 void hoistRedundantVectorBroadcasts(RewriterBase &rewriter, Operation *root);
64 
65 } // namespace linalg
66 } // namespace mlir
67 
68 #endif // MLIR_DIALECT_LINALG_TRANSFORMS_HOISTING_H_
69