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:
@@ -297,6 +297,10 @@ impl ABIMachineSpec for X64ABIMachineSpec {
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_args(_isa_flags: &x64_settings::Flags, args: Vec<ArgPair>) -> Inst {
|
||||
Inst::Args { args }
|
||||
}
|
||||
|
||||
fn gen_ret(_setup_frame: bool, _isa_flags: &x64_settings::Flags, rets: Vec<Reg>) -> Self::I {
|
||||
Inst::ret(rets)
|
||||
}
|
||||
|
||||
@@ -323,6 +323,10 @@
|
||||
(CallUnknown (dest RegMem)
|
||||
(info BoxCallInfo))
|
||||
|
||||
;; A pseudo-instruction that captures register arguments in vregs.
|
||||
(Args
|
||||
(args VecArgPair))
|
||||
|
||||
;; Return.
|
||||
(Ret (rets VecReg))
|
||||
|
||||
|
||||
@@ -1406,6 +1406,8 @@ pub(crate) fn emit(
|
||||
}
|
||||
}
|
||||
|
||||
Inst::Args { .. } => {}
|
||||
|
||||
Inst::Ret { .. } => sink.put1(0xC3),
|
||||
|
||||
Inst::JmpKnown { dst } => {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -30,8 +30,8 @@ use crate::{
|
||||
},
|
||||
},
|
||||
machinst::{
|
||||
isle::*, valueregs, InsnInput, InsnOutput, Lower, MachAtomicRmwOp, MachInst, VCodeConstant,
|
||||
VCodeConstantData,
|
||||
isle::*, valueregs, ArgPair, InsnInput, InsnOutput, Lower, MachAtomicRmwOp, MachInst,
|
||||
VCodeConstant, VCodeConstantData,
|
||||
},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
@@ -44,6 +44,7 @@ use target_lexicon::Triple;
|
||||
type BoxCallInfo = Box<CallInfo>;
|
||||
type BoxVecMachLabel = Box<SmallVec<[MachLabel; 4]>>;
|
||||
type MachLabelSlice = [MachLabel];
|
||||
type VecArgPair = Vec<ArgPair>;
|
||||
|
||||
pub struct SinkableLoad {
|
||||
inst: Inst,
|
||||
|
||||
Reference in New Issue
Block a user