-
Notifications
You must be signed in to change notification settings - Fork 46
Support using pinned registers as blockparams #75
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
Conversation
Pinned registers usually have special semantics and can't be merged with normal vregs. Similar checks already exist when merging `Reuse` operands and moves.
While pinned vregs are always assigned to the same preg and don't require moves across blocks, this doesn't apply to blockparams since the value is transferred to a different vreg.
|
Hi @Amanieu -- unfortunately I don't think this aligns with our eventual goal of getting rid of pinned vregs. We have #3 open for this, and at least in Cranelift I've been largely able to use fixed-reg constraints for everything. The main reason for that goal is to remove significant complexity. The subtle nature of this patch is good evidence of that, I think: it looks ok-ish to me, but the only way I'd really be sure is letting the fuzzer churn on it for a while. And the fuzzer doesn't cover pinned vregs directly. (They're tested somewhat by virtue of Cranelift's fuzzing, but we're moving away from them.) Edge-case complexity also makes it a lot harder to implement other optimizations or improvements. As a specific example, if we get completely to an SSA-only input world (and removing pinned vregs is a prerequisite for this), we can simplify a lot of the constraint fudging and fixing up that makes safepoints, half-instruction-wide constraints, multi-fixed-use cases, and the like work, by allowing for multiple copies of a value to exist. This also allows us to remove the redundant-move eliminator entirely. But we can only get there if we simplify the input that the regalloc core accepts. In your specific cases, I think the core primitive that you might want as an alternative is the ability to not pass an operand for a register, if it's an "undef" or "zero" case. Basically one can build paired behavior in the extract-operands logic and the apply-allocations-to-instruction logic where (i) an operand is emitted only if normal vreg; and (ii) an allocation is consumed only if the operand would have been emitted, otherwise the special reg is passed through. Does that seem reasonable? |
|
I had a look at Cranelift and the closest equivalent to what I am trying to do is the Now imagine that instead of having to emit this move instruction, Perhaps pinned registers are not the right mechanism to support this, but anything I can think of ends up being very similar. In an SSA world these pinned vregs are effectively constants since they are only every used in 2 ways:
|
Right, so in this case I think the mechanism I suggested above should be possible: the operand-producing glue code on the embedder side does not emit any operand at all ("effectively constant" as you say) and the allocation-consuming glue code knows that it should not expect an allocation in return. |
|
The problem is that the allocation-consuming glue doesn't know that it should not expect an allocation, at least not without some out-of-band data. The consumer is usually something like a generic However since #18 blockparams don't use In conclusion, I think that everything I want can be achieve by just re-introducing |
|
That seems reasonable to me as well actually; (If I can make a note of a semantically-important bikeshed color request for that reintroduction, I think we want to encode it by defining a sentinel value for the |
|
Superseded by #77. |
I use pinned registers to represent 2 things:
x0on RISC-V,xzron AArch64) which is hard-wired to zero.const_to_vregfunction to just return the pinned zero register instead of setting a register to 0.undefvalue which indicates that a value is never used.Option<i32>which consist of a tag vreg and a value vreg. If the tag indicatesNonethen the value is set toundef.undefinput or output are eliminated.These pinned registers are only ever used as instruction inputs (
use) and blockparam outputs (jump arguments).Making this work properly requires 2 changes: