Skip to content

Extend integer register PReg space to 128 registers #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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