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 NoTerminator trait #1049

Merged
merged 81 commits into from
Jun 21, 2023
Merged

Core: Add NoTerminator trait #1049

merged 81 commits into from
Jun 21, 2023

Conversation

compor
Copy link
Collaborator

@compor compor commented Jun 1, 2023

This PR adds the NoTerminator trait.

A current issue is that the IRDL annotations (e.g., SingleBlockRegion, etc) operate separately from this trait.
I'm not sure if the link between the two should be checked before an operation's verify method, i.e. during construction, or type-checked in this trait's verify method.

Any feedback on this is welcome.

@compor compor added the core xDSL core (ir, textual format, ...) label Jun 1, 2023
@compor compor self-assigned this Jun 1, 2023
@codecov
Copy link

codecov bot commented Jun 1, 2023

Codecov Report

Patch coverage: 99.09% and project coverage change: +0.02 🎉

Comparison is base (f86a6ea) 88.66% compared to head (22879d7) 88.68%.

❗ Current head 22879d7 differs from pull request most recent head 48ef91a. Consider uploading reports for the commit 48ef91a to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1049      +/-   ##
==========================================
+ Coverage   88.66%   88.68%   +0.02%     
==========================================
  Files         160      160              
  Lines       22300    22332      +32     
  Branches     3345     3356      +11     
==========================================
+ Hits        19773    19806      +33     
+ Misses       1989     1988       -1     
  Partials      538      538              
Impacted Files Coverage Δ
docs/Toy/toy/dialects/toy.py 68.12% <ø> (ø)
tests/dialects/test_affine.py 100.00% <ø> (ø)
xdsl/ir/core.py 88.37% <92.30%> (+<0.01%) ⬆️
tests/dialects/test_func.py 100.00% <100.00%> (ø)
tests/dialects/test_scf.py 100.00% <100.00%> (ø)
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/builtin.py 83.84% <100.00%> (ø)
xdsl/dialects/gpu.py 98.76% <100.00%> (ø)
... and 5 more

... and 1 file with indirect coverage changes

☔ 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.

I need to check in the MLIR codebase, but what we should have is somewhere a check that all blocks have terminator. I need to look where this check is done though!

tests/test_builtin_traits.py Outdated Show resolved Hide resolved
xdsl/traits.py Outdated

