Skip to content

Commit f4812a2

Browse files
authored
Refactor PRegSet. (#178)
The changes will make it easier to increase the number of physical registers and register classes in the future.
1 parent b13cda1 commit f4812a2

File tree

1 file changed

+45
-32
lines changed

1 file changed

+45
-32
lines changed

src/lib.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ impl core::fmt::Display for PReg {
183183
}
184184
}
185185

186+
/// A type for internal bit arrays.
187+
type Bits = u64;
188+
186189
/// A physical register set. Used to represent clobbers
187190
/// efficiently.
188191
///
@@ -191,82 +194,92 @@ impl core::fmt::Display for PReg {
191194
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
192195
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
193196
pub struct PRegSet {
194-
bits: [u128; 2],
197+
bits: [Bits; Self::LEN],
195198
}
196199

197200
impl PRegSet {
201+
/// The number of bits per element in the internal bit array.
202+
const BITS: usize = core::mem::size_of::<Bits>() * 8;
203+
204+
/// Length of the internal bit array.
205+
const LEN: usize = (PReg::NUM_INDEX + Self::BITS - 1) / Self::BITS;
206+
198207
/// Create an empty set.
199208
pub const fn empty() -> Self {
200-
Self { bits: [0; 2] }
209+
Self {
210+
bits: [0; Self::LEN],
211+
}
212+
}
213+
214+
/// Splits the given register index into parts to access the internal bit array.
215+
const fn split_index(reg: PReg) -> (usize, usize) {
216+
let index = reg.index();
217+
(index >> Self::BITS.ilog2(), index & (Self::BITS - 1))
201218
}
202219

203220
/// Returns whether the given register is part of the set.
204221
pub fn contains(&self, reg: PReg) -> bool {
205-
debug_assert!(reg.index() < 256);
206-
let bit = reg.index() & 127;
207-
let index = reg.index() >> 7;
208-
self.bits[index] & (1u128 << bit) != 0
222+
let (index, bit) = Self::split_index(reg);
223+
self.bits[index] & (1 << bit) != 0
209224
}
210225

211226
/// Add a physical register (PReg) to the set, returning the new value.
212227
pub const fn with(self, reg: PReg) -> Self {
213-
debug_assert!(reg.index() < 256);
214-
let bit = reg.index() & 127;
215-
let index = reg.index() >> 7;
228+
let (index, bit) = Self::split_index(reg);
216229
let mut out = self;
217-
out.bits[index] |= 1u128 << bit;
230+
out.bits[index] |= 1 << bit;
218231
out
219232
}
220233

221234
/// Add a physical register (PReg) to the set.
222235
pub fn add(&mut self, reg: PReg) {
223-
debug_assert!(reg.index() < 256);
224-
let bit = reg.index() & 127;
225-
let index = reg.index() >> 7;
226-
self.bits[index] |= 1u128 << bit;
236+
let (index, bit) = Self::split_index(reg);
237+
self.bits[index] |= 1 << bit;
227238
}
228239

229240
/// Remove a physical register (PReg) from the set.
230241
pub fn remove(&mut self, reg: PReg) {
231-
debug_assert!(reg.index() < 256);
232-
let bit = reg.index() & 127;
233-
let index = reg.index() >> 7;
234-
self.bits[index] &= !(1u128 << bit);
242+
let (index, bit) = Self::split_index(reg);
243+
self.bits[index] &= !(1 << bit);
235244
}
236245

237246
/// Add all of the registers in one set to this one, mutating in
238247
/// place.
239248
pub fn union_from(&mut self, other: PRegSet) {
240-
self.bits[0] |= other.bits[0];
241-
self.bits[1] |= other.bits[1];
249+
for i in 0..self.bits.len() {
250+
self.bits[i] |= other.bits[i];
251+
}
242252
}
243253
}
244254

245255
impl IntoIterator for PRegSet {
246256
type Item = PReg;
247257
type IntoIter = PRegSetIter;
248258
fn into_iter(self) -> PRegSetIter {
249-
PRegSetIter { bits: self.bits }
259+
PRegSetIter {
260+
bits: self.bits,
261+
cur: 0,
262+
}
250263
}
251264
}
252265

253266
pub struct PRegSetIter {
254-
bits: [u128; 2],
267+
bits: [Bits; PRegSet::LEN],
268+
cur: usize,
255269
}
256270

257271
impl Iterator for PRegSetIter {
258272
type Item = PReg;
259273
fn next(&mut self) -> Option<PReg> {
260-
if self.bits[0] != 0 {
261-
let index = self.bits[0].trailing_zeros();
262-
self.bits[0] &= !(1u128 << index);
263-
Some(PReg::from_index(index as usize))
264-
} else if self.bits[1] != 0 {
265-
let index = self.bits[1].trailing_zeros();
266-
self.bits[1] &= !(1u128 << index);
267-
Some(PReg::from_index(index as usize + 128))
268-
} else {
269-
None
274+
loop {
275+
let bits = self.bits.get_mut(self.cur)?;
276+
if *bits != 0 {
277+
let bit = bits.trailing_zeros();
278+
*bits &= !(1 << bit);
279+
let index = bit as usize + self.cur * PRegSet::BITS;
280+
return Some(PReg::from_index(index));
281+
}
282+
self.cur += 1;
270283
}
271284
}
272285
}

0 commit comments

Comments
 (0)