Fix AArch64 ABI to respect half-caller-save, half-callee-save vec regs.
This PR updates the AArch64 ABI implementation so that it (i) properly respects that v8-v15 inclusive have callee-save lower halves, and caller-save upper halves, by conservatively approximating (to full registers) in the appropriate directions when generating prologue caller-saves and when informing the regalloc of clobbered regs across callsites. In order to prevent saving all of these vector registers in the prologue of every non-leaf function due to the above approximation, this also makes use of a new regalloc.rs feature to exclude call instructions' writes from the clobber set returned by register allocation. This is safe whenever the caller and callee have the same ABI (because anything the callee could clobber, the caller is allowed to clobber as well without saving it in the prologue). Fixes #2254.
This commit is contained in:
@@ -361,6 +361,8 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
||||
loc: SourceLoc,
|
||||
opcode: ir::Opcode,
|
||||
tmp: Writable<Reg>,
|
||||
_callee_conv: isa::CallConv,
|
||||
_caller_conv: isa::CallConv,
|
||||
) -> SmallVec<[(InstIsSafepoint, Inst); 2]> {
|
||||
let mut insts = SmallVec::new();
|
||||
match &dest {
|
||||
@@ -431,11 +433,11 @@ impl ABIMachineSpec for Arm32MachineDeps {
|
||||
s.nominal_sp_to_fp
|
||||
}
|
||||
|
||||
fn get_caller_saves(_call_conv: isa::CallConv) -> Vec<Writable<Reg>> {
|
||||
fn get_regs_clobbered_by_call(_: isa::CallConv) -> Vec<Writable<Reg>> {
|
||||
let mut caller_saved = Vec::new();
|
||||
for i in 0..15 {
|
||||
let r = writable_rreg(i);
|
||||
if is_caller_save(r.to_reg().to_real_reg()) {
|
||||
if is_reg_clobbered_by_call(r.to_reg().to_real_reg()) {
|
||||
caller_saved.push(r);
|
||||
}
|
||||
}
|
||||
@@ -461,7 +463,7 @@ fn get_callee_saves(regs: &Set<Writable<RealReg>>) -> Vec<Writable<RealReg>> {
|
||||
ret
|
||||
}
|
||||
|
||||
fn is_caller_save(r: RealReg) -> bool {
|
||||
fn is_reg_clobbered_by_call(r: RealReg) -> bool {
|
||||
let enc = r.get_hw_encoding();
|
||||
enc <= 3
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::isa::arm32::inst::*;
|
||||
|
||||
use regalloc::{RealRegUniverse, Reg};
|
||||
use regalloc::{PrettyPrint, RealRegUniverse, Reg};
|
||||
|
||||
use std::string::String;
|
||||
|
||||
@@ -265,7 +265,7 @@ impl BranchTarget {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for ShiftOpAndAmt {
|
||||
impl PrettyPrint for ShiftOpAndAmt {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
let op = match self.op() {
|
||||
ShiftOp::LSL => "lsl",
|
||||
@@ -277,19 +277,19 @@ impl ShowWithRRU for ShiftOpAndAmt {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for UImm8 {
|
||||
impl PrettyPrint for UImm8 {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
format!("#{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for UImm12 {
|
||||
impl PrettyPrint for UImm12 {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
format!("#{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for AMode {
|
||||
impl PrettyPrint for AMode {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
match self {
|
||||
&AMode::RegReg(rn, rm, imm2) => {
|
||||
@@ -317,7 +317,7 @@ impl ShowWithRRU for AMode {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for Cond {
|
||||
impl PrettyPrint for Cond {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
let mut s = format!("{:?}", self);
|
||||
s.make_ascii_lowercase();
|
||||
@@ -325,7 +325,7 @@ impl ShowWithRRU for Cond {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShowWithRRU for BranchTarget {
|
||||
impl PrettyPrint for BranchTarget {
|
||||
fn show_rru(&self, _mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
match self {
|
||||
&BranchTarget::Label(label) => format!("label{:?}", label.get()),
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
||||
use crate::machinst::*;
|
||||
use crate::{settings, CodegenError, CodegenResult};
|
||||
|
||||
use regalloc::{RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
|
||||
use regalloc::{PrettyPrint, RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
|
||||
use regalloc::{RegUsageCollector, RegUsageMapper};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
@@ -897,7 +897,7 @@ fn mem_finalize_for_show(
|
||||
(mem_str, mem)
|
||||
}
|
||||
|
||||
impl ShowWithRRU for Inst {
|
||||
impl PrettyPrint for Inst {
|
||||
fn show_rru(&self, mb_rru: Option<&RealRegUniverse>) -> String {
|
||||
self.pretty_print(mb_rru, &mut EmitState::default())
|
||||
}
|
||||
|
||||
@@ -513,6 +513,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
}
|
||||
Opcode::Call | Opcode::CallIndirect => {
|
||||
let loc = ctx.srcloc(insn);
|
||||
let caller_conv = ctx.abi().call_conv();
|
||||
let (mut abi, inputs) = match op {
|
||||
Opcode::Call => {
|
||||
let (extname, dist) = ctx.call_target(insn).unwrap();
|
||||
@@ -521,7 +522,7 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
assert_eq!(inputs.len(), sig.params.len());
|
||||
assert_eq!(outputs.len(), sig.returns.len());
|
||||
(
|
||||
Arm32ABICaller::from_func(sig, &extname, dist, loc)?,
|
||||
Arm32ABICaller::from_func(sig, &extname, dist, loc, caller_conv)?,
|
||||
&inputs[..],
|
||||
)
|
||||
}
|
||||
@@ -530,7 +531,10 @@ pub(crate) fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
||||
let sig = ctx.call_sig(insn).unwrap();
|
||||
assert_eq!(inputs.len() - 1, sig.params.len());
|
||||
assert_eq!(outputs.len(), sig.returns.len());
|
||||
(Arm32ABICaller::from_ptr(sig, ptr, loc, op)?, &inputs[1..])
|
||||
(
|
||||
Arm32ABICaller::from_ptr(sig, ptr, loc, op, caller_conv)?,
|
||||
&inputs[1..],
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
use crate::ir::condcodes::IntCC;
|
||||
use crate::ir::Function;
|
||||
use crate::isa::Builder as IsaBuilder;
|
||||
use crate::machinst::{
|
||||
compile, MachBackend, MachCompileResult, ShowWithRRU, TargetIsaAdapter, VCode,
|
||||
};
|
||||
use crate::machinst::{compile, MachBackend, MachCompileResult, TargetIsaAdapter, VCode};
|
||||
use crate::result::CodegenResult;
|
||||
use crate::settings;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use regalloc::RealRegUniverse;
|
||||
use regalloc::{PrettyPrint, RealRegUniverse};
|
||||
use target_lexicon::{Architecture, ArmArchitecture, Triple};
|
||||
|
||||
// New backend:
|
||||
|
||||
Reference in New Issue
Block a user