ABI: implement register arguments with constraints. (#4858)

* ABI: implement register arguments with constraints.

Currently, Cranelift's ABI code emits a sequence of moves from physical
registers into vregs at the top of the function body, one for every
register-carried argument.

For a number of reasons, we want to move to operand constraints instead,
and remove the use of explicitly-named "pinned vregs"; this allows for
better regalloc in theory, as it removes the need to "reverse-engineer"
the sequence of moves.

This PR alters the ABI code so that it generates a single "args"
pseudo-instruction as the first instruction in the function body. This
pseudo-inst defs all register arguments, and constrains them to the
appropriate registers at the def-point. Subsequently the regalloc can
move them wherever it needs to.

Some care was taken not to have this pseudo-inst show up in
post-regalloc disassemblies, but the change did cause a general regalloc
"shift" in many tests, so the precise-output updates are a bit noisy.
Sorry about that!

A subsequent PR will handle the other half of the ABI code, namely, the
callsite case, with a similar preg-to-constraint conversion.

* Update based on review feedback.

* Review feedback.
This commit is contained in:
Chris Fallin
2022-09-08 20:03:14 -05:00
committed by GitHub
parent 13c7846815
commit 2986f6b0ff
101 changed files with 2688 additions and 2441 deletions

View File

@@ -101,6 +101,7 @@ impl Inst {
| Inst::Pop64 { .. }
| Inst::Push64 { .. }
| Inst::StackProbeLoop { .. }
| Inst::Args { .. }
| Inst::Ret { .. }
| Inst::Setcc { .. }
| Inst::ShiftR { .. }
@@ -1452,6 +1453,17 @@ impl PrettyPrint for Inst {
format!("{} *{}", ljustify("call".to_string()), dest)
}
Inst::Args { args } => {
let mut s = "args".to_string();
for arg in args {
use std::fmt::Write;
let preg = regs::show_reg(arg.preg);
let def = pretty_print_reg(arg.vreg.to_reg(), 8, allocs);
write!(&mut s, " {}={}", def, preg).unwrap();
}
s
}
Inst::Ret { .. } => "ret".to_string(),
Inst::JmpKnown { dst } => {
@@ -2037,6 +2049,12 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
mem.get_operands_late(collector)
}
Inst::Args { args } => {
for arg in args {
collector.reg_fixed_def(arg.vreg, arg.preg);
}
}
Inst::Ret { rets } => {
// The return value(s) are live-out; we represent this
// with register uses on the return instruction.
@@ -2134,6 +2152,13 @@ impl MachInst for Inst {
}
}
fn is_args(&self) -> bool {
match self {
Self::Args { .. } => true,
_ => false,
}
}
fn is_term(&self) -> MachTerminator {
match self {
// Interesting cases.