Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ component-async-tests = { path = "crates/misc/component-async-tests" }

# Bytecode Alliance maintained dependencies:
# ---------------------------
regalloc2 = "0.13.4"
regalloc2 = "0.14.0"
wasip1 = { version = "1.0.0", default-features = false }

# cap-std family:
Expand Down
161 changes: 78 additions & 83 deletions cranelift/codegen/src/isa/aarch64/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use alloc::boxed::Box;
use alloc::vec::Vec;
use regalloc2::{MachineEnv, PReg, PRegSet};
use smallvec::{SmallVec, smallvec};
use std::sync::OnceLock;

// We use a generic implementation that factors out AArch64 and x64 ABI commonalities, because
// these ABIs are very similar.
Expand Down Expand Up @@ -1089,11 +1088,11 @@ impl ABIMachineSpec for AArch64MachineDeps {

fn get_machine_env(flags: &settings::Flags, _call_conv: isa::CallConv) -> &MachineEnv {
if flags.enable_pinned_reg() {
static MACHINE_ENV: OnceLock<MachineEnv> = OnceLock::new();
MACHINE_ENV.get_or_init(|| create_reg_env(true))
static MACHINE_ENV: MachineEnv = create_reg_env(true);
&MACHINE_ENV
} else {
static MACHINE_ENV: OnceLock<MachineEnv> = OnceLock::new();
MACHINE_ENV.get_or_init(|| create_reg_env(false))
static MACHINE_ENV: MachineEnv = create_reg_env(false);
&MACHINE_ENV
}
}

Expand Down Expand Up @@ -1534,100 +1533,96 @@ const WINCH_CLOBBERS: PRegSet = winch_clobbers();
const ALL_CLOBBERS: PRegSet = all_clobbers();
const NO_CLOBBERS: PRegSet = PRegSet::empty();

fn create_reg_env(enable_pinned_reg: bool) -> MachineEnv {
fn preg(r: Reg) -> PReg {
r.to_real_reg().unwrap().into()
const fn create_reg_env(enable_pinned_reg: bool) -> MachineEnv {
const fn preg(r: Reg) -> PReg {
r.to_real_reg().unwrap().preg()
}

let mut env = MachineEnv {
preferred_regs_by_class: [
vec![
preg(xreg(0)),
preg(xreg(1)),
preg(xreg(2)),
preg(xreg(3)),
preg(xreg(4)),
preg(xreg(5)),
preg(xreg(6)),
preg(xreg(7)),
preg(xreg(8)),
preg(xreg(9)),
preg(xreg(10)),
preg(xreg(11)),
preg(xreg(12)),
preg(xreg(13)),
preg(xreg(14)),
preg(xreg(15)),
// x16 and x17 are spilltmp and tmp2 (see above).
// x18 could be used by the platform to carry inter-procedural state;
// conservatively assume so and make it not allocatable.
// x19-28 are callee-saved and so not preferred.
// x21 is the pinned register (if enabled) and not allocatable if so.
// x29 is FP, x30 is LR, x31 is SP/ZR.
],
vec![
preg(vreg(0)),
preg(vreg(1)),
preg(vreg(2)),
preg(vreg(3)),
preg(vreg(4)),
preg(vreg(5)),
preg(vreg(6)),
preg(vreg(7)),
PRegSet::empty()
.with(preg(xreg(0)))
.with(preg(xreg(1)))
.with(preg(xreg(2)))
.with(preg(xreg(3)))
.with(preg(xreg(4)))
.with(preg(xreg(5)))
.with(preg(xreg(6)))
.with(preg(xreg(7)))
.with(preg(xreg(8)))
.with(preg(xreg(9)))
.with(preg(xreg(10)))
.with(preg(xreg(11)))
.with(preg(xreg(12)))
.with(preg(xreg(13)))
.with(preg(xreg(14)))
.with(preg(xreg(15))),
// x16 and x17 are spilltmp and tmp2 (see above).
// x18 could be used by the platform to carry inter-procedural state;
// conservatively assume so and make it not allocatable.
// x19-28 are callee-saved and so not preferred.
// x21 is the pinned register (if enabled) and not allocatable if so.
// x29 is FP, x30 is LR, x31 is SP/ZR.
PRegSet::empty()
.with(preg(vreg(0)))
.with(preg(vreg(1)))
.with(preg(vreg(2)))
.with(preg(vreg(3)))
.with(preg(vreg(4)))
.with(preg(vreg(5)))
.with(preg(vreg(6)))
.with(preg(vreg(7)))
// v8-15 are callee-saved and so not preferred.
preg(vreg(16)),
preg(vreg(17)),
preg(vreg(18)),
preg(vreg(19)),
preg(vreg(20)),
preg(vreg(21)),
preg(vreg(22)),
preg(vreg(23)),
preg(vreg(24)),
preg(vreg(25)),
preg(vreg(26)),
preg(vreg(27)),
preg(vreg(28)),
preg(vreg(29)),
preg(vreg(30)),
preg(vreg(31)),
],
.with(preg(vreg(16)))
.with(preg(vreg(17)))
.with(preg(vreg(18)))
.with(preg(vreg(19)))
.with(preg(vreg(20)))
.with(preg(vreg(21)))
.with(preg(vreg(22)))
.with(preg(vreg(23)))
.with(preg(vreg(24)))
.with(preg(vreg(25)))
.with(preg(vreg(26)))
.with(preg(vreg(27)))
.with(preg(vreg(28)))
.with(preg(vreg(29)))
.with(preg(vreg(30)))
.with(preg(vreg(31))),
// Vector Regclass is unused
vec![],
PRegSet::empty(),
],
non_preferred_regs_by_class: [
vec![
preg(xreg(19)),
preg(xreg(20)),
PRegSet::empty()
.with(preg(xreg(19)))
.with(preg(xreg(20)))
// x21 is pinned reg if enabled; we add to this list below if not.
preg(xreg(22)),
preg(xreg(23)),
preg(xreg(24)),
preg(xreg(25)),
preg(xreg(26)),
preg(xreg(27)),
preg(xreg(28)),
],
vec![
preg(vreg(8)),
preg(vreg(9)),
preg(vreg(10)),
preg(vreg(11)),
preg(vreg(12)),
preg(vreg(13)),
preg(vreg(14)),
preg(vreg(15)),
],
.with(preg(xreg(22)))
.with(preg(xreg(23)))
.with(preg(xreg(24)))
.with(preg(xreg(25)))
.with(preg(xreg(26)))
.with(preg(xreg(27)))
.with(preg(xreg(28))),
PRegSet::empty()
.with(preg(vreg(8)))
.with(preg(vreg(9)))
.with(preg(vreg(10)))
.with(preg(vreg(11)))
.with(preg(vreg(12)))
.with(preg(vreg(13)))
.with(preg(vreg(14)))
.with(preg(vreg(15))),
// Vector Regclass is unused
vec![],
PRegSet::empty(),
],
fixed_stack_slots: vec![],
scratch_by_class: [None, None, None],
};

if !enable_pinned_reg {
debug_assert_eq!(PINNED_REG, 21); // We assumed this above in hardcoded reg list.
env.non_preferred_regs_by_class[0].push(preg(xreg(PINNED_REG)));
debug_assert!(PINNED_REG == 21);
env.non_preferred_regs_by_class[0].add(preg(xreg(PINNED_REG)));
}

env
Expand Down
4 changes: 2 additions & 2 deletions cranelift/codegen/src/isa/aarch64/inst/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub fn writable_xreg(num: u8) -> Writable<Reg> {
}

/// Get a reference to a V-register (vector/FP register).
pub fn vreg(num: u8) -> Reg {
Reg::from(vreg_preg(num))
pub const fn vreg(num: u8) -> Reg {
Reg::from_real_reg(vreg_preg(num))
}

/// Get the given V-register as a PReg.
Expand Down
131 changes: 111 additions & 20 deletions cranelift/codegen/src/isa/pulley_shared/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ use alloc::borrow::ToOwned;
use alloc::vec::Vec;
use core::marker::PhantomData;
use cranelift_bitset::ScalarBitSet;
use regalloc2::{MachineEnv, PReg, PRegSet};
use regalloc2::{MachineEnv, PRegSet};
use smallvec::{SmallVec, smallvec};
use std::sync::OnceLock;

/// Support for the Pulley ABI from the callee side (within a function body).
pub(crate) type PulleyCallee<P> = Callee<PulleyMachineDeps<P>>;
Expand Down Expand Up @@ -481,8 +480,8 @@ where
}

fn get_machine_env(_flags: &settings::Flags, _call_conv: isa::CallConv) -> &MachineEnv {
static MACHINE_ENV: OnceLock<MachineEnv> = OnceLock::new();
MACHINE_ENV.get_or_init(create_reg_environment)
static MACHINE_ENV: MachineEnv = create_reg_environment();
&MACHINE_ENV
}

fn get_regs_clobbered_by_call(
Expand Down Expand Up @@ -972,26 +971,118 @@ const ALL_CLOBBERS: PRegSet = PRegSet::empty()

const NO_CLOBBERS: PRegSet = PRegSet::empty();

fn create_reg_environment() -> MachineEnv {
const fn create_reg_environment() -> MachineEnv {
// Prefer caller-saved registers over callee-saved registers, because that
// way we don't need to emit code to save and restore them if we don't
// mutate them.

let preferred_regs_by_class: [Vec<PReg>; 3] = {
let x_registers: Vec<PReg> = (0..16).map(|x| px_reg(x)).collect();
let f_registers: Vec<PReg> = (0..32).map(|x| pf_reg(x)).collect();
let v_registers: Vec<PReg> = (0..32).map(|x| pv_reg(x)).collect();
[x_registers, f_registers, v_registers]
};

let non_preferred_regs_by_class: [Vec<PReg>; 3] = {
let x_registers: Vec<PReg> = (16..XReg::SPECIAL_START)
.map(|x| px_reg(x.into()))
.collect();
let f_registers: Vec<PReg> = vec![];
let v_registers: Vec<PReg> = vec![];
[x_registers, f_registers, v_registers]
};
let preferred_regs_by_class: [PRegSet; 3] = [
PRegSet::empty()
.with(px_reg(0))
.with(px_reg(1))
.with(px_reg(2))
.with(px_reg(3))
.with(px_reg(4))
.with(px_reg(5))
.with(px_reg(6))
.with(px_reg(7))
.with(px_reg(8))
.with(px_reg(9))
.with(px_reg(10))
.with(px_reg(11))
.with(px_reg(12))
.with(px_reg(13))
.with(px_reg(14))
.with(px_reg(15)),
PRegSet::empty()
.with(pf_reg(0))
.with(pf_reg(1))
.with(pf_reg(2))
.with(pf_reg(3))
.with(pf_reg(4))
.with(pf_reg(5))
.with(pf_reg(6))
.with(pf_reg(7))
.with(pf_reg(8))
.with(pf_reg(9))
.with(pf_reg(10))
.with(pf_reg(11))
.with(pf_reg(12))
.with(pf_reg(13))
.with(pf_reg(14))
.with(pf_reg(15))
.with(pf_reg(16))
.with(pf_reg(17))
.with(pf_reg(18))
.with(pf_reg(19))
.with(pf_reg(20))
.with(pf_reg(21))
.with(pf_reg(22))
.with(pf_reg(23))
.with(pf_reg(24))
.with(pf_reg(25))
.with(pf_reg(26))
.with(pf_reg(27))
.with(pf_reg(28))
.with(pf_reg(29))
.with(pf_reg(30))
.with(pf_reg(31)),
PRegSet::empty()
.with(pv_reg(0))
.with(pv_reg(1))
.with(pv_reg(2))
.with(pv_reg(3))
.with(pv_reg(4))
.with(pv_reg(5))
.with(pv_reg(6))
.with(pv_reg(7))
.with(pv_reg(8))
.with(pv_reg(9))
.with(pv_reg(10))
.with(pv_reg(11))
.with(pv_reg(12))
.with(pv_reg(13))
.with(pv_reg(14))
.with(pv_reg(15))
.with(pv_reg(16))
.with(pv_reg(17))
.with(pv_reg(18))
.with(pv_reg(19))
.with(pv_reg(20))
.with(pv_reg(21))
.with(pv_reg(22))
.with(pv_reg(23))
.with(pv_reg(24))
.with(pv_reg(25))
.with(pv_reg(26))
.with(pv_reg(27))
.with(pv_reg(28))
.with(pv_reg(29))
.with(pv_reg(30))
.with(pv_reg(31)),
];

let non_preferred_regs_by_class: [PRegSet; 3] = [
PRegSet::empty()
.with(px_reg(16))
.with(px_reg(17))
.with(px_reg(18))
.with(px_reg(19))
.with(px_reg(20))
.with(px_reg(21))
.with(px_reg(22))
.with(px_reg(23))
.with(px_reg(24))
.with(px_reg(25))
.with(px_reg(26))
.with(px_reg(27))
.with(px_reg(28))
.with(px_reg(29)),
PRegSet::empty(),
PRegSet::empty(),
];

debug_assert!(XReg::SPECIAL_START == 30);

MachineEnv {
preferred_regs_by_class,
Expand Down
Loading