-
Notifications
You must be signed in to change notification settings - Fork 42
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
Adjust Operand encoding #13
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -55,21 +55,21 @@ pub enum RegClass { | |||
/// register 0 is different than Float register 0. | ||||
/// | ||||
/// Because of bit-packed encodings throughout the implementation, | ||||
/// `hw_enc` must fit in 5 bits, i.e., at most 32 registers per class. | ||||
/// `hw_enc` must fit in 6 bits, i.e., at most 64 registers per class. | ||||
/// | ||||
/// The value returned by `index()`, in contrast, is in a single index | ||||
/// space shared by all classes, in order to enable uniform reasoning | ||||
/// about physical registers. This is done by putting the class bit at | ||||
/// the MSB, or equivalently, declaring that indices 0..31 are the 32 | ||||
/// integer registers and indices 32..63 are the 32 float registers. | ||||
/// the MSB, or equivalently, declaring that indices 0..63 are the 64 | ||||
/// integer registers and indices 64..127 are the 64 float registers. | ||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
pub struct PReg { | ||||
hw_enc: u8, | ||||
class: RegClass, | ||||
} | ||||
|
||||
impl PReg { | ||||
pub const MAX_BITS: usize = 5; | ||||
pub const MAX_BITS: usize = 6; | ||||
pub const MAX: usize = (1 << Self::MAX_BITS) - 1; | ||||
pub const MAX_INDEX: usize = 1 << (Self::MAX_BITS + 1); // including RegClass bit | ||||
|
||||
|
@@ -170,7 +170,7 @@ pub struct VReg { | |||
} | ||||
|
||||
impl VReg { | ||||
pub const MAX_BITS: usize = 20; | ||||
pub const MAX_BITS: usize = 21; | ||||
pub const MAX: usize = (1 << Self::MAX_BITS) - 1; | ||||
|
||||
#[inline(always)] | ||||
|
@@ -383,15 +383,15 @@ pub enum OperandPos { | |||
/// that the conflict (overlap) is properly accounted for. See | ||||
/// comments on the constructors below for more. | ||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
//#[repr(packed)] | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like a stray comment ?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops that's from an old test I was doing. |
||||
pub struct Operand { | ||||
/// Bit-pack into 32 bits. | ||||
/// | ||||
/// constraint:3 kind:2 pos:1 class:1 preg:5 vreg:20 | ||||
/// constraint:7 kind:2 pos:1 class:1 vreg:21 | ||||
/// | ||||
/// where `constraint` is an `OperandConstraint`, `kind` is an | ||||
/// `OperandKind`, `pos` is an `OperandPos`, `class` is a | ||||
/// `RegClass`, `preg` is a `PReg` or an index for a reused-input | ||||
/// constraint, and `vreg` is a vreg index. | ||||
/// `RegClass`, and `vreg` is a vreg index. | ||||
bits: u32, | ||||
} | ||||
|
||||
|
@@ -404,29 +404,28 @@ impl Operand { | |||
kind: OperandKind, | ||||
pos: OperandPos, | ||||
) -> Self { | ||||
let (preg_field, constraint_field): (u32, u32) = match constraint { | ||||
OperandConstraint::Any => (0, 0), | ||||
OperandConstraint::Reg => (0, 1), | ||||
OperandConstraint::Stack => (0, 2), | ||||
let constraint_field = match constraint { | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a block comment here describing the bit encoding? |
||||
OperandConstraint::Any => 0, | ||||
OperandConstraint::Reg => 1, | ||||
OperandConstraint::Stack => 2, | ||||
OperandConstraint::FixedReg(preg) => { | ||||
assert_eq!(preg.class(), vreg.class()); | ||||
(preg.hw_enc() as u32, 3) | ||||
0b1000000 | preg.hw_enc() as u32 | ||||
} | ||||
OperandConstraint::Reuse(which) => { | ||||
assert!(which <= PReg::MAX); | ||||
(which as u32, 4) | ||||
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 { | ||||
bits: vreg.vreg() as u32 | ||||
| (preg_field << 20) | ||||
| (class_field << 25) | ||||
| (pos_field << 26) | ||||
| (kind_field << 27) | ||||
| (constraint_field << 29), | ||||
| (class_field << 21) | ||||
| (pos_field << 22) | ||||
| (kind_field << 23) | ||||
| (constraint_field << 25), | ||||
} | ||||
} | ||||
|
||||
|
@@ -565,7 +564,7 @@ impl Operand { | |||
/// Get the register class used by this operand. | ||||
#[inline(always)] | ||||
pub fn class(self) -> RegClass { | ||||
let class_field = (self.bits >> 25) & 1; | ||||
let class_field = (self.bits >> 21) & 1; | ||||
match class_field { | ||||
0 => RegClass::Int, | ||||
1 => RegClass::Float, | ||||
|
@@ -577,7 +576,7 @@ impl Operand { | |||
/// (read), or a "mod" / modify (a read followed by a write). | ||||
#[inline(always)] | ||||
pub fn kind(self) -> OperandKind { | ||||
let kind_field = (self.bits >> 27) & 3; | ||||
let kind_field = (self.bits >> 23) & 3; | ||||
match kind_field { | ||||
0 => OperandKind::Def, | ||||
1 => OperandKind::Mod, | ||||
|
@@ -592,7 +591,7 @@ impl Operand { | |||
/// at "after", though there are cases where this is not true. | ||||
#[inline(always)] | ||||
pub fn pos(self) -> OperandPos { | ||||
let pos_field = (self.bits >> 26) & 1; | ||||
let pos_field = (self.bits >> 22) & 1; | ||||
match pos_field { | ||||
0 => OperandPos::Early, | ||||
1 => OperandPos::Late, | ||||
|
@@ -604,15 +603,18 @@ impl Operand { | |||
/// its allocation must fulfill. | ||||
#[inline(always)] | ||||
pub fn constraint(self) -> OperandConstraint { | ||||
let constraint_field = (self.bits >> 29) & 7; | ||||
let preg_field = ((self.bits >> 20) as usize) & PReg::MAX; | ||||
match constraint_field { | ||||
0 => OperandConstraint::Any, | ||||
1 => OperandConstraint::Reg, | ||||
2 => OperandConstraint::Stack, | ||||
3 => OperandConstraint::FixedReg(PReg::new(preg_field, self.class())), | ||||
4 => OperandConstraint::Reuse(preg_field), | ||||
_ => unreachable!(), | ||||
let constraint_field = ((self.bits >> 25) as usize) & 127; | ||||
if constraint_field & 0b1000000 != 0 { | ||||
OperandConstraint::FixedReg(PReg::new(constraint_field & 0b0111111, self.class())) | ||||
} else if constraint_field & 0b0100000 != 0 { | ||||
OperandConstraint::Reuse(constraint_field & 0b0011111) | ||||
} else { | ||||
match constraint_field { | ||||
0 => OperandConstraint::Any, | ||||
1 => OperandConstraint::Reg, | ||||
2 => OperandConstraint::Stack, | ||||
_ => unreachable!(), | ||||
} | ||||
} | ||||
} | ||||
|
||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pre-existing but a pedantic nit on my own comment: could you adjust to either
0..=63
or0..64
(and likewise for the second range)? Inconsistency w.r.t. Rust open/cosed-range syntax is bothering me :-)