This is an archive of the discontinued LLVM Phabricator instance.

[mlir] Add 'Skip' result to Operation visitor
ClosedPublic

Authored by dcaballe on Mar 2 2021, 5:23 PM.

Details

Summary

This patch is a follow-up on D97217. It adds a new 'Skip' result to the Operation visitor
so that a callback can stop the ongoing visit of an operation/block/region and
continue visiting the next one without fully interrupting the walk. Skipping is
needed to be able to erase an operation/block in pre-order and do not continue
visiting the internals of that operation/block.

Related to the skipping mechanism, the patch also introduces the following changes:

  • Added new TestIRVisitors pass with basic testing for the IR visitors.
  • Fixed missing early increment ranges in visitor implementation.
  • Updated documentation of walk methods to include erasure information and walk order information.

Diff Detail

Event Timeline

dcaballe created this revision.Mar 2 2021, 5:23 PM
dcaballe requested review of this revision.Mar 2 2021, 5:23 PM
sgrechanik added inline comments.Mar 3 2021, 10:31 AM
mlir/include/mlir/IR/Block.h
259

May be reformat this sentence for better clarity? Something like this:

A callback on a block or operation is allowed to erase that block or operation if either:
- the walk is in post-order, or
- the walk is in pre-order and the walk is pruned after the erasure.
mlir/lib/IR/Visitors.cpp
139

It's not obvious to me whether it matters that we return prune() here, and not advance(). I think it shouldn't matter but may be I miss something, so maybe a clarifying comment would help.

Just to clarify, "prune" is ignored for post order walks?

mlir/include/mlir/IR/Visitors.h
31

Why not just Skip? Seems much easier to understand.

mlir/lib/IR/Visitors.cpp
15–20

Remove the newline here.

80

Same here and elsewhere.

mlir/test/lib/IR/TestVisitors.cpp
14

Anonymous namespaces should only contain classes, the functions should be top-level.

dcaballe updated this revision to Diff 328329.Mar 4 2021, 3:54 PM
dcaballe marked 3 inline comments as done.

Addressed feedback.

Just to clarify, "prune" is ignored for post order walks?

Yes, it's ignored in the sense that it just happens that because of the post-order traversal, when we come to invoke the callback for, let's say, an operation, all its nested regions/blocks/operations has been already visited so there wouldn't be anything to prune. Does it make sense?

mlir/include/mlir/IR/Block.h
259

Much better, thanks!

mlir/include/mlir/IR/Visitors.h
31

It makes sense, thanks!

mlir/lib/IR/Visitors.cpp
139

Good point! Yeah, I think it makes more sense to return 'advance()' since the pruning for this op is already happening here and the caller shouldn't have to do anything about it. I'll change that and update the related comments. Thanks!

mlir/test/lib/IR/TestVisitors.cpp
14

Good catch!

dcaballe retitled this revision from [mlir] Add pruning to Operation visitor to [mlir] Add 'Skip' result to Operation visitor.Mar 4 2021, 3:56 PM
dcaballe edited the summary of this revision. (Show Details)
rriddle accepted this revision.Mar 4 2021, 4:39 PM

LGTM

mlir/include/mlir/IR/Operation.h
505

Missed change?

mlir/lib/IR/Visitors.cpp
139

Pulled this comment above the if.

mlir/test/lib/IR/TestVisitors.cpp
123

Weird phrasing here, can you revise?

125

The naming on these functions and several variables should be camelCase

166

Can you move this to the test namespace?

This revision is now accepted and ready to land.Mar 4 2021, 4:39 PM
dcaballe updated this revision to Diff 328339.Mar 4 2021, 5:06 PM
dcaballe marked 5 inline comments as done.

Addressed feedback.

Thanks! I will commit it tomorrow if no more comments.

mlir/test/lib/IR/TestVisitors.cpp
125

Sorry about that.

This revision was landed with ongoing or failed builds.Mar 5 2021, 2:06 PM
This revision was automatically updated to reflect the committed changes.
mlir/include/mlir/IR/Block.h
255

Did you mean "topological" order ?
If it's really lexicographic, can you describe the alphabet?

mlir/include/mlir/IR/Operation.h
505

Locally, skip the walk of this op's region?

508

Globally interrupt the walk ?

mlir/lib/IR/Visitors.cpp
41

@rriddle in general, is there value of not always making region and block range early increment ?

83

@rriddle Is this a distinction we should want to generally worried about?
Wouldn't it be easier to just always early increment and be done with it?

100

is there an invariant we can / should assert ?

mehdi_amini added inline comments.Mar 7 2021, 10:34 AM
mlir/lib/IR/Visitors.cpp
41

If you iterate the operation in a block and you're modifying the current operation, what is visited at the next iteration?

We could make it an implicit early_inc but that would make it different from the convention of every other C++ iterators, which runs the risk of unintended behavior for the user.
(now one may argue that the lack of early increment is non intuitive in most cases and is thus the original issue, but that ship has sailed in C++...)

dcaballe added inline comments.Mar 7 2021, 9:59 PM
mlir/include/mlir/IR/Block.h
255

I'm trying to say "in program order or in order of appearance", which is the order achieved by traversing the lists they are contained in. I've seen "lexicographical order" used for this matter in the past but maybe I'm wrong. I found "topological order" misleading since one might think we are traversing instructions following def-use chains, which would provide one of the many potential topological orders for a set of instructions in a block. Any other suggestion?

mlir/include/mlir/IR/Operation.h
505

Ok, I can add these comments. Thanks!

mlir/lib/IR/Visitors.cpp
83

I didn't do it because I couldn't find a good way to test it. Maybe I'm missing something but I couldn't find public APIs to erase/insert regions from/to ops (probably for good reasons?). Therefore, I leaned towards preserving the existing behavior. No strong opinion, though. I buy the consistency argument. Just let me know and I'll change it.

100

Not that I can think of... What this comment is saying is that if the region was skipped, there's nothing we can skip at this point since the region was already visited (post-order). We could do:

if (result.wasSkipped())
  continue;

But this would be redundant since we are at the end of the loop.