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

@@ -586,8 +586,9 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
let regs = writable_value_regs(self.value_regs[*param]);
for insn in self
.vcode
.abi()
.gen_copy_arg_to_regs(self.sigs(), i, regs)
.vcode
.abi
.gen_copy_arg_to_regs(&self.vcode.vcode.sigs, i, regs)
.into_iter()
{
self.emit(insn);
@@ -611,7 +612,22 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
));
}
}
if let Some(insn) = self.vcode.abi().gen_retval_area_setup(self.sigs()) {
if let Some(insn) = self
.vcode
.vcode
.abi
.gen_retval_area_setup(&self.vcode.vcode.sigs)
{
self.emit(insn);
}
// The `args` instruction below must come first. Finish
// the current "IR inst" (with a default source location,
// as for other special instructions inserted during
// lowering) and continue the scan backward.
self.finish_ir_inst(Default::default());
if let Some(insn) = self.vcode.vcode.abi.take_args() {
self.emit(insn);
}
}