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 Nov 19, 2023
1 parent 5d79e12 commit 6080822
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 21 deletions.
34 changes: 24 additions & 10 deletions src/fuzzing/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,13 @@ 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)?, op.class());
let fixed_reg = PReg::new(
match op.class() {
RegClass::Int => u.int_in_range(0..=119)?,
RegClass::Float | RegClass::Vector => u.int_in_range(0..=62)?,
},
op.class(),
);
let fixed_list = match op.pos() {
OperandPos::Early => &mut fixed_early,
OperandPos::Late => &mut fixed_late,
Expand Down Expand Up @@ -511,9 +517,13 @@ impl Func {
clobbers.push(PReg::new(reg, RegClass::arbitrary(u)?));
}
} else if opts.fixed_nonallocatable && bool::arbitrary(u)? {
let class = RegClass::arbitrary(u)?;
operands.push(Operand::fixed_nonallocatable(PReg::new(
63,
RegClass::arbitrary(u)?,
match class {
RegClass::Int => 121,
RegClass::Float | RegClass::Vector => 63,
},
class,
)));
}

Expand Down Expand Up @@ -658,16 +668,20 @@ pub fn machine_env() -> MachineEnv {
regs(24..32, RegClass::Vector),
];
let scratch_by_class: [Option<PReg>; 3] = [None, None, None];
let fixed_stack_slots = (32..63)
let fixed_stack_slots = (32..120)
.flat_map(|i| {
[
PReg::new(i, RegClass::Int),
PReg::new(i, RegClass::Float),
PReg::new(i, RegClass::Vector),
]
if i < 63 {
vec![
PReg::new(i, RegClass::Int),
PReg::new(i, RegClass::Float),
PReg::new(i, RegClass::Vector),
]
} else {
vec![PReg::new(i, RegClass::Int)]
}
})
.collect();
// Register 63 is reserved for use as a fixed non-allocatable register.
// Register 63/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 @@ -106,30 +106,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 @@ -156,7 +167,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 @@ -314,7 +325,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 @@ -540,20 +551,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 @@ -748,7 +762,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 @@ -785,9 +799,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 6080822

Please sign in to comment.