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:
@@ -391,6 +391,10 @@ impl ABIMachineSpec for AArch64MachineDeps {
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_args(_isa_flags: &aarch64_settings::Flags, args: Vec<ArgPair>) -> Inst {
|
||||
Inst::Args { args }
|
||||
}
|
||||
|
||||
fn gen_ret(setup_frame: bool, isa_flags: &aarch64_settings::Flags, rets: Vec<Reg>) -> Inst {
|
||||
if isa_flags.sign_return_address() && (setup_frame || isa_flags.sign_return_address_all()) {
|
||||
let key = if isa_flags.sign_return_address_with_bkey() {
|
||||
|
||||
@@ -779,6 +779,10 @@
|
||||
(CallInd
|
||||
(info BoxCallIndInfo))
|
||||
|
||||
;; A pseudo-instruction that captures register arguments in vregs.
|
||||
(Args
|
||||
(args VecArgPair))
|
||||
|
||||
;; ---- branches (exactly one must appear at end of BB) ----
|
||||
|
||||
;; A machine return instruction.
|
||||
|
||||
@@ -3015,6 +3015,10 @@ impl MachInstEmit for Inst {
|
||||
// Emit the jump itself.
|
||||
sink.put4(enc_jump26(0b000101, dest.as_offset26_or_zero()));
|
||||
}
|
||||
&Inst::Args { .. } => {
|
||||
// Nothing: this is a pseudoinstruction that serves
|
||||
// only to constrain registers at a certain point.
|
||||
}
|
||||
&Inst::Ret { .. } => {
|
||||
sink.put4(0xd65f03c0);
|
||||
}
|
||||
|
||||
@@ -1015,6 +1015,11 @@ fn aarch64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
|
||||
collector.reg_def(rd);
|
||||
collector.reg_use(rn);
|
||||
}
|
||||
&Inst::Args { ref args } => {
|
||||
for arg in args {
|
||||
collector.reg_fixed_def(arg.vreg, arg.preg);
|
||||
}
|
||||
}
|
||||
&Inst::Ret { ref rets } | &Inst::AuthenticatedRet { ref rets, .. } => {
|
||||
for &ret in rets {
|
||||
collector.reg_use(ret);
|
||||
@@ -1131,6 +1136,13 @@ impl MachInst for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_args(&self) -> bool {
|
||||
match self {
|
||||
Self::Args { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_term(&self) -> MachTerminator {
|
||||
match self {
|
||||
&Inst::Ret { .. } | &Inst::AuthenticatedRet { .. } => MachTerminator::Ret,
|
||||
@@ -2632,6 +2644,16 @@ impl Inst {
|
||||
let rn = pretty_print_reg(info.rn, allocs);
|
||||
format!("blr {}", rn)
|
||||
}
|
||||
&Inst::Args { ref args } => {
|
||||
let mut s = "args".to_string();
|
||||
for arg in args {
|
||||
use std::fmt::Write;
|
||||
let preg = pretty_print_reg(arg.preg, &mut empty_allocs);
|
||||
let def = pretty_print_reg(arg.vreg.to_reg(), allocs);
|
||||
write!(&mut s, " {}={}", def, preg).unwrap();
|
||||
}
|
||||
s
|
||||
}
|
||||
&Inst::Ret { .. } => "ret".to_string(),
|
||||
&Inst::AuthenticatedRet { key, is_hint, .. } => {
|
||||
let key = match key {
|
||||
|
||||
@@ -30,7 +30,9 @@ use crate::{
|
||||
isa::aarch64::abi::AArch64Caller,
|
||||
isa::aarch64::inst::args::{ShiftOp, ShiftOpShiftImm},
|
||||
isa::unwind::UnwindInst,
|
||||
machinst::{ty_bits, InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData},
|
||||
machinst::{
|
||||
abi::ArgPair, ty_bits, InsnOutput, Lower, MachInst, VCodeConstant, VCodeConstantData,
|
||||
},
|
||||
};
|
||||
use regalloc2::PReg;
|
||||
use std::boxed::Box;
|
||||
@@ -43,6 +45,7 @@ type BoxCallIndInfo = Box<CallIndInfo>;
|
||||
type VecMachLabel = Vec<MachLabel>;
|
||||
type BoxJTSequenceInfo = Box<JTSequenceInfo>;
|
||||
type BoxExternalName = Box<ExternalName>;
|
||||
type VecArgPair = Vec<ArgPair>;
|
||||
|
||||
/// The main entry point for lowering with ISLE.
|
||||
pub(crate) fn lower(
|
||||
|
||||
Reference in New Issue
Block a user