-
Notifications
You must be signed in to change notification settings - Fork 77
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
dialects: (x86) PR5_1 - single operand instructions - one source #2398
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2398 +/- ##
==========================================
+ Coverage 89.64% 89.72% +0.08%
==========================================
Files 346 350 +4
Lines 41175 42567 +1392
Branches 6120 6331 +211
==========================================
+ Hits 36911 38194 +1283
- Misses 3366 3437 +71
- Partials 898 936 +38 ☔ View full report in Codecov by Sentry. |
tests/dialects/test_x86.py
Outdated
@@ -27,3 +29,59 @@ | |||
def test_register(register: x86.register.GeneralRegisterType, name: str): | |||
assert register.is_allocated | |||
assert register.register_name == name | |||
|
|||
|
|||
def test_push_op(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend sticking to filecheck tests for everything that can be checked with filecheck, which I think is the case for these. For verification errors search for --verify-diagnostics
in the project to find some examples. Having the expected error string is quite useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I was not aware of the verify-diagnostics, I’ll change that 👍
xdsl/dialects/x86/ops.py
Outdated
source = opt_operand_def(R1InvT) | ||
destination = opt_result_def(R1InvT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why optional? I'd expect these to be required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s to support different types of operations eg. pop has only a destination while push has only a source.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sounds like they should be different operations, one with only a source, and one with only a destination. Otherwise a user may construct a pop with only a source.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made the verification methods to avoid that, but can split them into two methods as well if that’s better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes please, verification is good, but declarative structures are better, that way we get more warnings statically rather than at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What to do if the operand is both a source and a destination like in the 'not' instruction? a seperate class for this case as well?
Sorry for no progress by the way, i'll get on it after I'm done with the dissertation writing,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I'd say we want an instruction that has a source and target register, and constrains the type of the operand and result to be exactly the same, with a ConstraintVar, something like this:
T = Annotated[RegisterType, ConstraintVar("T")]
operand: Operand = operand_def(T)
result: OpResult = result_def(T)
I feel like for things like |
I disagree, I think that testing for string equality is better in general, and in this case, as we add the whitespace to make the assembly more uniform/readable, and would like to at least be notified when the format changes. |
xdsl/dialects/x86/ops.py
Outdated
|
||
|
||
@irdl_op_definition | ||
class IdivOp(ROperation[GeneralRegisterType]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, in a perfect world, I would love it if you could encode the fact that rax and rdx are the needed registers in a declarative way. I imagine something like:
class IdivOp:
divisend = operand_def(x86RegisterType("rdx"))
divisor = operand_def(x86RegisterType("rax"))
quotient = ...
remainder = ...
I am honestly not sure if this will be possible in the current xDSL infrastructure and with the way you have set up the x86Registertype. But it would still be cool to do somehow 😅
IMO, it might make sense to remove Idiv from this PR and submit one for this specifically, then we could have this discussion there and not stall this one :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah TBH we could probably open separate PRs for a few of these ops to be able to discuss these things separately. I understand that this was the original intent of this PR, but it feels like "single operand instruction" is not quite the abstraction we're looking for
As per the suggestion I decided to split up the PR into one for each - 1 source, 1 destination and 1 source/destination case. This is going to be for 1 source. I will set up the other PRs shortly. |
Added support for single operand instructions and the following specific cases: idiv, pop, push and not. I added some tests for the verification of the single operand instructions given that the one operand can be a destination, a source or both.
idiv is a bit of a special case since it technically has 2 destination registers: RAX for quotient and RDX for remained, but they're not specified by the programmer but rather built-in. I'd be happy to discuss what the best approach to this is and if it should create SSA values.