@@ -150,12 +150,45 @@ void RewriterBase::replaceOp(Operation *op, Operation *newOp) {
150
150
eraseOp (op);
151
151
}
152
152
153
+ // / Returns the given block iterator if it lies within the block `b`.
154
+ // / Otherwise, otherwise finds the ancestor of the given block iterator that
155
+ // / lies within `b`. Returns and "empty" iterator if the latter fails.
156
+ // /
157
+ // / Note: This is a variant of Block::findAncestorOpInBlock that operates on
158
+ // / block iterators instead of ops.
159
+ static std::pair<Block *, Block::iterator>
160
+ findAncestorIteratorInBlock (Block *b, Block *itBlock, Block::iterator it) {
161
+ // Case 1: The iterator lies within the block.
162
+ if (itBlock == b)
163
+ return std::make_pair (itBlock, it);
164
+
165
+ // Otherwise: Find ancestor iterator. Bail if we run out of parent ops.
166
+ Operation *parentOp = itBlock->getParentOp ();
167
+ if (!parentOp)
168
+ return std::make_pair (static_cast <Block *>(nullptr ), Block::iterator ());
169
+ Operation *op = b->findAncestorOpInBlock (*parentOp);
170
+ if (!op)
171
+ return std::make_pair (static_cast <Block *>(nullptr ), Block::iterator ());
172
+ return std::make_pair (op->getBlock (), op->getIterator ());
173
+ }
174
+
153
175
// / This method erases an operation that is known to have no uses. The uses of
154
176
// / the given operation *must* be known to be dead.
155
177
void RewriterBase::eraseOp (Operation *op) {
156
178
assert (op->use_empty () && " expected 'op' to have no uses" );
157
179
auto *rewriteListener = dyn_cast_if_present<Listener>(listener);
158
180
181
+ // If the current insertion point is before/within the erased operation, we
182
+ // need to adjust the insertion point to be after the operation.
183
+ if (getInsertionBlock ()) {
184
+ Block *insertionBlock;
185
+ Block::iterator insertionPoint;
186
+ std::tie (insertionBlock, insertionPoint) = findAncestorIteratorInBlock (
187
+ op->getBlock (), getInsertionBlock (), getInsertionPoint ());
188
+ if (insertionBlock && insertionPoint == op->getIterator ())
189
+ setInsertionPointAfter (op);
190
+ }
191
+
159
192
// Fast path: If no listener is attached, the op can be dropped in one go.
160
193
if (!rewriteListener) {
161
194
op->erase ();
@@ -320,6 +353,11 @@ void RewriterBase::inlineBlockBefore(Block *source, Block *dest,
320
353
moveOpBefore (&source->front (), dest, before);
321
354
}
322
355
356
+ // If the current insertion point is within the source block, adjust the
357
+ // insertion point to the destination block.
358
+ if (getInsertionBlock () == source)
359
+ setInsertionPoint (dest, getInsertionPoint ());
360
+
323
361
// Erase the source block.
324
362
assert (source->empty () && " expected 'source' to be empty" );
325
363
eraseBlock (source);
0 commit comments