-
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
s390x: Migrate branches and traps to ISLE #3724
Conversation
In order to migrate branches to ISLE, we define a second entry point `lower_branch` which gets the list of branch targets as additional argument. This requires a small change to `lower_common`: the `isle_lower` callback argument is changed from a function pointer to a closure. This allows passing the extra argument via a closure. Traps make use of the recently added facility to emit safepoints from ISLE, but are otherwise straightforward.
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.
Looks great modulo a couple nitpicks below, thanks!
(decl safepoint (SideEffectNoResult) ValueRegs) | ||
(rule (safepoint (SideEffectNoResult.Inst inst)) | ||
(let ((_ Unit (emit_safepoint inst))) | ||
(value_regs_invalid))) |
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 think this should go in the shared prelude, next to value_regs_none
.
#[inline] | ||
fn emit_safepoint(&mut self, inst: &MInst) -> Unit { | ||
self.emitted_insts.push((inst.clone(), true)); | ||
} |
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.
And then I would expect this to go into wasmtime/cranelift/codegen/src/machinst/isle.rs
(decl emit_safepoint (MInst) Unit) | ||
(extern constructor emit_safepoint emit_safepoint) |
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.
And this should be in the prelude as well.
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 see that emit
actually isn't in the prelude, but we do use it from the prelude. So we should probably move emit
to the prelude as well, since in practice it has to be the same declaration across all backends anyways. Happy to have that as part of this updated PR or we can do it in another PR.
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, that's why I didn't put it in the prelude ...
I agree it makes sense to move emit / emit_safepoint there, but then we should also move the implementations to machinst/isle.re, right?
I'd be happy to do that, but I think it would be better to do it in another PR, as it will touch all back-ends.
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, we wouldn't necessarily have to move the implementations as well, nothing is stopping us from implementing the ISLE context's emit
trait method once for each backend even when the decl
is in the prelude.
In fact the x86_64 implementation is a little different, in that it calls a mov_mitosis
method on each inst in emitted_insts
, and if we made this code common then we would need to add such a method to the MachInst
trait or something.
So I think we can move just the ISLE decl
into the prelude without moving the rust trait implementations at all. Happy to have this in a follow up PR.
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, I see. But even if we don't move the implementaton, once the decl
is in the prelude as extern constructor
, every back-end must implement it or it won't compile any more. So we'll still need to touch all back-ends. (In fact, with the x86 mov_mitosis
implementation, I'm not sure exactly how the safepoint variant would work. I guess only the last instruction in the list should be the safepoint?)
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.
once the
decl
is in the prelude asextern constructor
, every back-end must implement it or it won't compile any more.
Correct. (Also, it is already the case that every backend must implement it or the ISLE won't compile because we are calling emit
and assuming it is declared from inside the prelude already, it just so happens that we have N identical declarations for each backend instead of a single shared declaration in the prelude.)
(In fact, with the x86
mov_mitosis
implementation, I'm not sure exactly how the safepoint variant would work. I guess only the last instruction in the list should be the safepoint?)
Yeah, I will have to think a bit about how to do this best. I think making only the last instruction a safepoint would work, but we might want to have some debug asserts in there too. Planning on tackling this after I'm done with my newtype wrappers PR by which time this PR will have merged.
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 think making only the last instruction a safepoint would work,
Yeah, I think that's the correct solution -- the expanded list should always have the form of zero or more moves, followed by the original instruction; and the safepoint bit applies to the latter.
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.
There are some instructions that always generate their results into a particular register, and so when our SSA-ified version of that instruction wants the result in a temp, we have to generate a move that follows the "real" instruction, so we can have trailing moves as well after move mitosis. This shouldn't be the case for safepoints I don't think (except maybe ABI/calling convention stuff where results are always in rax
?) and we should be able to just debug assert this.
Can this be merged now or are you waiting on any action from my side? I have other patches I'd like to submit and this is causing merge conflicts ... As to the question of moving |
I think just the nitpicks that we didn't already discuss and agree could wait for follow ups:
|
But that was just what we discussed: As I understand, x64 will need a different |
Ah right. Then just the |
I'm happy to do that, but I'd really prefer this to be a separate PR. That will still touch all backends and their generated files, and I'd prefer not to entangle this with this back-end change, which is already quite large as-is ... |
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.
Okay, we can do that in follow ups then.
Thanks! The follow up is now here: #3745 |
In order to migrate branches to ISLE, we define a second entry
point
lower_branch
which gets the list of branch targets asadditional argument.
This requires a small change to
lower_common
: theisle_lower
callback argument is changed from a function pointer to a closure.
This allows passing the extra argument via a closure.
Traps make use of the recently added facility to emit safepoints
from ISLE, but are otherwise straightforward.
@cfallin @fitzgen