@@ -260,68 +260,91 @@ class Block : public IRObjectWithUseList<BlockOperand>,
260
260
SuccessorRange getSuccessors () { return SuccessorRange (this ); }
261
261
262
262
// ===--------------------------------------------------------------------===//
263
- // Operation Walkers
263
+ // Walkers
264
264
// ===--------------------------------------------------------------------===//
265
265
266
- // / Walk the operations in this block. The callback method is called for each
267
- // / nested region, block or operation, depending on the callback provided.
268
- // / The order in which regions, blocks and operations at the same nesting
266
+ // / Walk all nested operations, blocks (including this block) or regions,
267
+ // / depending on the type of callback.
268
+ // /
269
+ // / The order in which operations, blocks or regions at the same nesting
269
270
// / level are visited (e.g., lexicographical or reverse lexicographical order)
270
- // / is determined by 'Iterator'. The walk order for enclosing regions, blocks
271
- // / and operations with respect to their nested ones is specified by 'Order'
272
- // / (post-order by default). A callback on a block or operation is allowed to
273
- // / erase that block or operation if either:
271
+ // / is determined by `Iterator`. The walk order for enclosing operations,
272
+ // / blocks or regions with respect to their nested ones is specified by
273
+ // / `Order` (post-order by default).
274
+ // /
275
+ // / A callback on a operation or block is allowed to erase that operation or
276
+ // / block if either:
274
277
// / * the walk is in post-order, or
275
278
// / * the walk is in pre-order and the walk is skipped after the erasure.
279
+ // /
276
280
// / See Operation::walk for more details.
277
281
template <WalkOrder Order = WalkOrder::PostOrder,
278
282
typename Iterator = ForwardIterator, typename FnT,
283
+ typename ArgT = detail::first_argument<FnT>,
279
284
typename RetT = detail::walkResultType<FnT>>
280
285
RetT walk (FnT &&callback) {
281
- return walk<Order, Iterator>(begin (), end (), std::forward<FnT>(callback));
282
- }
283
-
284
- // / Walk the operations in the specified [begin, end) range of this block. The
285
- // / callback method is called for each nested region, block or operation,
286
- // / depending on the callback provided. The order in which regions, blocks and
287
- // / operations at the same nesting level are visited (e.g., lexicographical or
288
- // / reverse lexicographical order) is determined by 'Iterator'. The walk order
289
- // / for enclosing regions, blocks and operations with respect to their nested
290
- // / ones is specified by 'Order' (post-order by default). This method is
291
- // / invoked for void-returning callbacks. A callback on a block or operation
292
- // / is allowed to erase that block or operation only if the walk is in
293
- // / post-order. See non-void method for pre-order erasure.
294
- // / See Operation::walk for more details.
295
- template <WalkOrder Order = WalkOrder::PostOrder,
296
- typename Iterator = ForwardIterator, typename FnT,
297
- typename RetT = detail::walkResultType<FnT>>
298
- std::enable_if_t <std::is_same<RetT, void >::value, RetT>
299
- walk (Block::iterator begin, Block::iterator end, FnT &&callback) {
300
- for (auto &op : llvm::make_early_inc_range (llvm::make_range (begin, end)))
301
- detail::walk<Order, Iterator>(&op, callback);
286
+ if constexpr (std::is_same<ArgT, Block *>::value &&
287
+ Order == WalkOrder::PreOrder) {
288
+ // Pre-order walk on blocks: invoke the callback on this block.
289
+ if constexpr (std::is_same<RetT, void >::value) {
290
+ callback (this );
291
+ } else {
292
+ RetT result = callback (this );
293
+ if (result.wasSkipped ())
294
+ return WalkResult::advance ();
295
+ if (result.wasInterrupted ())
296
+ return WalkResult::interrupt ();
297
+ }
298
+ }
299
+
300
+ // Walk nested operations, blocks or regions.
301
+ if constexpr (std::is_same<RetT, void >::value) {
302
+ walk<Order, Iterator>(begin (), end (), std::forward<FnT>(callback));
303
+ } else {
304
+ if (walk<Order, Iterator>(begin (), end (), std::forward<FnT>(callback))
305
+ .wasInterrupted ())
306
+ return WalkResult::interrupt ();
307
+ }
308
+
309
+ if constexpr (std::is_same<ArgT, Block *>::value &&
310
+ Order == WalkOrder::PostOrder) {
311
+ // Post-order walk on blocks: invoke the callback on this block.
312
+ return callback (this );
313
+ }
314
+ if constexpr (!std::is_same<RetT, void >::value)
315
+ return WalkResult::advance ();
302
316
}
303
317
304
- // / Walk the operations in the specified [begin, end) range of this block. The
305
- // / callback method is called for each nested region, block or operation,
306
- // / depending on the callback provided. The order in which regions, blocks and
307
- // / operations at the same nesting level are visited (e.g., lexicographical or
308
- // / reverse lexicographical order) is determined by 'Iterator'. The walk order
309
- // / for enclosing regions, blocks and operations with respect to their nested
310
- // / ones is specified by 'Order' (post-order by default). This method is
311
- // / invoked for skippable or interruptible callbacks. A callback on a block or
312
- // / operation is allowed to erase that block or operation if either:
318
+ // / Walk all nested operations, blocks (excluding this block) or regions,
319
+ // / depending on the type of callback, in the specified [begin, end) range of
320
+ // / this block.
321
+ // /
322
+ // / The order in which operations, blocks or regions at the same nesting
323
+ // / level are visited (e.g., lexicographical or reverse lexicographical order)
324
+ // / is determined by `Iterator`. The walk order for enclosing operations,
325
+ // / blocks or regions with respect to their nested ones is specified by
326
+ // / `Order` (post-order by default).
327
+ // /
328
+ // / A callback on a operation or block is allowed to erase that operation or
329
+ // / block if either:
313
330
// / * the walk is in post-order, or
314
331
// / * the walk is in pre-order and the walk is skipped after the erasure.
332
+ // /
315
333
// / See Operation::walk for more details.
316
334
template <WalkOrder Order = WalkOrder::PostOrder,
317
335
typename Iterator = ForwardIterator, typename FnT,
318
336
typename RetT = detail::walkResultType<FnT>>
319
- std::enable_if_t <std::is_same<RetT, WalkResult>::value, RetT>
320
- walk (Block::iterator begin, Block::iterator end, FnT &&callback) {
321
- for (auto &op : llvm::make_early_inc_range (llvm::make_range (begin, end)))
322
- if (detail::walk<Order, Iterator>(&op, callback).wasInterrupted ())
323
- return WalkResult::interrupt ();
324
- return WalkResult::advance ();
337
+ RetT walk (Block::iterator begin, Block::iterator end, FnT &&callback) {
338
+ for (auto &op : llvm::make_early_inc_range (llvm::make_range (begin, end))) {
339
+ if constexpr (std::is_same<RetT, WalkResult>::value) {
340
+ if (detail::walk<Order, Iterator>(&op, callback).wasInterrupted ())
341
+ return WalkResult::interrupt ();
342
+ } else {
343
+ detail::walk<Order, Iterator>(&op, callback);
344
+ }
345
+ }
346
+ if constexpr (std::is_same<RetT, WalkResult>::value)
347
+ return WalkResult::advance ();
325
348
}
326
349
327
350
// ===--------------------------------------------------------------------===//
0 commit comments