Implement pinned register usage through set_pinned_reg/get_pinned_reg;
This commit is contained in:
@@ -4,7 +4,7 @@ use crate::binemit::{CodeOffset, Reloc};
|
|||||||
use crate::ir::constant::ConstantData;
|
use crate::ir::constant::ConstantData;
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::TrapCode;
|
use crate::ir::TrapCode;
|
||||||
use crate::isa::aarch64::inst::*;
|
use crate::isa::aarch64::{inst::regs::PINNED_REG, inst::*};
|
||||||
|
|
||||||
use regalloc::{Reg, RegClass, Writable};
|
use regalloc::{Reg, RegClass, Writable};
|
||||||
|
|
||||||
@@ -1307,6 +1307,20 @@ impl<O: MachSectionOutput> MachInstEmit<O> for Inst {
|
|||||||
}
|
}
|
||||||
_ => unimplemented!("{:?}", mem),
|
_ => unimplemented!("{:?}", mem),
|
||||||
},
|
},
|
||||||
|
&Inst::GetPinnedReg { rd } => {
|
||||||
|
let inst = Inst::Mov {
|
||||||
|
rd,
|
||||||
|
rm: xreg(PINNED_REG),
|
||||||
|
};
|
||||||
|
inst.emit(sink);
|
||||||
|
}
|
||||||
|
&Inst::SetPinnedReg { rm } => {
|
||||||
|
let inst = Inst::Mov {
|
||||||
|
rd: Writable::from_reg(xreg(PINNED_REG)),
|
||||||
|
rm,
|
||||||
|
};
|
||||||
|
inst.emit(sink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1315,6 +1329,7 @@ impl<O: MachSectionOutput> MachInstEmit<O> for Inst {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::isa::test_utils;
|
use crate::isa::test_utils;
|
||||||
|
use crate::settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_aarch64_binemit() {
|
fn test_aarch64_binemit() {
|
||||||
@@ -4074,7 +4089,7 @@ mod test {
|
|||||||
"frintn d23, d24",
|
"frintn d23, d24",
|
||||||
));
|
));
|
||||||
|
|
||||||
let rru = create_reg_universe();
|
let rru = create_reg_universe(&settings::Flags::new(settings::builder()));
|
||||||
for (insn, expected_encoding, expected_printing) in insns {
|
for (insn, expected_encoding, expected_printing) in insns {
|
||||||
println!(
|
println!(
|
||||||
"AArch64: {:?}, {}, {}",
|
"AArch64: {:?}, {}, {}",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::binemit::CodeOffset;
|
|||||||
use crate::ir::types::{B1, B16, B32, B64, B8, F32, F64, FFLAGS, I16, I32, I64, I8, IFLAGS};
|
use crate::ir::types::{B1, B16, B32, B64, B8, F32, F64, FFLAGS, I16, I32, I64, I8, IFLAGS};
|
||||||
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
use crate::ir::{ExternalName, Opcode, SourceLoc, TrapCode, Type};
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
|
use crate::settings;
|
||||||
|
|
||||||
use regalloc::Map as RegallocMap;
|
use regalloc::Map as RegallocMap;
|
||||||
use regalloc::{RealReg, RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
|
use regalloc::{RealReg, RealRegUniverse, Reg, RegClass, SpillSlot, VirtualReg, Writable};
|
||||||
@@ -714,6 +715,16 @@ pub enum Inst {
|
|||||||
rd: Writable<Reg>,
|
rd: Writable<Reg>,
|
||||||
mem: MemArg,
|
mem: MemArg,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Sets the value of the pinned register to the given register target.
|
||||||
|
GetPinnedReg {
|
||||||
|
rd: Writable<Reg>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Writes the value of the given source register to the pinned register.
|
||||||
|
SetPinnedReg {
|
||||||
|
rm: Reg,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_zero_half_words(mut value: u64) -> usize {
|
fn count_zero_half_words(mut value: u64) -> usize {
|
||||||
@@ -1099,6 +1110,12 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
|
|||||||
&Inst::LoadAddr { rd, mem: _ } => {
|
&Inst::LoadAddr { rd, mem: _ } => {
|
||||||
collector.add_def(rd);
|
collector.add_def(rd);
|
||||||
}
|
}
|
||||||
|
&Inst::GetPinnedReg { rd } => {
|
||||||
|
collector.add_def(rd);
|
||||||
|
}
|
||||||
|
&Inst::SetPinnedReg { rm } => {
|
||||||
|
collector.add_use(rm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1660,6 +1677,12 @@ fn aarch64_map_regs(
|
|||||||
map_wr(d, rd);
|
map_wr(d, rd);
|
||||||
map_mem(u, mem);
|
map_mem(u, mem);
|
||||||
}
|
}
|
||||||
|
&mut Inst::GetPinnedReg { ref mut rd } => {
|
||||||
|
map_wr(d, rd);
|
||||||
|
}
|
||||||
|
&mut Inst::SetPinnedReg { ref mut rm } => {
|
||||||
|
map(u, rm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1850,8 +1873,8 @@ impl MachInst for Inst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reg_universe() -> RealRegUniverse {
|
fn reg_universe(flags: &settings::Flags) -> RealRegUniverse {
|
||||||
create_reg_universe()
|
create_reg_universe(flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2589,6 +2612,14 @@ impl ShowWithRRU for Inst {
|
|||||||
}
|
}
|
||||||
_ => unimplemented!("{:?}", mem),
|
_ => unimplemented!("{:?}", mem),
|
||||||
},
|
},
|
||||||
|
&Inst::GetPinnedReg { rd } => {
|
||||||
|
let rd = rd.show_rru(mb_rru);
|
||||||
|
format!("get_pinned_reg {}", rd)
|
||||||
|
}
|
||||||
|
&Inst::SetPinnedReg { rm } => {
|
||||||
|
let rm = rm.show_rru(mb_rru);
|
||||||
|
format!("set_pinned_reg {}", rm)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::isa::aarch64::inst::InstSize;
|
use crate::isa::aarch64::inst::InstSize;
|
||||||
use crate::machinst::*;
|
use crate::machinst::*;
|
||||||
|
use crate::settings;
|
||||||
|
|
||||||
use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
|
use regalloc::{RealRegUniverse, Reg, RegClass, RegClassInfo, Writable, NUM_REG_CLASSES};
|
||||||
|
|
||||||
@@ -10,6 +11,11 @@ use std::string::{String, ToString};
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
// Registers, the Universe thereof, and printing
|
// Registers, the Universe thereof, and printing
|
||||||
|
|
||||||
|
/// The pinned register on this architecture.
|
||||||
|
/// It must be the same as Spidermonkey's HeapReg, as found in this file.
|
||||||
|
/// https://searchfox.org/mozilla-central/source/js/src/jit/arm64/Assembler-arm64.h#103
|
||||||
|
pub const PINNED_REG: u8 = 21;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const XREG_INDICES: [u8; 31] = [
|
const XREG_INDICES: [u8; 31] = [
|
||||||
// X0 - X7
|
// X0 - X7
|
||||||
@@ -22,8 +28,12 @@ const XREG_INDICES: [u8; 31] = [
|
|||||||
47, 48,
|
47, 48,
|
||||||
// X18
|
// X18
|
||||||
60,
|
60,
|
||||||
// X19 - X28
|
// X19, X20
|
||||||
49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
49, 50,
|
||||||
|
// X21, put aside because it's the pinned register.
|
||||||
|
58,
|
||||||
|
// X22 - X28
|
||||||
|
51, 52, 53, 54, 55, 56, 57,
|
||||||
// X29
|
// X29
|
||||||
61,
|
61,
|
||||||
// X30
|
// X30
|
||||||
@@ -131,14 +141,13 @@ pub fn writable_spilltmp_reg() -> Writable<Reg> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create the register universe for AArch64.
|
/// Create the register universe for AArch64.
|
||||||
pub fn create_reg_universe() -> RealRegUniverse {
|
pub fn create_reg_universe(flags: &settings::Flags) -> RealRegUniverse {
|
||||||
let mut regs = vec![];
|
let mut regs = vec![];
|
||||||
let mut allocable_by_class = [None; NUM_REG_CLASSES];
|
let mut allocable_by_class = [None; NUM_REG_CLASSES];
|
||||||
|
|
||||||
// Numbering Scheme: we put V-regs first, then X-regs. The X-regs
|
// Numbering Scheme: we put V-regs first, then X-regs. The X-regs exclude several registers:
|
||||||
// exclude several registers: x18 (globally reserved for platform-specific
|
// x18 (globally reserved for platform-specific purposes), x29 (frame pointer), x30 (link
|
||||||
// purposes), x29 (frame pointer), x30 (link register), x31 (stack pointer
|
// register), x31 (stack pointer or zero register, depending on context).
|
||||||
// or zero register, depending on context).
|
|
||||||
|
|
||||||
let v_reg_base = 0u8; // in contiguous real-register index space
|
let v_reg_base = 0u8; // in contiguous real-register index space
|
||||||
let v_reg_count = 32;
|
let v_reg_count = 32;
|
||||||
@@ -159,9 +168,12 @@ pub fn create_reg_universe() -> RealRegUniverse {
|
|||||||
|
|
||||||
let x_reg_base = 32u8; // in contiguous real-register index space
|
let x_reg_base = 32u8; // in contiguous real-register index space
|
||||||
let mut x_reg_count = 0;
|
let mut x_reg_count = 0;
|
||||||
|
|
||||||
|
let uses_pinned_reg = flags.enable_pinned_reg();
|
||||||
|
|
||||||
for i in 0u8..32u8 {
|
for i in 0u8..32u8 {
|
||||||
// See above for excluded registers.
|
// See above for excluded registers.
|
||||||
if i == 15 || i == 18 || i == 29 || i == 30 || i == 31 {
|
if i == 15 || i == 18 || i == 29 || i == 30 || i == 31 || i == PINNED_REG {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let reg = Reg::new_real(
|
let reg = Reg::new_real(
|
||||||
@@ -188,13 +200,24 @@ pub fn create_reg_universe() -> RealRegUniverse {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Other regs, not available to the allocator.
|
// Other regs, not available to the allocator.
|
||||||
let allocable = regs.len();
|
let allocable = if uses_pinned_reg {
|
||||||
|
// The pinned register is not allocatable in this case, so record the length before adding
|
||||||
|
// it.
|
||||||
|
let len = regs.len();
|
||||||
|
regs.push((xreg(PINNED_REG).to_real_reg(), "x21/pinned_reg".to_string()));
|
||||||
|
len
|
||||||
|
} else {
|
||||||
|
regs.push((xreg(PINNED_REG).to_real_reg(), "x21".to_string()));
|
||||||
|
regs.len()
|
||||||
|
};
|
||||||
|
|
||||||
regs.push((xreg(15).to_real_reg(), "x15".to_string()));
|
regs.push((xreg(15).to_real_reg(), "x15".to_string()));
|
||||||
regs.push((xreg(18).to_real_reg(), "x18".to_string()));
|
regs.push((xreg(18).to_real_reg(), "x18".to_string()));
|
||||||
regs.push((fp_reg().to_real_reg(), "fp".to_string()));
|
regs.push((fp_reg().to_real_reg(), "fp".to_string()));
|
||||||
regs.push((link_reg().to_real_reg(), "lr".to_string()));
|
regs.push((link_reg().to_real_reg(), "lr".to_string()));
|
||||||
regs.push((zero_reg().to_real_reg(), "xzr".to_string()));
|
regs.push((zero_reg().to_real_reg(), "xzr".to_string()));
|
||||||
regs.push((stack_reg().to_real_reg(), "sp".to_string()));
|
regs.push((stack_reg().to_real_reg(), "sp".to_string()));
|
||||||
|
|
||||||
// FIXME JRS 2020Feb06: unfortunately this pushes the number of real regs
|
// FIXME JRS 2020Feb06: unfortunately this pushes the number of real regs
|
||||||
// to 65, which is potentially inconvenient from a compiler performance
|
// to 65, which is potentially inconvenient from a compiler performance
|
||||||
// standpoint. We could possibly drop back to 64 by "losing" a vector
|
// standpoint. We could possibly drop back to 64 by "losing" a vector
|
||||||
|
|||||||
@@ -1935,9 +1935,16 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(ctx: &mut C, insn: IRInst) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::GetPinnedReg
|
Opcode::GetPinnedReg => {
|
||||||
| Opcode::SetPinnedReg
|
let rd = output_to_reg(ctx, outputs[0]);
|
||||||
| Opcode::Spill
|
ctx.emit(Inst::GetPinnedReg { rd });
|
||||||
|
}
|
||||||
|
Opcode::SetPinnedReg => {
|
||||||
|
let rm = input_to_reg(ctx, inputs[0], NarrowValueMode::None);
|
||||||
|
ctx.emit(Inst::SetPinnedReg { rm });
|
||||||
|
}
|
||||||
|
|
||||||
|
Opcode::Spill
|
||||||
| Opcode::Fill
|
| Opcode::Fill
|
||||||
| Opcode::FillNop
|
| Opcode::FillNop
|
||||||
| Opcode::Regmove
|
| Opcode::Regmove
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl MachBackend for AArch64Backend {
|
|||||||
let frame_size = vcode.frame_size();
|
let frame_size = vcode.frame_size();
|
||||||
|
|
||||||
let disasm = if want_disasm {
|
let disasm = if want_disasm {
|
||||||
Some(vcode.show_rru(Some(&create_reg_universe())))
|
Some(vcode.show_rru(Some(&create_reg_universe(flags))))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -77,7 +77,7 @@ impl MachBackend for AArch64Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn reg_universe(&self) -> RealRegUniverse {
|
fn reg_universe(&self) -> RealRegUniverse {
|
||||||
create_reg_universe()
|
create_reg_universe(&self.flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ where
|
|||||||
// This lowers the CL IR.
|
// This lowers the CL IR.
|
||||||
let mut vcode = Lower::new(f, abi).lower(b);
|
let mut vcode = Lower::new(f, abi).lower(b);
|
||||||
|
|
||||||
let universe = &B::MInst::reg_universe();
|
let universe = &B::MInst::reg_universe(vcode.flags());
|
||||||
|
|
||||||
debug!("vcode from lowering: \n{}", vcode.show_rru(Some(universe)));
|
debug!("vcode from lowering: \n{}", vcode.show_rru(Some(universe)));
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ use crate::ir::condcodes::IntCC;
|
|||||||
use crate::ir::{Function, Type};
|
use crate::ir::{Function, Type};
|
||||||
use crate::result::CodegenResult;
|
use crate::result::CodegenResult;
|
||||||
use crate::settings::Flags;
|
use crate::settings::Flags;
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
@@ -189,7 +190,7 @@ pub trait MachInst: Clone + Debug {
|
|||||||
fn with_block_offsets(&mut self, my_offset: CodeOffset, targets: &[CodeOffset]);
|
fn with_block_offsets(&mut self, my_offset: CodeOffset, targets: &[CodeOffset]);
|
||||||
|
|
||||||
/// Get the register universe for this backend.
|
/// Get the register universe for this backend.
|
||||||
fn reg_universe() -> RealRegUniverse;
|
fn reg_universe(flags: &Flags) -> RealRegUniverse;
|
||||||
|
|
||||||
/// Align a basic block offset (from start of function). By default, no
|
/// Align a basic block offset (from start of function). By default, no
|
||||||
/// alignment occurs.
|
/// alignment occurs.
|
||||||
|
|||||||
Reference in New Issue
Block a user