Skip to content

Commit

Permalink
Extend integer register PReg space to 128 registers
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu committed May 2, 2023
1 parent 1b4287b commit 253cde7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
8 changes: 4 additions & 4 deletions src/fuzzing/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ impl Func {
// Pick an operand and make it a fixed reg.
let i = u.int_in_range(0..=(operands.len() - 1))?;
let op = operands[i];
let fixed_reg = PReg::new(u.int_in_range(0..=62)?, RegClass::Int);
let fixed_reg = PReg::new(u.int_in_range(0..=119)?, RegClass::Int);
let fixed_list = match op.pos() {
OperandPos::Early => &mut fixed_early,
OperandPos::Late => &mut fixed_late,
Expand Down Expand Up @@ -538,7 +538,7 @@ impl Func {
clobbers.push(PReg::new(reg, RegClass::Int));
}
} else if opts.fixed_nonallocatable && bool::arbitrary(u)? {
operands.push(Operand::fixed_nonallocatable(PReg::new(63, RegClass::Int)));
operands.push(Operand::fixed_nonallocatable(PReg::new(121, RegClass::Int)));
}

let is_safepoint = opts.reftypes
Expand Down Expand Up @@ -662,8 +662,8 @@ pub fn machine_env() -> MachineEnv {
let preferred_regs_by_class: [Vec<PReg>; 3] = [regs(0..24), vec![], vec![]];
let non_preferred_regs_by_class: [Vec<PReg>; 3] = [regs(24..32), vec![], vec![]];
let scratch_by_class: [Option<PReg>; 3] = [None, None, None];
let fixed_stack_slots = regs(32..63);
// Register 63 is reserved for use as a fixed non-allocatable register.
let fixed_stack_slots = regs(32..120);
// Register 121 is reserved for use as a fixed non-allocatable register.
MachineEnv {
preferred_regs_by_class,
non_preferred_regs_by_class,
Expand Down
41 changes: 30 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,30 +103,41 @@ pub struct PReg {
}

impl PReg {
pub const MAX_BITS: usize = 6;
const MAX_BITS: usize = 6;
pub const MAX: usize = (1 << Self::MAX_BITS) - 1;
pub const MAX_INT: usize = (2 << Self::MAX_BITS) - 1;
pub const NUM_INDEX: usize = 1 << (Self::MAX_BITS + 2); // including RegClass bits

/// Create a new PReg. The `hw_enc` range is 6 bits.
#[inline(always)]
pub const fn new(hw_enc: usize, class: RegClass) -> Self {
debug_assert!(hw_enc <= PReg::MAX);
match class {
RegClass::Int => debug_assert!(hw_enc <= PReg::MAX_INT),
RegClass::Float | RegClass::Vector => debug_assert!(hw_enc <= PReg::MAX),
}
let mut class = class as u8;
if class == 0 && hw_enc > PReg::MAX {
class = 3;
}
PReg {
bits: ((class as u8) << Self::MAX_BITS) | (hw_enc as u8),
bits: (class << Self::MAX_BITS) | ((hw_enc & PReg::MAX) as u8),
}
}

/// The physical register number, as encoded by the ISA for the particular register class.
#[inline(always)]
pub const fn hw_enc(self) -> usize {
self.bits as usize & Self::MAX
match self.class() {
RegClass::Int => self.bits as usize & Self::MAX_INT,
RegClass::Float | RegClass::Vector => self.bits as usize & Self::MAX,
}
}

/// The register class.
#[inline(always)]
pub const fn class(self) -> RegClass {
match (self.bits >> Self::MAX_BITS) & 0b11 {
0 => RegClass::Int,
0 | 3 => RegClass::Int,
1 => RegClass::Float,
2 => RegClass::Vector,
_ => unreachable!(),
Expand All @@ -153,7 +164,7 @@ impl PReg {
/// data structures.
#[inline(always)]
pub const fn invalid() -> Self {
PReg::new(Self::MAX, RegClass::Int)
PReg::new(Self::MAX_INT, RegClass::Int)
}
}

Expand Down Expand Up @@ -311,7 +322,7 @@ impl VReg {
pub const fn new(virt_reg: usize, class: RegClass) -> Self {
debug_assert!(virt_reg <= VReg::MAX);
VReg {
bits: ((virt_reg as u32) << 2) | (class as u8 as u32),
bits: ((virt_reg as u32) << 2) | (class as u32),
}
}

Expand Down Expand Up @@ -537,20 +548,23 @@ impl Operand {
kind: OperandKind,
pos: OperandPos,
) -> Self {
let mut class_field = vreg.class() as u32;
let constraint_field = match constraint {
OperandConstraint::Any => 0,
OperandConstraint::Reg => 1,
OperandConstraint::Stack => 2,
OperandConstraint::FixedReg(preg) => {
debug_assert_eq!(preg.class(), vreg.class());
0b1000000 | preg.hw_enc() as u32
if preg.hw_enc() & 0b1000000 != 0 {
class_field = 3;
}
0b1000000 | (preg.hw_enc() & PReg::MAX) as u32
}
OperandConstraint::Reuse(which) => {
debug_assert!(which <= 31);
0b0100000 | which as u32
}
};
let class_field = vreg.class() as u8 as u32;
let pos_field = pos as u8 as u32;
let kind_field = kind as u8 as u32;
Operand {
Expand Down Expand Up @@ -745,7 +759,7 @@ impl Operand {
pub fn class(self) -> RegClass {
let class_field = (self.bits >> 21) & 3;
match class_field {
0 => RegClass::Int,
0 | 3 => RegClass::Int,
1 => RegClass::Float,
2 => RegClass::Vector,
_ => unreachable!(),
Expand Down Expand Up @@ -782,9 +796,14 @@ impl Operand {
/// its allocation must fulfill.
#[inline(always)]
pub fn constraint(self) -> OperandConstraint {
let class_field = (self.bits >> 21) as usize & 3;
let constraint_field = ((self.bits >> 25) as usize) & 127;
if constraint_field & 0b1000000 != 0 {
OperandConstraint::FixedReg(PReg::new(constraint_field & 0b0111111, self.class()))
let mut hw_enc = constraint_field & 0b0111111;
if class_field == 3 {
hw_enc |= 1 << 6;
}
OperandConstraint::FixedReg(PReg::new(hw_enc, self.class()))
} else if constraint_field & 0b0100000 != 0 {
OperandConstraint::Reuse(constraint_field & 0b0011111)
} else {
Expand Down

0 comments on commit 253cde7

Please sign in to comment.