49 if (
auto subviewUse = dyn_cast<memref::SubViewOp>(user)) {
53 MemRefType newType = memref::SubViewOp::inferRankReducedResultType(
54 subviewUse.getType().getShape(), cast<MemRefType>(val.
getType()),
55 subviewUse.getStaticOffsets(), subviewUse.getStaticSizes(),
56 subviewUse.getStaticStrides());
57 Value newSubview = memref::SubViewOp::create(
58 rewriter, subviewUse->getLoc(), newType, val,
59 subviewUse.getMixedOffsets(), subviewUse.getMixedSizes(),
60 subviewUse.getMixedStrides());
83 unsigned multiBufferingFactor,
84 bool skipOverrideAnalysis) {
85 LLVM_DEBUG(
DBGS() <<
"Start multibuffering: " << allocOp <<
"\n");
87 LoopLikeOpInterface candidateLoop;
89 auto parentLoop = user->getParentOfType<LoopLikeOpInterface>();
91 if (isa<memref::DeallocOp>(user)) {
97 LLVM_DEBUG(
DBGS() <<
"--no parent loop -> fail\n");
98 LLVM_DEBUG(
DBGS() <<
"----due to user: " << *user <<
"\n");
101 if (!skipOverrideAnalysis) {
104 LLVM_DEBUG(
DBGS() <<
"--Skip user: found loop-carried dependence\n");
108 if (llvm::any_of(allocOp->getUsers(), [&](
Operation *otherUser) {
109 return !dom.dominates(user, otherUser);
112 DBGS() <<
"--Skip user: does not dominate all other users\n");
116 if (llvm::any_of(allocOp->getUsers(), [&](
Operation *otherUser) {
117 return !isa<memref::DeallocOp>(otherUser) &&
118 !parentLoop->isProperAncestor(otherUser);
122 <<
"--Skip user: not all other users are in the parent loop\n");
126 candidateLoop = parentLoop;
130 if (!candidateLoop) {
131 LLVM_DEBUG(
DBGS() <<
"Skip alloc: no candidate loop\n");
135 std::optional<Value> inductionVar = candidateLoop.getSingleInductionVar();
136 std::optional<OpFoldResult> lowerBound = candidateLoop.getSingleLowerBound();
137 std::optional<OpFoldResult> singleStep = candidateLoop.getSingleStep();
138 if (!inductionVar || !lowerBound || !singleStep ||
139 !llvm::hasSingleElement(candidateLoop.getLoopRegions())) {
140 LLVM_DEBUG(
DBGS() <<
"Skip alloc: no single iv, lb, step or region\n");
144 if (!dom.
dominates(allocOp.getOperation(), candidateLoop)) {
145 LLVM_DEBUG(
DBGS() <<
"Skip alloc: does not dominate candidate loop\n");
149 LLVM_DEBUG(
DBGS() <<
"Start multibuffering loop: " << candidateLoop <<
"\n");
154 llvm::append_range(multiBufferedShape, originalShape);
155 LLVM_DEBUG(
DBGS() <<
"--original type: " << allocOp.getType() <<
"\n");
159 LLVM_DEBUG(
DBGS() <<
"--multi-buffered type: " << mbMemRefType <<
"\n");
165 auto mbAlloc = memref::AllocOp::create(rewriter, loc, mbMemRefType,
167 LLVM_DEBUG(
DBGS() <<
"--multi-buffered alloc: " << mbAlloc <<
"\n");
172 &candidateLoop.getLoopRegions().front()->front());
173 Value ivVal = *inductionVar;
179 rewriter, loc, ((iv - lb).floorDiv(step)) % multiBufferingFactor,
180 {ivVal, lbVal, stepVal});
181 LLVM_DEBUG(
DBGS() <<
"--multi-buffered indexing: " << bufferIndex <<
"\n");
185 int64_t mbMemRefTypeRank = mbMemRefType.getRank();
192 offsets.front() = bufferIndex;
194 for (
int64_t i = 0, e = originalShape.size(); i != e; ++i)
197 MemRefType dstMemref = memref::SubViewOp::inferRankReducedResultType(
198 originalShape, mbMemRefType, offsets, sizes, strides);
199 Value subview = memref::SubViewOp::create(rewriter, loc, dstMemref, mbAlloc,
200 offsets, sizes, strides);
201 LLVM_DEBUG(
DBGS() <<
"--multi-buffered slice: " << subview <<
"\n");
205 for (
OpOperand &use : llvm::make_early_inc_range(allocOp->getUses())) {
206 auto deallocOp = dyn_cast<memref::DeallocOp>(use.getOwner());
212 memref::DeallocOp::create(rewriter, deallocOp->getLoc(), mbAlloc);
214 LLVM_DEBUG(
DBGS() <<
"----Created dealloc: " << newDeallocOp <<
"\n");