Add a few register utilities.
This commit is contained in:
@@ -151,6 +151,11 @@ impl RegClassData {
|
|||||||
let uoffset = offset * self.width as usize;
|
let uoffset = offset * self.width as usize;
|
||||||
self.first + uoffset as RegUnit
|
self.first + uoffset as RegUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does this register class contain `regunit`?
|
||||||
|
pub fn contains(&self, regunit: RegUnit) -> bool {
|
||||||
|
self.mask[(regunit / 32) as usize] & (1u32 << (regunit % 32)) != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for RegClassData {
|
impl fmt::Display for RegClassData {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ include!(concat!(env!("OUT_DIR"), "/registers-riscv.rs"));
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::INFO;
|
use super::{INFO, GPR, FPR};
|
||||||
use isa::RegUnit;
|
use isa::RegUnit;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -34,4 +34,16 @@ mod tests {
|
|||||||
assert_eq!(uname(63), "%f31");
|
assert_eq!(uname(63), "%f31");
|
||||||
assert_eq!(uname(64), "%INVALID64");
|
assert_eq!(uname(64), "%INVALID64");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn classes() {
|
||||||
|
assert!(GPR.contains(GPR.unit(0)));
|
||||||
|
assert!(GPR.contains(GPR.unit(31)));
|
||||||
|
assert!(!FPR.contains(GPR.unit(0)));
|
||||||
|
assert!(!FPR.contains(GPR.unit(31)));
|
||||||
|
assert!(!GPR.contains(FPR.unit(0)));
|
||||||
|
assert!(!GPR.contains(FPR.unit(31)));
|
||||||
|
assert!(FPR.contains(FPR.unit(0)));
|
||||||
|
assert!(FPR.contains(FPR.unit(31)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,25 @@ impl AllocatableSet {
|
|||||||
}
|
}
|
||||||
rsi
|
rsi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if any register units allocated out of this set interferes with units allocated out
|
||||||
|
/// of `other`.
|
||||||
|
///
|
||||||
|
/// This assumes that unused bits are 1.
|
||||||
|
pub fn interferes_with(&self, other: &AllocatableSet) -> bool {
|
||||||
|
self.avail
|
||||||
|
.iter()
|
||||||
|
.zip(&other.avail)
|
||||||
|
.any(|(&x, &y)| (x | y) != !0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Intersect this set of allocatable registers with `other`. This has the effect of removing
|
||||||
|
/// any register units from this set that are not in `other`.
|
||||||
|
pub fn intersect(&mut self, other: &AllocatableSet) {
|
||||||
|
for (x, &y) in self.avail.iter_mut().zip(&other.avail) {
|
||||||
|
*x &= y;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over available registers in a register class.
|
/// Iterator over available registers in a register class.
|
||||||
@@ -179,4 +198,18 @@ mod tests {
|
|||||||
assert_eq!(regs.iter(GPR).count(), 7);
|
assert_eq!(regs.iter(GPR).count(), 7);
|
||||||
assert_eq!(regs.iter(DPR).collect::<Vec<_>>(), [30, 33, 35]);
|
assert_eq!(regs.iter(DPR).collect::<Vec<_>>(), [30, 33, 35]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn interference() {
|
||||||
|
let mut regs1 = AllocatableSet::new();
|
||||||
|
let mut regs2 = AllocatableSet::new();
|
||||||
|
|
||||||
|
assert!(!regs1.interferes_with(®s2));
|
||||||
|
regs1.take(&GPR, 32);
|
||||||
|
assert!(!regs1.interferes_with(®s2));
|
||||||
|
regs2.take(&GPR, 31);
|
||||||
|
assert!(!regs1.interferes_with(®s2));
|
||||||
|
regs1.intersect(®s2);
|
||||||
|
assert!(regs1.interferes_with(®s2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user