@@ -43,50 +43,34 @@ static bool overrideBuffer(Operation *op, Value buffer) {
4343// / propagate the type change and erase old subview ops.
4444static void replaceUsesAndPropagateType (RewriterBase &rewriter,
4545 Operation *oldOp, Value val) {
46- SmallVector<Operation *> opsToDelete;
47- SmallVector<OpOperand *> operandsToReplace;
48-
49- // Save the operand to replace / delete later (avoid iterator invalidation).
50- // TODO: can we use an early_inc iterator?
51- for (OpOperand &use : oldOp->getUses ()) {
52- // Non-subview ops will be replaced by `val`.
53- auto subviewUse = dyn_cast<memref::SubViewOp>(use.getOwner ());
54- if (!subviewUse) {
55- operandsToReplace.push_back (&use);
46+ // Iterate with early_inc to erase current user inside the loop.
47+ for (OpOperand &use : llvm::make_early_inc_range (oldOp->getUses ())) {
48+ Operation *user = use.getOwner ();
49+ if (auto subviewUse = dyn_cast<memref::SubViewOp>(user)) {
50+ // `subview(old_op)` is replaced by a new `subview(val)`.
51+ OpBuilder::InsertionGuard g (rewriter);
52+ rewriter.setInsertionPoint (subviewUse);
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 ());
61+
62+ // Ouch recursion ... is this really necessary?
63+ replaceUsesAndPropagateType (rewriter, subviewUse, newSubview);
64+
65+ // Safe to erase.
66+ rewriter.eraseOp (subviewUse);
5667 continue ;
5768 }
58-
59- // `subview(old_op)` is replaced by a new `subview(val)`.
60- OpBuilder::InsertionGuard g (rewriter);
61- rewriter.setInsertionPoint (subviewUse);
62- MemRefType newType = memref::SubViewOp::inferRankReducedResultType (
63- subviewUse.getType ().getShape (), cast<MemRefType>(val.getType ()),
64- subviewUse.getStaticOffsets (), subviewUse.getStaticSizes (),
65- subviewUse.getStaticStrides ());
66- Value newSubview = memref::SubViewOp::create (
67- rewriter, subviewUse->getLoc (), newType, val,
68- subviewUse.getMixedOffsets (), subviewUse.getMixedSizes (),
69- subviewUse.getMixedStrides ());
70-
71- // Ouch recursion ... is this really necessary?
72- replaceUsesAndPropagateType (rewriter, subviewUse, newSubview);
73-
74- opsToDelete.push_back (use.getOwner ());
69+ // Non-subview: replace with new value.
70+ rewriter.startOpModification (user);
71+ use.set (val);
72+ rewriter.finalizeOpModification (user);
7573 }
76-
77- // Perform late replacement.
78- // TODO: can we use an early_inc iterator?
79- for (OpOperand *operand : operandsToReplace) {
80- Operation *op = operand->getOwner ();
81- rewriter.startOpModification (op);
82- operand->set (val);
83- rewriter.finalizeOpModification (op);
84- }
85-
86- // Perform late op erasure.
87- // TODO: can we use an early_inc iterator?
88- for (Operation *op : opsToDelete)
89- rewriter.eraseOp (op);
9074}
9175
9276// Transformation to do multi-buffering/array expansion to remove dependencies
@@ -216,8 +200,8 @@ mlir::memref::multiBuffer(RewriterBase &rewriter, memref::AllocOp allocOp,
216200 offsets, sizes, strides);
217201 LLVM_DEBUG (DBGS () << " --multi-buffered slice: " << subview << " \n " );
218202
219- // 5. Due to the recursive nature of replaceUsesAndPropagateType , we need to
220- // handle dealloc uses separately..
203+ // 5. Due to the recursive nature of replaceUsesAndPropagateType , we need
204+ // to handle dealloc uses separately..
221205 for (OpOperand &use : llvm::make_early_inc_range (allocOp->getUses ())) {
222206 auto deallocOp = dyn_cast<memref::DeallocOp>(use.getOwner ());
223207 if (!deallocOp)
0 commit comments