diff --git a/fuzz/fuzz_targets/moves.rs b/fuzz/fuzz_targets/moves.rs index b257451..0becec3 100644 --- a/fuzz/fuzz_targets/moves.rs +++ b/fuzz/fuzz_targets/moves.rs @@ -40,14 +40,14 @@ impl Arbitrary<'_> for TestCase { Allocation::reg(PReg::new(reg, RegClass::Int)) } else { let slot = u.int_in_range(0..=31)?; - Allocation::stack(SpillSlot::new(slot, RegClass::Int)) + Allocation::stack(SpillSlot::new(slot)) }; let dst = if bool::arbitrary(u)? { let reg = u.int_in_range(0..=29)?; Allocation::reg(PReg::new(reg, RegClass::Int)) } else { let slot = u.int_in_range(0..=31)?; - Allocation::stack(SpillSlot::new(slot, RegClass::Int)) + Allocation::stack(SpillSlot::new(slot)) }; // Stop if we are going to write a reg more than once: @@ -88,7 +88,7 @@ fuzz_target!(|testcase: TestCase| { let get_stackslot = || { let slot = next_slot; next_slot += 1; - Allocation::stack(SpillSlot::new(slot, RegClass::Int)) + Allocation::stack(SpillSlot::new(slot)) }; let preferred_victim = PReg::new(0, RegClass::Int); let scratch_resolver = diff --git a/src/ion/data_structures.rs b/src/ion/data_structures.rs index 01c0db1..cf92d5a 100644 --- a/src/ion/data_structures.rs +++ b/src/ion/data_structures.rs @@ -440,7 +440,7 @@ impl<'a, F: Function> Env<'a, F> { #[derive(Clone, Debug)] pub struct SpillSlotData { pub ranges: LiveRangeSet, - pub class: RegClass, + pub slots: u32, pub alloc: Allocation, } @@ -580,7 +580,7 @@ pub struct InsertedMove { pub pos_prio: PosWithPrio, pub from_alloc: Allocation, pub to_alloc: Allocation, - pub to_vreg: Option, + pub to_vreg: VReg, } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index 77e842e..b717fcd 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -573,7 +573,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::MultiFixedRegInitial, Allocation::reg(src_preg), Allocation::reg(dst_preg), - Some(dst.vreg()), + dst.vreg(), ); } @@ -718,14 +718,14 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::Regular, Allocation::reg(preg), Allocation::reg(preg), - Some(dst.vreg()), + dst.vreg(), ); self.insert_move( ProgPoint::before(inst.next()), InsertMovePrio::MultiFixedRegInitial, Allocation::reg(preg), Allocation::reg(preg), - Some(src.vreg()), + src.vreg(), ); } else { if inst > self.cfginfo.block_entry[block.index()].inst() { @@ -751,7 +751,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::BlockParam, Allocation::reg(preg), Allocation::reg(preg), - Some(dst.vreg()), + dst.vreg(), ); } } else { @@ -781,7 +781,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::PostRegular, Allocation::reg(preg), Allocation::reg(preg), - Some(dst.vreg()), + dst.vreg(), ); } // Otherwise, if dead, no need to create diff --git a/src/ion/moves.rs b/src/ion/moves.rs index 5109267..9f6e3da 100644 --- a/src/ion/moves.rs +++ b/src/ion/moves.rs @@ -45,20 +45,21 @@ impl<'a, F: Function> Env<'a, F> { prio: InsertMovePrio, from_alloc: Allocation, to_alloc: Allocation, - to_vreg: Option, + to_vreg: VReg, ) { trace!( - "insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}", + "insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?} to_vreg {:?}", pos, prio, from_alloc, - to_alloc + to_alloc, + to_vreg ); - match (from_alloc.as_reg(), to_alloc.as_reg()) { - (Some(from), Some(to)) => { - debug_assert_eq!(from.class(), to.class()); - } - _ => {} + if let Some(from) = from_alloc.as_reg() { + debug_assert_eq!(from.class(), to_vreg.class()); + } + if let Some(to) = to_alloc.as_reg() { + debug_assert_eq!(to.class(), to_vreg.class()); } self.inserted_moves.push(InsertedMove { pos_prio: PosWithPrio { @@ -280,7 +281,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::Regular, prev_alloc, alloc, - Some(self.vreg(vreg)), + self.vreg(vreg), ); } } @@ -720,7 +721,7 @@ impl<'a, F: Function> Env<'a, F> { prio, src.alloc, dest.alloc, - Some(self.vreg(dest.to_vreg())), + self.vreg(dest.to_vreg()), ); last = Some(dest.alloc); } @@ -741,13 +742,7 @@ impl<'a, F: Function> Env<'a, F> { FixedRegFixupLevel::Initial => InsertMovePrio::MultiFixedRegInitial, FixedRegFixupLevel::Secondary => InsertMovePrio::MultiFixedRegSecondary, }; - self.insert_move( - fixup.pos, - prio, - from_alloc, - to_alloc, - Some(self.vreg(fixup.vreg)), - ); + self.insert_move(fixup.pos, prio, from_alloc, to_alloc, self.vreg(fixup.vreg)); self.set_alloc( fixup.pos.inst(), fixup.to_slot as usize, @@ -831,7 +826,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::ReusedInput, input_alloc, output_alloc, - Some(input_operand.vreg()), + input_operand.vreg(), ); self.set_alloc(inst, input_idx, output_alloc); } @@ -871,7 +866,7 @@ impl<'a, F: Function> Env<'a, F> { InsertMovePrio::Regular, from_alloc, to_alloc, - Some(self.vreg(to_vreg)), + self.vreg(to_vreg), ); } @@ -961,13 +956,10 @@ impl<'a, F: Function> Env<'a, F> { let mut float_moves: SmallVec<[InsertedMove; 8]> = smallvec![]; for m in moves { - if m.from_alloc.is_reg() && m.to_alloc.is_reg() { - debug_assert_eq!(m.from_alloc.class(), m.to_alloc.class()); - } if m.from_alloc == m.to_alloc { continue; } - match m.from_alloc.class() { + match m.to_vreg.class() { RegClass::Int => { int_moves.push(m.clone()); } @@ -990,10 +982,8 @@ impl<'a, F: Function> Env<'a, F> { pos_prio.prio ); for m in moves { - if (m.from_alloc != m.to_alloc) || m.to_vreg.is_some() { - trace!(" {} -> {}", m.from_alloc, m.to_alloc,); - parallel_moves.add(m.from_alloc, m.to_alloc, m.to_vreg); - } + trace!(" {} -> {}", m.from_alloc, m.to_alloc); + parallel_moves.add(m.from_alloc, m.to_alloc, Some(m.to_vreg)); } let resolved = parallel_moves.resolve(); @@ -1042,7 +1032,7 @@ impl<'a, F: Function> Env<'a, F> { // these placeholders then allocate the actual // slots if needed with `self.allocate_spillslot` // below. - Allocation::stack(SpillSlot::new(SpillSlot::MAX - idx, regclass)) + Allocation::stack(SpillSlot::new(SpillSlot::MAX - idx)) }; let is_stack_alloc = |alloc: Allocation| { if let Some(preg) = alloc.as_reg() { @@ -1065,11 +1055,12 @@ impl<'a, F: Function> Env<'a, F> { let mut rewrites = FxHashMap::default(); for i in 0..stackslot_idx { if i >= self.extra_spillslots_by_class[regclass as usize].len() { - let slot = self.allocate_spillslot(regclass); + let slot = + self.allocate_spillslot(self.func.spillslot_size(regclass) as u32); self.extra_spillslots_by_class[regclass as usize].push(slot); } rewrites.insert( - Allocation::stack(SpillSlot::new(SpillSlot::MAX - i, regclass)), + Allocation::stack(SpillSlot::new(SpillSlot::MAX - i)), self.extra_spillslots_by_class[regclass as usize][i], ); } diff --git a/src/ion/spill.rs b/src/ion/spill.rs index 121d3f7..5bc6e9e 100644 --- a/src/ion/spill.rs +++ b/src/ion/spill.rs @@ -13,7 +13,7 @@ //! Spillslot allocation. use super::{ - AllocRegResult, Env, LiveRangeKey, LiveRangeSet, PReg, PRegIndex, RegClass, RegTraversalIter, + AllocRegResult, Env, LiveRangeKey, LiveRangeSet, PReg, PRegIndex, RegTraversalIter, SpillSetIndex, SpillSlotData, SpillSlotIndex, SpillSlotList, }; use crate::{Allocation, Function, SpillSlot}; @@ -165,7 +165,7 @@ impl<'a, F: Function> Env<'a, F> { self.spillslots.push(SpillSlotData { ranges: LiveRangeSet::new(), alloc: Allocation::none(), - class: self.spillsets[spillset.index()].class, + slots: size as u32, }); self.slots_by_size[size].slots.push(spillslot); self.slots_by_size[size].probe_start = self.slots_by_size[size].slots.len() - 1; @@ -176,14 +176,13 @@ impl<'a, F: Function> Env<'a, F> { // Assign actual slot indices to spillslots. for i in 0..self.spillslots.len() { - self.spillslots[i].alloc = self.allocate_spillslot(self.spillslots[i].class); + self.spillslots[i].alloc = self.allocate_spillslot(self.spillslots[i].slots); } trace!("spillslot allocator done"); } - pub fn allocate_spillslot(&mut self, class: RegClass) -> Allocation { - let size = self.func.spillslot_size(class) as u32; + pub fn allocate_spillslot(&mut self, size: u32) -> Allocation { let mut offset = self.num_spillslots; // Align up to `size`. debug_assert!(size.is_power_of_two()); @@ -195,6 +194,6 @@ impl<'a, F: Function> Env<'a, F> { }; offset += size; self.num_spillslots = offset; - Allocation::stack(SpillSlot::new(slot as usize, class)) + Allocation::stack(SpillSlot::new(slot as usize)) } } diff --git a/src/lib.rs b/src/lib.rs index 81551ff..1b79368 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -324,13 +324,11 @@ impl SpillSlot { /// The maximum spillslot index. pub const MAX: usize = (1 << 24) - 1; - /// Create a new SpillSlot of a given class. + /// Create a new SpillSlot. #[inline(always)] - pub fn new(slot: usize, class: RegClass) -> Self { + pub fn new(slot: usize) -> Self { debug_assert!(slot <= Self::MAX); - SpillSlot { - bits: (slot as u32) | (class as u8 as u32) << 24, - } + SpillSlot { bits: slot as u32 } } /// Get the spillslot index for this spillslot. @@ -339,20 +337,10 @@ impl SpillSlot { (self.bits & 0x00ffffff) as usize } - /// Get the class for this spillslot. - #[inline(always)] - pub fn class(self) -> RegClass { - match (self.bits >> 24) as u8 { - 0 => RegClass::Int, - 1 => RegClass::Float, - _ => unreachable!(), - } - } - /// Get the spillslot `offset` slots away. #[inline(always)] pub fn plus(self, offset: usize) -> Self { - SpillSlot::new(self.index() + offset, self.class()) + SpillSlot::new(self.index() + offset) } /// Get the invalid spillslot, used for initializing data structures. @@ -965,18 +953,6 @@ pub enum AllocationKind { Stack = 2, } -impl Allocation { - /// Get the register class of an allocation's value. - #[inline(always)] - pub fn class(self) -> RegClass { - match self.kind() { - AllocationKind::None => panic!("Allocation::None has no class"), - AllocationKind::Reg => self.as_reg().unwrap().class(), - AllocationKind::Stack => self.as_stack().unwrap().class(), - } - } -} - /// A trait defined by the regalloc client to provide access to its /// machine-instruction / CFG representation. ///