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: Add IsTerminator trait #1080

Merged
merged 30 commits into from Jun 9, 2023
Merged

Core: Add IsTerminator trait #1080

merged 30 commits into from Jun 9, 2023

Conversation

compor
Copy link
Collaborator

@compor compor commented Jun 5, 2023

This PR adds the IsTerminator trait.

It is a spinoff of the discussion here and specifically this recommendation regarding the initial (and pending) attempt to add the NoTerminator trait.

@compor compor added the core xDSL core (ir, textual format, ...) label Jun 5, 2023
@compor compor self-assigned this Jun 5, 2023
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@math-fehr math-fehr left a comment

Choose a reason for hiding this comment

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

Nice! Happy to see that coming!

xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/ir.py Outdated Show resolved Hide resolved
xdsl/traits.py Show resolved Hide resolved
xdsl/ir.py Outdated
"Operation with block successors must terminate its parent block"
)

if not self.has_trait(IsTerminator):
Copy link
Collaborator

Choose a reason for hiding this comment

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

This (len(self.successors) > 0 -> has_trait(IsTerminator)) should be checked even if the operation has no parents right?
Should we move this higher up?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hmm, is there a point in checking for the terminator conditions if the operation is not part of some control flow (i.e., in a block and region?

I moved the condition up and then got verification errors from things like this.
I can fix those tests, but I'm unsure what we want here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@math-fehr I ended up moving the condition for has_trait(IsTerminator) one indentation level since indeed there was an implicit assumption that a terminator must have successors, which is indeed not the case.

But my point regarding control flow (i.e., not belonging to a block/region) still stands; or am I missing something?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm that's a good question. It turns out that you cannot jump to the entry block, so technically it is not allowed.
We don't raise an error yet, the question is where should we raise an error.
I believe we should raise it here, as it reduce the amount of corner cases we have (otherwise, we rely on another verification pass to handle that case, and I feel this is very error-prone if that makes sense).
What do you think?

Copy link
Collaborator Author

@compor compor Jun 9, 2023

Choose a reason for hiding this comment

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

I think it's a good point to "piggyback" this check here.

Hence, I'll just check separately that if an operation has successors and doesn't belong to a parent block or region, then it should fail verification.
This is regardless of the IsTerminator trait.

After this, we can continue with the current verification logic and enhance/supplement it with the follow-up NoTerminator trait patch.

tests/test_builtin_traits.py Show resolved Hide resolved
tests/test_ir.py Outdated Show resolved Hide resolved
tests/test_ir.py Show resolved Hide resolved
) is not None:
# TODO single-block regions dealt when the NoTerminator trait is
# implemented (https://github.com/xdslproject/xdsl/issues/1093)
if len(parent_region.blocks) > 1:
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the case where there is a single block, we still need to check that an operation that is not the last does not have a successor (with or without NoTerminator), right?
Or is it different since you technically are not allowed to jump to the entry block?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That is right but I was thinking it might be simpler to check for both cases when the NoTerminator trait is implemented. I guess the branching off for a non-last op is irrelevant to that, so we can just test it now.

Am I understanding correctly?

Copy link
Collaborator Author

@compor compor Jun 9, 2023

Choose a reason for hiding this comment

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

I changed my mind on this, it's simpler and more clear to check that an operation should not have successors unless it is the last operation in its parent block (regardless of the number of blocks in the parent region or the existence of the NoTerminator trait.

The PR is now updated to reflect this.

Copy link
Collaborator

@math-fehr math-fehr left a comment

Choose a reason for hiding this comment

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

Nice! Thanks a lot

@compor
Copy link
Collaborator Author

compor commented Jun 8, 2023

Nice! Thanks a lot

No problem, thanks for the input; I'll address your remaining feedback and ping you again.
Also fighting a failing filecheck, so it might take a while.

@compor
Copy link
Collaborator Author

compor commented Jun 9, 2023

Regarding the failing filecheck tests/filecheck/parser-printer/graph_region.mlir I think the problem is that TestOp does not have the IsTerminator trait now and although the test checks operand dependency cycles and other value reference tests it fails.

My idea here was to add a TestTermOp in the test dialect with implements also the IsTerminator trait.
What do you think?

@compor compor requested review from math-fehr and webmiche June 9, 2023 07:25
@superlopuh
Copy link
Member

