//===- PipelineDataTransfer.cpp --- Pass for pipelining data movement ---*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements a pass to pipeline data transfers. // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Affine/Passes.h" #include "mlir/Dialect/Affine/Analysis/AffineAnalysis.h" #include "mlir/Dialect/Affine/Analysis/LoopAnalysis.h" #include "mlir/Dialect/Affine/Analysis/Utils.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/LoopUtils.h" #include "mlir/Dialect/Affine/Utils.h" #include "mlir/Dialect/Arith/Utils/Utils.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Builders.h" #include "mlir/Transforms/Passes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Debug.h" namespace mlir { namespace affine { #define GEN_PASS_DEF_AFFINEPIPELINEDATATRANSFER #include "mlir/Dialect/Affine/Passes.h.inc" } // namespace affine } // namespace mlir #define DEBUG_TYPE … usingnamespacemlir; usingnamespacemlir::affine; namespace { struct PipelineDataTransfer : public affine::impl::AffinePipelineDataTransferBase< PipelineDataTransfer> { … }; } // namespace /// Creates a pass to pipeline explicit movement of data across levels of the /// memory hierarchy. std::unique_ptr<OperationPass<func::FuncOp>> mlir::affine::createPipelineDataTransferPass() { … } // Returns the position of the tag memref operand given a DMA operation. // Temporary utility: will be replaced when DmaStart/DmaFinish abstract op's are // added. static unsigned getTagMemRefPos(Operation &dmaOp) { … } /// Doubles the buffer of the supplied memref on the specified 'affine.for' /// operation by adding a leading dimension of size two to the memref. /// Replaces all uses of the old memref by the new one while indexing the newly /// added dimension by the loop IV of the specified 'affine.for' operation /// modulo 2. Returns false if such a replacement cannot be performed. static bool doubleBuffer(Value oldMemRef, AffineForOp forOp) { … } /// Returns success if the IR is in a valid state. void PipelineDataTransfer::runOnOperation() { … } // Check if tags of the dma start op and dma wait op match. static bool checkTagMatch(AffineDmaStartOp startOp, AffineDmaWaitOp waitOp) { … } // Identify matching DMA start/finish operations to overlap computation with. static void findMatchingStartFinishInsts( AffineForOp forOp, SmallVectorImpl<std::pair<Operation *, Operation *>> &startWaitPairs) { … } /// Overlap DMA transfers with computation in this loop. If successful, /// 'forOp' is deleted, and a prologue, a new pipelined loop, and epilogue are /// inserted right before where it was. void PipelineDataTransfer::runOnAffineForOp(AffineForOp forOp) { … }