def verify(self, op: Operation) -> None:
for r in op.regions:
if len(r.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.

It is actually a bit more complex than that. Here is the "documentation" I could find in MLIR:
image

In our case, we don't actually need to verify anything in the trait. What we need is somewhere a check that blocks have terminator if the conditions are respected. I'm just not sure where to put it yet, I'll take a look now.

Copy link
Collaborator Author

@compor compor Jun 1, 2023

Choose a reason for hiding this comment

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

yeah, I found that as well yesterday, good to see, but when I tried to check for the NoTerminator trait in ir.py (simulating this), I got a circular dependency in my imports, so that kinda put me off from going that route.

Moreover, I couldn't find any validation for terminators in xDSL. (see comment below)

@math-fehr
Copy link
Collaborator

Looking at the MLIR codebase, the check that blocks have terminators should be done in the verify function in Operation between these two code blocks:
image

@compor
Copy link
Collaborator Author

compor commented Jun 1, 2023

Looking at the MLIR codebase, the check that blocks have terminators should be done in the verify function in Operation between these two code blocks: image

I see, and just to be clear about my understanding, terminators are operations with a non-empty successor list in xDSL, correct?

@superlopuh
Copy link
Member

If I understand correctly, while this trait would be useful for xDSL in general, we'd still want terminators in pretty much all RISC-V blocks, right? @math-fehr

@superlopuh
Copy link
Member

At least the ones that represent code as opposed to data sections

@compor
Copy link
Collaborator Author

compor commented Jun 1, 2023

At least the ones that represent code as opposed to data sections

That is my understanding by looking at the MLIR verifier.
Once this is in, we could annotate RISCV blocks without jump operations with this trait by default.
Not sure how prudent that is.

Otherwise, maybe we could have a TerminatorOp that doesn't emit assembly.

@superlopuh
Copy link
Member

I think that's standard, something like a yield op that just carries on to its successor

@math-fehr
Copy link
Collaborator

Terminator is probably the trait you want to implement first actually!
It should be a trait on operations. And operations should not have any successors unless they have the Terminator trait (this is something that I can add myself on IRDL later on).
Any region that has multiple blocks should have terminators on these blocks, so not sure what you have in your Riscv blocks.

I guess the steps would be:

  • Adding the Terminator trait, and the check in Operation.verify that blocks have terminators, besides the single block ones (so it is easier to write the next patch)
  • Add the NoTerminator trait, and ensure all single block regions have terminators unless they have this trait.

@compor
Copy link
Collaborator Author

compor commented Jun 2, 2023

Terminator is probably the trait you want to implement first actually! It should be a trait on operations. And operations should not have any successors unless they have the Terminator trait (this is something that I can add myself on IRDL later on). Any region that has multiple blocks should have terminators on these blocks, so not sure what you have in your Riscv blocks.

I guess the steps would be:

* Adding the `Terminator` trait, and the check in `Operation.verify` that blocks have terminators, besides the single block ones (so it is easier to write the next patch)

* Add the `NoTerminator` trait, and ensure all single block regions have terminators unless they have this trait.

Yeah, I was going to open a PR later for this, but I guess it makes sense to add it first.

Regarding, the MLIR implementation of this and mayBeValidWithoutTerminator utility method, it seems it applies the aforementioned "rules" twice, once for empty blocks and non-empty ones, but only after the successors go through sanity checks and that is within verifyBlock, and that seems to work for us as well.
I'm just saying this because implementing it within operation felt a bit awkward, but I can come back to it.

@superlopuh
Copy link
Member

Seems like riscv.ret would benefit from the Terminator trait, and then we could add a yield operation for other control flow like things

@compor
Copy link
Collaborator Author

compor commented Jun 2, 2023

Seems like riscv.ret would benefit from the Terminator trait, and then we could add a yield operation for other control flow like things

yeah exactly and combine that with NoTerminator in other cases (considering the initial discussion that sparked this)

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@compor compor changed the title [WIP] Core: Add NoTerminator trait Core: Add NoTerminator trait Jun 20, 2023
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.

A big PR, but I don't think we can reduce it much further!

@@ -6,12 +6,14 @@
%y = "op_with_res"() {otherattr = #unknown_attr<b2 ...2 [] <<>>>} : () -> (i32)
%z = "op_with_operands"(%y, %y) : (i32, i32) -> !unknown_type<{[<()>]}>
"op"() {ab = !unknown_singleton_type} : () -> ()
"test.termop"() : () -> ()
Copy link
Collaborator

Choose a reason for hiding this comment

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

That looks suspicious to me.
If an operation is not registered, we cannot require a terminator, as we don't know if the operation has a NoTerminator trait or not.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, let's do that in another PR, I need to add HasMaybeTrait that does exactly that.

Copy link
Collaborator Author

@compor compor Jun 20, 2023

Choose a reason for hiding this comment

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

hmm, that goes back to a question I had regarding unregistered ops in xDSL.
I can have a look at that, basically, it will be modelled after hasTrait but take into account if an op is not registered, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I opened an issue to track this #1167

xdsl/dialects/stencil.py Outdated Show resolved Hide resolved
xdsl/ir/core.py Outdated Show resolved Hide resolved
xdsl/ir/core.py Outdated Show resolved Hide resolved
)
if parent_block.last_op == self:
if len(parent_region.blocks) == 1:
if (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there a case missing where we have NoTerminator but have been given a terminator?
Or is this handle somewhere else?

Copy link
Collaborator Author

@compor compor Jun 20, 2023

Choose a reason for hiding this comment

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

do you mean the check in Block.verify()?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this checks it as well.
If we have

builtin.module {
  test.term_op
}

this should fail because the last operation of a NoTerminator operation is a terminator.
But I don't see any check for that here or in Block.verify()?

Copy link
Collaborator Author

@compor compor Jun 20, 2023

Choose a reason for hiding this comment

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

Hmm, forget my Block.verify comment, I misunderstood there.
The way I read it was that if the NoTerminator trait is applied, no need to do any further checking.
If it doesn't exist, then the IsTerminator is required on the last operation.

Basically, the last few lines here.

Copy link
Collaborator Author

@compor compor Jun 21, 2023

Choose a reason for hiding this comment

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

I've added a test case regarding this @math-fehr

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.

LGTM, thanks for the PR :)

@compor compor requested a review from math-fehr June 21, 2023 08:14
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.

👍

@compor compor merged commit d8e60cd into main Jun 21, 2023
@compor compor deleted the christos/core/no-term-trait branch June 21, 2023 13:35
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.

4 participants