31#include "llvm/Support/CommandLine.h"
37#define GEN_PASS_DEF_AFFINEDATACOPYGENERATION
38#include "mlir/Dialect/Affine/Passes.h.inc"
42#define DEBUG_TYPE "affine-data-copy-generate"
60struct AffineDataCopyGeneration
61 :
public affine::impl::AffineDataCopyGenerationBase<
62 AffineDataCopyGeneration> {
63 AffineDataCopyGeneration() =
default;
64 explicit AffineDataCopyGeneration(
unsigned slowMemorySpace,
65 unsigned fastMemorySpace,
66 unsigned tagMemorySpace,
67 int minDmaTransferSize,
68 uint64_t fastMemCapacityBytes) {
69 this->slowMemorySpace = slowMemorySpace;
70 this->fastMemorySpace = fastMemorySpace;
71 this->tagMemorySpace = tagMemorySpace;
72 this->minDmaTransferSize = minDmaTransferSize;
73 this->fastMemoryCapacity = fastMemCapacityBytes / 1024;
76 void runOnOperation()
override;
80 Value zeroIndex =
nullptr;
88std::unique_ptr<OperationPass<func::FuncOp>>
90 unsigned slowMemorySpace,
unsigned fastMemorySpace,
unsigned tagMemorySpace,
91 int minDmaTransferSize, uint64_t fastMemCapacityBytes) {
92 return std::make_unique<AffineDataCopyGeneration>(
93 slowMemorySpace, fastMemorySpace, tagMemorySpace, minDmaTransferSize,
94 fastMemCapacityBytes);
96std::unique_ptr<OperationPass<func::FuncOp>>
98 return std::make_unique<AffineDataCopyGeneration>();
105void AffineDataCopyGeneration::runOnBlock(
Block *block,
110 uint64_t fastMemCapacityBytes =
111 fastMemoryCapacity != std::numeric_limits<uint64_t>::max()
112 ? fastMemoryCapacity * 1024
113 : fastMemoryCapacity;
115 fastMemorySpace, tagMemorySpace,
116 fastMemCapacityBytes};
127 auto curBegin = llvm::find_if(*block, [&](
Operation &op) {
128 return isa<AffineLoadOp, AffineStoreOp, AffineForOp>(op) &&
129 copyNests.count(&op) == 0;
134 while (it != block->
end()) {
137 if ((forOp = dyn_cast<AffineForOp>(&*it)) && copyNests.count(forOp) == 0) {
139 (void)affineDataCopyGenerate(curBegin, it, copyOptions,
140 std::nullopt, copyNests);
143 auto exceedsCapacity = [&](AffineForOp forOp) {
144 std::optional<int64_t> footprint =
147 return (footprint.has_value() &&
148 static_cast<uint64_t
>(*footprint) > fastMemCapacityBytes);
157 bool recurseInner = skipNonUnitStrideLoops ? forOp.getStep() != 1
158 : exceedsCapacity(forOp);
162 runOnBlock(forOp.getBody(), copyNests);
172 (void)affineDataCopyGenerate(it, std::next(it),
174 std::nullopt, copyNests);
177 curBegin = std::find_if(std::next(it), block->
end(), [&](Operation &op) {
178 return isa<AffineLoadOp, AffineStoreOp, AffineForOp>(op) &&
179 copyNests.count(&op) == 0;
183 assert(copyNests.count(&*it) == 0 &&
184 "all copy nests generated should have been skipped above");
191 if (curBegin != block->
end()) {
193 assert(!curBegin->hasTrait<OpTrait::IsTerminator>() &&
194 "can't be a terminator");
196 (void)affineDataCopyGenerate(curBegin,
197 std::prev(block->
end()), copyOptions,
198 std::nullopt, copyNests);
202void AffineDataCopyGeneration::runOnOperation() {
203 func::FuncOp f = getOperation();
204 OpBuilder topBuilder(f.getBody());
214 for (
auto &block : f)
215 runOnBlock(&block, copyNests);
219 SmallVector<Operation *, 4> copyOps;
220 for (Operation *nest : copyNests)
223 nest->walk([&](Operation *op) {
224 if (
auto forOp = dyn_cast<AffineForOp>(op))
226 else if (isa<AffineLoadOp, AffineStoreOp>(op))
227 copyOps.push_back(op);
236 FrozenRewritePatternSet frozenPatterns(std::move(
patterns));
238 copyOps, frozenPatterns,
239 GreedyRewriteConfig().setStrictness(
240 GreedyRewriteStrictness::ExistingAndNewOps));
Block represents an ordered list of Operations.
Operation is the basic unit of execution within MLIR.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
LogicalResult promoteIfSingleIteration(AffineForOp forOp)
Promotes the loop body of a AffineForOp to its containing block if the loop was known to have a singl...
std::optional< int64_t > getMemoryFootprintBytes(AffineForOp forOp, int memorySpace=-1)
Gets the memory footprint of all data touched in the specified memory space in bytes; if the memory s...
std::unique_ptr< OperationPass< func::FuncOp > > createAffineDataCopyGenerationPass()
Overload relying on pass options for initialization.
Include the generated interface declarations.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
LogicalResult applyOpPatternsGreedily(ArrayRef< Operation * > ops, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr, bool *allErased=nullptr)
Rewrite the specified ops by repeatedly applying the highest benefit patterns in a greedy worklist dr...
const FrozenRewritePatternSet & patterns
Explicit copy / DMA generation options for mlir::affineDataCopyGenerate.