-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
x86_32: legalize {istore,sload,uload}32.i64 #1789
x86_32: legalize {istore,sload,uload}32.i64 #1789
Conversation
Subscribe to Label Actioncc @bnjbvr
This issue or pull request has been labeled: "cranelift", "cranelift:meta"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
1d984ba
to
a96dc5f
Compare
Hm, I think I still don't fully understand the machinery here, especially around |
cranelift/filetests/filetests/isa/x86/legalize-x86_32-loadstore32-i64.clif
Outdated
Show resolved
Hide resolved
a96dc5f
to
5b44d6d
Compare
I think I'm ok merging this if we add some comments like those in #1747 (comment) about what the controlling type variable is. This isn't really a problem with the PR as much as it is with the types of the instruction definitions being unclear but at least with comments we'll be able to troubleshoot these legalizations more easily. Also, I would have expected to see these legalizations in |
So the problem is that unlike my earlier PRs I actually still don't really understand why it works, and why some of the earlier (incorrect) iterations worked and some of them were broken. |
Hm, yeah... Cranelift's legalizations are a bit tricky. Just to confirm the intent of all of this, you want to be able to run |
Yes. Moreover, I have the exact same problem with the |
def!((al, ah) = isplit(a)), | ||
def!(store.I32(flags, al, ptr, offset)), | ||
], | ||
); |
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.
In this legalization we are trying to store the lower 32 bits of an I64
(the controlling type is for the value to store). It makes sense to me that this would be in narrow
.
def!(b = load.I32(flags, ptr, offset)), | ||
def!(a = sextend.I64(b)), | ||
], | ||
); |
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.
This seems to use an I32
pointer (the controlling type) to load the low 32 bits of a register and then sign-extend to 64 bits (from the instruction definition). In 32-bit x86, what is this operation supposed to be doing? If there are no 64-bit registers available for this sign-extension, is sextend.I64
going to legalize further to something else? And is that actually what you want? E.g. if bit 31 is 0, should another register be zeroed out; or if bit 31 is 1, should another register be set to all 1s?
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.
is
sextend.I64
going to legalize further to something else?
Yes. In cases that I see (and I get no new legalizer failures with the *32
instructions) sextend.I64
is then processed by isplit
, and the top half is usually just thrown away. I have no special insight for why Cranelift emits sload32
instructions though.
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.
sload32
instuctions are emitted for a certain WASM instruction.
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.
Ok, yeah I see it in code_translator.rs
. I think a summary of our back and forth here would be helpful as a comment on these legalizations. The only other remaining issue is: why can't this be in the widen
group? @bjorn3, is that clear to you?
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.
The ctrl typevar is I32
, which matches the native pointer size on x86_32, so it requires the expand
group. widen
is only for ctrl typevars that are smaller than the native pointer size.
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.
Ah, good. Yeah, let's add that nice detail to the comment as well.
def!(a = uextend.I64(b)), | ||
], | ||
); | ||
|
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.
This uses an I32
pointer (the controlling type) to load the low 32 bits of a register and then just extend (unsigned) to 64 bits. In 32-bit x86, I would think that uextend.I64
should just zero out another register?
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.
You're correct that this could be replaced with just iconst
, I kept it symmetric but there's no reason other than that.
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 believe that is exactly how uextend.i64
is legalized on i686.
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.
👍
My comments are aimed at clarifying what we want these legalizations to do (so feel free to correct me above if I'm not getting the intent right). But it occurs to me that this may be quicker in IM. I'm usually in https://bytecodealliance.zulipchat.com/#narrow/stream/217117-cranelift and can discuss more tomorrow. |
Fixes bytecodealliance#1747. Co-authored-by: bjorn3
5b44d6d
to
ecc4fdc
Compare
I think I'm going to close this because I see that the migration to the new backend is underway, and it feels like I'm not going to be able to get x86_32 support to a usable state before it gets removed. |
@whitequark this might make sense, but just to make sure we didn't accidentally create wrong impressions: the old backend framework won't be removed until sometime next year. We'll have switched the default for the x64 codegen to the new framework well before, after which very little will happen around the old one, but it'll stay in-tree for quite a while longer. |
I understand that, but I expect that, once the old backend is no longer heavily tested by the majority of the users, it's going to slowly bit-rot. Since the x86_32 code paths are marginal in first place, it would mean that I'd have to run twice as fast just to remain in the same place, and I don't expect to be able to do that. |
Oh and to add to this: I would be generally happy to work on x32 support in the new backend, but given that it's currently written to support x64 alone, it requires an amount of work I can't justify (and experience with x86 that I do not have). If someone else generalizes the x64 backend to support 32 bits too, like the old one, I'd help bring it to completion. |
I thought that might be the reason, and makes sense to me, yes.
Much appreciated! I filed #1980 to look into what support for x86 in the new framework could look like. |
Thank you! Looking forward to it. |
Fixes #1747.