Cranelift: update to latest regalloc2: (#4324)
- Handle call instructions' clobbers with the clobbers API, using RA2's clobbers bitmask (bytecodealliance/regalloc2#58) rather than clobbers list; - Pull in changes from bytecodealliance/regalloc2#59 for much more sane edge-case behavior w.r.t. liverange splitting.
This commit is contained in:
@@ -1202,7 +1202,11 @@ pub(crate) fn emit(
|
||||
sink.put1(0x58 + (enc_dst & 7));
|
||||
}
|
||||
|
||||
Inst::CallKnown { dest, opcode, .. } => {
|
||||
Inst::CallKnown {
|
||||
dest,
|
||||
info: call_info,
|
||||
..
|
||||
} => {
|
||||
if info.flags.enable_probestack() {
|
||||
sink.add_trap(TrapCode::StackOverflow);
|
||||
}
|
||||
@@ -1214,12 +1218,16 @@ pub(crate) fn emit(
|
||||
// beginning of the immediate field.
|
||||
emit_reloc(sink, Reloc::X86CallPCRel4, &dest, -4);
|
||||
sink.put4(0);
|
||||
if opcode.is_call() {
|
||||
sink.add_call_site(*opcode);
|
||||
if call_info.opcode.is_call() {
|
||||
sink.add_call_site(call_info.opcode);
|
||||
}
|
||||
}
|
||||
|
||||
Inst::CallUnknown { dest, opcode, .. } => {
|
||||
Inst::CallUnknown {
|
||||
dest,
|
||||
info: call_info,
|
||||
..
|
||||
} => {
|
||||
let dest = dest.with_allocs(allocs);
|
||||
|
||||
if info.flags.enable_probestack() {
|
||||
@@ -1258,8 +1266,8 @@ pub(crate) fn emit(
|
||||
if let Some(s) = state.take_stack_map() {
|
||||
sink.add_stack_map(StackMapExtent::StartedAtOffset(start_offset), s);
|
||||
}
|
||||
if opcode.is_call() {
|
||||
sink.add_call_site(*opcode);
|
||||
if call_info.opcode.is_call() {
|
||||
sink.add_call_site(call_info.opcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3572,8 +3572,9 @@ fn test_x64_emit() {
|
||||
namespace: 0,
|
||||
index: 0,
|
||||
},
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
smallvec![],
|
||||
smallvec![],
|
||||
PRegSet::default(),
|
||||
Opcode::Call,
|
||||
),
|
||||
"E800000000",
|
||||
@@ -3583,7 +3584,13 @@ fn test_x64_emit() {
|
||||
// ========================================================
|
||||
// CallUnknown
|
||||
fn call_unknown(rm: RegMem) -> Inst {
|
||||
Inst::call_unknown(rm, Vec::new(), Vec::new(), Opcode::CallIndirect)
|
||||
Inst::call_unknown(
|
||||
rm,
|
||||
smallvec![],
|
||||
smallvec![],
|
||||
PRegSet::default(),
|
||||
Opcode::CallIndirect,
|
||||
)
|
||||
}
|
||||
|
||||
insns.push((call_unknown(RegMem::reg(rbp)), "FFD5", "call *%rbp"));
|
||||
|
||||
@@ -8,8 +8,9 @@ use crate::isa::x64::settings as x64_settings;
|
||||
use crate::isa::CallConv;
|
||||
use crate::machinst::*;
|
||||
use crate::{settings, CodegenError, CodegenResult};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use regalloc2::{Allocation, VReg};
|
||||
use regalloc2::{Allocation, PRegSet, VReg};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::fmt;
|
||||
use std::string::{String, ToString};
|
||||
@@ -29,6 +30,19 @@ use args::*;
|
||||
// `Inst` is defined inside ISLE as `MInst`. We publicly re-export it here.
|
||||
pub use super::lower::isle::generated_code::MInst as Inst;
|
||||
|
||||
// Out-of-line data for calls, to keep the size of `Inst` downn.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CallInfo {
|
||||
/// Register uses of this call.
|
||||
pub uses: SmallVec<[Reg; 8]>,
|
||||
/// Register defs of this call.
|
||||
pub defs: SmallVec<[Writable<Reg>; 8]>,
|
||||
/// Registers clobbered by this call, as per its calling convention.
|
||||
pub clobbers: PRegSet,
|
||||
/// The opcode of this call.
|
||||
pub opcode: Opcode,
|
||||
}
|
||||
|
||||
pub(crate) fn low32_will_sign_extend_to_64(x: u64) -> bool {
|
||||
let xs = x as i64;
|
||||
xs == ((xs << 32) >> 32)
|
||||
@@ -646,30 +660,38 @@ impl Inst {
|
||||
|
||||
pub(crate) fn call_known(
|
||||
dest: ExternalName,
|
||||
uses: Vec<Reg>,
|
||||
defs: Vec<Writable<Reg>>,
|
||||
uses: SmallVec<[Reg; 8]>,
|
||||
defs: SmallVec<[Writable<Reg>; 8]>,
|
||||
clobbers: PRegSet,
|
||||
opcode: Opcode,
|
||||
) -> Inst {
|
||||
Inst::CallKnown {
|
||||
dest,
|
||||
uses,
|
||||
defs,
|
||||
opcode,
|
||||
info: Box::new(CallInfo {
|
||||
uses,
|
||||
defs,
|
||||
clobbers,
|
||||
opcode,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn call_unknown(
|
||||
dest: RegMem,
|
||||
uses: Vec<Reg>,
|
||||
defs: Vec<Writable<Reg>>,
|
||||
uses: SmallVec<[Reg; 8]>,
|
||||
defs: SmallVec<[Writable<Reg>; 8]>,
|
||||
clobbers: PRegSet,
|
||||
opcode: Opcode,
|
||||
) -> Inst {
|
||||
dest.assert_regclass_is(RegClass::Int);
|
||||
Inst::CallUnknown {
|
||||
dest,
|
||||
uses,
|
||||
defs,
|
||||
opcode,
|
||||
info: Box::new(CallInfo {
|
||||
uses,
|
||||
defs,
|
||||
clobbers,
|
||||
opcode,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1977,34 +1999,25 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
|
||||
collector.reg_def(dst.to_writable_reg());
|
||||
}
|
||||
|
||||
Inst::CallKnown {
|
||||
ref uses, ref defs, ..
|
||||
} => {
|
||||
for &u in uses {
|
||||
Inst::CallKnown { ref info, .. } => {
|
||||
for &u in &info.uses {
|
||||
collector.reg_use(u);
|
||||
}
|
||||
for &d in defs {
|
||||
for &d in &info.defs {
|
||||
collector.reg_def(d);
|
||||
}
|
||||
// FIXME: keep clobbers separate in the Inst and use
|
||||
// `reg_clobber()`.
|
||||
collector.reg_clobbers(info.clobbers);
|
||||
}
|
||||
|
||||
Inst::CallUnknown {
|
||||
ref uses,
|
||||
ref defs,
|
||||
dest,
|
||||
..
|
||||
} => {
|
||||
Inst::CallUnknown { ref info, dest, .. } => {
|
||||
dest.get_operands(collector);
|
||||
for &u in uses {
|
||||
for &u in &info.uses {
|
||||
collector.reg_use(u);
|
||||
}
|
||||
for &d in defs {
|
||||
for &d in &info.defs {
|
||||
collector.reg_def(d);
|
||||
}
|
||||
// FIXME: keep clobbers separate in the Inst and use
|
||||
// `reg_clobber()`.
|
||||
collector.reg_clobbers(info.clobbers);
|
||||
}
|
||||
|
||||
Inst::JmpTableSeq {
|
||||
@@ -2076,10 +2089,9 @@ fn x64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandCol
|
||||
// pseudoinstruction (and relocation that it emits) is specific to
|
||||
// ELF systems; other x86-64 targets with other conventions (i.e.,
|
||||
// Windows) use different TLS strategies.
|
||||
for reg in X64ABIMachineSpec::get_regs_clobbered_by_call(CallConv::SystemV) {
|
||||
// FIXME: use actual clobber functionality.
|
||||
collector.reg_def(reg);
|
||||
}
|
||||
collector.reg_clobbers(X64ABIMachineSpec::get_regs_clobbered_by_call(
|
||||
CallConv::SystemV,
|
||||
));
|
||||
}
|
||||
|
||||
Inst::Unwind { .. } => {}
|
||||
|
||||
@@ -33,9 +33,12 @@ pub const ENC_R15: u8 = 15;
|
||||
// Constructors for Regs.
|
||||
|
||||
fn gpr(enc: u8) -> Reg {
|
||||
let preg = PReg::new(enc as usize, RegClass::Int);
|
||||
let preg = gpr_preg(enc);
|
||||
Reg::from(VReg::new(preg.index(), RegClass::Int))
|
||||
}
|
||||
pub(crate) const fn gpr_preg(enc: u8) -> PReg {
|
||||
PReg::new(enc as usize, RegClass::Int)
|
||||
}
|
||||
|
||||
pub(crate) fn rsi() -> Reg {
|
||||
gpr(ENC_RSI)
|
||||
@@ -96,10 +99,14 @@ pub(crate) fn pinned_reg() -> Reg {
|
||||
}
|
||||
|
||||
fn fpr(enc: u8) -> Reg {
|
||||
let preg = PReg::new(enc as usize, RegClass::Float);
|
||||
let preg = fpr_preg(enc);
|
||||
Reg::from(VReg::new(preg.index(), RegClass::Float))
|
||||
}
|
||||
|
||||
pub(crate) const fn fpr_preg(enc: u8) -> PReg {
|
||||
PReg::new(enc as usize, RegClass::Float)
|
||||
}
|
||||
|
||||
pub(crate) fn xmm0() -> Reg {
|
||||
fpr(0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user