Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: preorder walk of blocks in nested operations #3367

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

gabrielrodcanal
Copy link
Contributor

Preorder walk of blocks in nested operations. This corresponds to the behaviour of WalkOrder::Preorder in MLIR. The test in the PR was developed in parallel with an analysis pass in MLIR to ensure equivalent behaviour in xDSL. For reproducibility, the relevant method in MLIR is:

void PreorderBlocks::print(raw_ostream &os) const {
  operation->walk<WalkOrder::PreOrder>([&](Block *block) {
    os << "--- Block: \n";
    block->print(os);
    os << "\n";
  });
}

Copy link

codecov bot commented Oct 31, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.11%. Comparing base (e6c7282) to head (15e5d31).
Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #3367    +/-   ##
========================================
  Coverage   90.10%   90.11%            
========================================
  Files         449      450     +1     
  Lines       56599    56762   +163     
  Branches     5429     5456    +27     
========================================
+ Hits        51001    51150   +149     
- Misses       4164     4170     +6     
- Partials     1434     1442     +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 50 to 54
ctx = MLContext()
ctx.load_dialect(Builtin)
ctx.load_dialect(Arith)
ctx.load_dialect(Func)
ctx.load_dialect(Scf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please change this test to work with only the test dialect, to avoid spurious dependencies?

@@ -967,6 +967,13 @@ def walk(
if region_first:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps rename the post_order.py file to traversals.py and move it there?

@@ -967,6 +967,13 @@ def walk(
if region_first:
yield self

def walk_blocks_preorder(self) -> Iterator[Block]:
for region in self.regions:
for block in region.blocks:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what I would have expected a preorder traversal of blocks to do. Does llvm simply iterate over them in the order they appear?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think about it, it would probably be worth adding a walk method on Block that mirrors the API of the Operation walk, and to change this to forward to that one. I also prefer our walk_regions_first to Preorder as it's more declarative, maybe for blocks it could be walk_child_blocks_first? pre-post order doesn't make sense in the absence of left and right children

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I more meant that I would have expected a "traversal" to explore blocks via a depth first search of successors from each block, rather than just return each block in order

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no that's not what I would expect TBH. @gabrielrodcanal, if you don't feel like implementing reversed iteration and post-order then I think it would still be worth adding walk on Block, and walk_blocks on Operation, and we can add the optional parameters later without API breaking.

@gabrielrodcanal gabrielrodcanal added the core xDSL core (ir, textual format, ...) label Oct 31, 2024
Comment on lines +94 to +95
parser = Parser(ctx, test_prog)
op = parser.parse_op()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry to be annoying, but do you think you could change this from parsing the text to constructing it in Python? Something like this would make the test a little easier to read and understand, IMO. then we could just assert tuple(op.walk_blocks()) == (...)

Comment on lines +1687 to +1692
def walk_child_blocks_first(self) -> Iterator[Block]:
for op in self.ops:
for region in op.regions:
for block in region.blocks:
yield block
yield from block.walk_child_blocks_first()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels natural for it to have this name, WDYT? It would be worth testing also, probably in the same pytest

Suggested change
def walk_child_blocks_first(self) -> Iterator[Block]:
for op in self.ops:
for region in op.regions:
for block in region.blocks:
yield block
yield from block.walk_child_blocks_first()
def walk(self) -> Iterator[Block]:
for op in self.ops:
for region in op.regions:
for block in region.blocks:
yield block
yield from block.walk()

@superlopuh
Copy link
Member

Any updates on this? Will you have some time to iterate on it this week?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core xDSL core (ir, textual format, ...)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants