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