Compute register class intersections.
Ensure that the set of register classes is closed under intersection. Provide a RegClass::intersect() method which finds the register class representing the intersection of two classes. Generate a bit-mask of subclasses for each register class to be used by the intersect() method. Ensure that register classes are sorted topologically. This is also used by the intersect() method.
This commit is contained in:
@@ -6,7 +6,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-intel.rs"));
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::INFO;
|
||||
use super::*;
|
||||
use isa::RegUnit;
|
||||
|
||||
#[test]
|
||||
@@ -46,4 +46,17 @@ mod tests {
|
||||
assert_eq!(uname(16), "%xmm0");
|
||||
assert_eq!(uname(31), "%xmm15");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regclasses() {
|
||||
assert_eq!(GPR.intersect(GPR), Some(GPR.into()));
|
||||
assert_eq!(GPR.intersect(ABCD), Some(ABCD.into()));
|
||||
assert_eq!(GPR.intersect(FPR), None);
|
||||
assert_eq!(ABCD.intersect(GPR), Some(ABCD.into()));
|
||||
assert_eq!(ABCD.intersect(ABCD), Some(ABCD.into()));
|
||||
assert_eq!(ABCD.intersect(FPR), None);
|
||||
assert_eq!(FPR.intersect(FPR), Some(FPR.into()));
|
||||
assert_eq!(FPR.intersect(GPR), None);
|
||||
assert_eq!(FPR.intersect(ABCD), None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Data structures describing the registers in an ISA.
|
||||
|
||||
use entity_map::EntityRef;
|
||||
use std::fmt;
|
||||
|
||||
/// Register units are the smallest units of register allocation.
|
||||
@@ -106,11 +107,59 @@ pub struct RegClassData {
|
||||
/// How many register units to allocate per register.
|
||||
pub width: u8,
|
||||
|
||||
/// Bit-mask of sub-classes of this register class, including itself.
|
||||
///
|
||||
/// Bits correspond to RC indexes.
|
||||
pub subclasses: u32,
|
||||
|
||||
/// Mask of register units in the class. If `width > 1`, the mask only has a bit set for the
|
||||
/// first register unit in each allocatable register.
|
||||
pub mask: RegUnitMask,
|
||||
}
|
||||
|
||||
impl RegClassData {
|
||||
/// Get the register class corresponding to the intersection of `self` and `other`.
|
||||
///
|
||||
/// This register class is guaranteed to exist if the register classes overlap. If the register
|
||||
/// classes don't overlap, returns `None`.
|
||||
pub fn intersect(&self, other: RegClass) -> Option<RegClassIndex> {
|
||||
// Compute the set of common subclasses.
|
||||
let mask = self.subclasses & other.subclasses;
|
||||
|
||||
if mask == 0 {
|
||||
// No overlap.
|
||||
None
|
||||
} else {
|
||||
// Register class indexes are topologically ordered, so the largest common subclass has
|
||||
// the smallest index.
|
||||
Some(RegClassIndex(mask.trailing_zeros() as u8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A small reference to a register class.
|
||||
///
|
||||
/// Use this when storing register classes in compact data structures. The `RegInfo::rc()` method
|
||||
/// can be used to get the real register class reference back.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct RegClassIndex(u8);
|
||||
|
||||
impl EntityRef for RegClassIndex {
|
||||
fn new(idx: usize) -> Self {
|
||||
RegClassIndex(idx as u8)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RegClass> for RegClassIndex {
|
||||
fn from(rc: RegClass) -> Self {
|
||||
RegClassIndex(rc.index)
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the registers in an ISA.
|
||||
///
|
||||
/// The `RegUnit` data structure collects all relevant static information about the registers in an
|
||||
@@ -143,6 +192,11 @@ impl RegInfo {
|
||||
reginfo: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the register class corresponding to `idx`.
|
||||
pub fn rc(&self, idx: RegClassIndex) -> RegClass {
|
||||
&self.classes[idx.index()]
|
||||
}
|
||||
}
|
||||
|
||||
/// Temporary object that holds enough information to print a register unit.
|
||||
|
||||
@@ -120,11 +120,13 @@ mod tests {
|
||||
const GPR: RegClass = &RegClassData {
|
||||
index: 0,
|
||||
width: 1,
|
||||
subclasses: 0,
|
||||
mask: [0xf0000000, 0x0000000f, 0],
|
||||
};
|
||||
const DPR: RegClass = &RegClassData {
|
||||
index: 0,
|
||||
width: 2,
|
||||
subclasses: 0,
|
||||
mask: [0x50000000, 0x0000000a, 0],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user