Seems that graph regions broke in the tests

@compor
Copy link
Collaborator Author

compor commented Jun 9, 2023

Seems that graph regions broke in the tests

I commented on this above, although now I think this is not what we might want.

It seems the graph regions are limited to a single basic block, so this might be a clue towards a solution.
Currently, looking at mlir-opt source ans tests on this.

@math-fehr
Copy link
Collaborator

Oh, I see what happened!
I think you are right, we should have a test.termop for this test.
Concerning graph regions, yes they are only for single-block regions, but here the test was testing that we don't have to order basic blocks.

@compor
Copy link
Collaborator Author

compor commented Jun 9, 2023

@math-fehr I think I have addressed all comments now.

@codecov
Copy link

codecov bot commented Jun 9, 2023

Codecov Report

Patch coverage: 98.31% and project coverage change: +0.05 🎉

Comparison is base (8dcfb40) 86.95% compared to head (8066cbc) 87.00%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1080      +/-   ##
==========================================
+ Coverage   86.95%   87.00%   +0.05%     
==========================================
  Files         137      137              
  Lines       20676    20774      +98     
  Branches     3128     3143      +15     
==========================================
+ Hits        17979    18075      +96     
- Misses       2179     2180       +1     
- Partials      518      519       +1     
Impacted Files Coverage Δ
xdsl/traits.py 93.93% <86.66%> (-6.07%) ⬇️
tests/test_builtin_traits.py 100.00% <100.00%> (ø)
tests/test_ir.py 100.00% <100.00%> (ø)
tests/test_operation_builder.py 100.00% <100.00%> (ø)
xdsl/dialects/cf.py 100.00% <100.00%> (ø)
xdsl/dialects/func.py 94.61% <100.00%> (ø)
xdsl/dialects/scf.py 89.65% <100.00%> (+0.12%) ⬆️
xdsl/dialects/test.py 100.00% <100.00%> (ø)
xdsl/ir/core.py 87.17% <100.00%> (+0.04%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@math-fehr math-fehr left a comment

Choose a reason for hiding this comment

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

Nice! Thanks a lot, that looks good to me!

@math-fehr
Copy link
Collaborator

@webmiche @superlopuh, is that good for you as well?

Copy link
Collaborator

@webmiche webmiche left a comment

Choose a reason for hiding this comment

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

One thing that I don't like, though that is probably an MLIR design issue, is that the IsTerminator trait is very closely coupled into the core datastructures now. So no block can be without a terminator essentially. This makes the dependencies within the code very hard to follow and couples different parts very closely together. To me, that is particularly apparent by the fact that you added two kinds of tests in this PR.

That's all to say, nice to have this in, I think we really need this and I think we can merge. But I will reserve the right to change this coupling at some point, if we manage to design this cleaner than MLIR does.

@compor
Copy link
Collaborator Author

compor commented Jun 9, 2023

One thing that I don't like, though that is probably an MLIR design issue, is that the IsTerminator trait is very closely coupled into the core datastructures now. So no block can be without a terminator essentially. This makes the dependencies within the code very hard to follow and couples different parts very closely together. To me, that is particularly apparent by the fact that you added two kinds of tests in this PR.

That's all to say, nice to have this in, I think we really need this and I think we can merge. But I will reserve the right to change this coupling at some point, if we manage to design this cleaner than MLIR does.

I mostly agree with this.
I think combining traits with interfaces is already an improvement in the Python world.

When I started this, I wanted to implement everything in the trait's verify method; I feel this can take place with some redesign and maybe(?) additional traits.
It just feels that the overlap of cases hasn't been well thought through in the trait system.

Regardless of these deficiencies, I like the additional verification they provide.

@compor compor merged commit 1df2278 into main Jun 9, 2023
12 checks passed
@compor compor deleted the christos/core/term-trait branch June 9, 2023 18:19
cigarichard pushed a commit to cigarichard/xdsl that referenced this pull request Jun 17, 2023
This PR implements the [`IsTerminator`][3] trait.

It is a spinoff of the discussion [here][1] and specifically [this][2]
recommendation regarding the initial (and pending) attempt to add the
`NoTerminator` trait.

[1]: xdslproject#1049
[2]: xdslproject#1049 (comment)
[3]: https://mlir.llvm.org/docs/Traits/#terminator
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.

None yet

4 participants