wip
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 16 Feb 2023 03:59:39 +0000 (19:59 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 16 Feb 2023 03:59:39 +0000 (19:59 -0800)
register_allocator/src/fuzzing.rs
register_allocator/src/live_range.rs
register_allocator/src/loc.rs
register_allocator/src/state.rs

index 25748ad87dd142481178f10094765c0d35001be6..6ba5ace5dbd209826174b672096ae53a0583b462 100644 (file)
@@ -1,11 +1,10 @@
 #![cfg(feature = "fuzzing")]
 use crate::{
     function::{
-        Block, BlockTermInstKind, Constraint, CopyInstKind, Entries, EntriesMut, FnFields, Inst,
-        InstKind, InstStage, KindAndConstraint, Operand, OperandKind, OperandKindDefOnly, SSAVal,
-        SSAValDef,
+        Block, BlockTermInstKind, Constraint, CopyInstKind, FnFields, Inst, InstKind, InstStage,
+        KindAndConstraint, Operand, OperandKind, OperandKindDefOnly, SSAVal, SSAValDef,
     },
-    index::{BlockIdx, InstIdx, InstRange, OperandIdx, RangeIter, SSAValIdx},
+    index::{BlockIdx, Entries, EntriesMut, InstIdx, InstRange, OperandIdx, RangeIter, SSAValIdx},
     interned::{GlobalState, Intern},
     loc::Ty,
     loc_set::LocSet,
index 239120f119a011841a776561a65c9c88a6c042de..9cf9a7193d176bc5fd7ab47152bcaadececacd6a 100644 (file)
@@ -171,6 +171,7 @@ fn _check_prog_range_is_not_hashable() {
 pub struct LiveRange {
     pub range: ProgRange,
     pub ssa_val: SSAValIdx,
+    pub allocation: Option<Loc>,
 }
 
 pub struct LiveRangeBundle {
index 08e81fc2fa7ef89d158b01e2b7126d640f3b3640..6798b4485f6ad801250568904e4296bf3bf125d5 100644 (file)
@@ -2,7 +2,7 @@ use crate::error::{Error, Result};
 use arbitrary::{size_hint, Arbitrary};
 use enum_map::Enum;
 use serde::{Deserialize, Serialize};
-use std::num::NonZeroU32;
+use std::{iter::FusedIterator, num::NonZeroU32};
 
 #[derive(
     Serialize,
@@ -181,6 +181,26 @@ impl Ty {
     }
 }
 
+validated_fields! {
+    #[fields_ty = SubLocFields]
+    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+    pub struct SubLoc {
+        pub kind: LocKind,
+        pub start: u32,
+    }
+}
+
+impl SubLoc {
+    pub const fn new(fields: SubLocFields) -> Result<SubLoc> {
+        const_try!(Loc::new(LocFields {
+            reg_len: nzu32_lit!(1),
+            kind: fields.kind,
+            start: fields.start
+        }));
+        Ok(SubLoc(fields))
+    }
+}
+
 validated_fields! {
     #[fields_ty = LocFields]
     #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
@@ -230,9 +250,18 @@ impl LocFields {
     pub const fn stop(self) -> NonZeroU32 {
         const_unwrap_opt!(self.reg_len.checked_add(self.start), "overflow")
     }
+    pub const fn first_subloc(self) -> SubLocFields {
+        SubLocFields {
+            kind: self.kind,
+            start: self.start,
+        }
+    }
 }
 
 impl Loc {
+    pub const fn first_subloc(self) -> SubLoc {
+        SubLoc(self.get().first_subloc())
+    }
     pub fn arbitrary_with_ty(
         ty: Ty,
         u: &mut arbitrary::Unstructured<'_>,
@@ -358,6 +387,17 @@ impl Loc {
             reg_len: nzu32_lit!(1),
         }),
     ];
+    pub fn sub_locs(
+        self,
+    ) -> impl Iterator<Item = SubLoc> + FusedIterator + ExactSizeIterator + DoubleEndedIterator
+    {
+        let LocFields {
+            reg_len: _,
+            kind,
+            start,
+        } = *self;
+        (start..self.stop().get()).map(move |start| SubLoc(SubLocFields { kind, start }))
+    }
 }
 
 #[cfg(test)]
index 103233a9991f50b0783664ce581232580727c0cb..684f262ca096dcdd074c32d0a3f7747ca177054b 100644 (file)
@@ -1,8 +1,92 @@
-use crate::{function::Function, interned::GlobalState, live_range::LiveRange};
+use crate::{
+    function::Function,
+    index::LiveRangeIdx,
+    interned::GlobalState,
+    live_range::{LiveRange, ProgRange},
+    loc::{Loc, SubLoc},
+};
+use hashbrown::HashMap;
+use std::{collections::BTreeMap, rc::Rc};
 
 #[derive(Debug)]
 pub struct AllocatorState<'a> {
-    global_state: &'a GlobalState,
+    global_state: &'a Rc<GlobalState>,
     func: &'a Function,
     live_ranges: Vec<LiveRange>,
+    allocations: HashMap<SubLoc, BTreeMap<ProgRange, LiveRangeIdx>>,
+}
+
+impl<'a> AllocatorState<'a> {
+    pub fn new(global_state: &'a Rc<GlobalState>, func: &'a Function) -> Self {
+        Self {
+            global_state,
+            func,
+            live_ranges: vec![],
+            allocations: HashMap::new(),
+        }
+    }
+    pub fn global_state(&self) -> &'a Rc<GlobalState> {
+        self.global_state
+    }
+    pub fn func(&self) -> &'a Function {
+        self.func
+    }
+    pub fn live_ranges(&self) -> &[LiveRange] {
+        &self.live_ranges
+    }
+    pub fn allocations(&self, sub_loc: SubLoc) -> &BTreeMap<ProgRange, LiveRangeIdx> {
+        const EMPTY: &'static BTreeMap<ProgRange, LiveRangeIdx> = &BTreeMap::new();
+        self.allocations.get(&sub_loc).unwrap_or(EMPTY)
+    }
+    pub fn remove_allocations_for(&mut self, live_range_idx: LiveRangeIdx) -> Option<Loc> {
+        let live_range = &mut self.live_ranges[live_range_idx];
+        let old_allocation = live_range.allocation.take();
+        if let Some(old_allocation) = old_allocation {
+            for sub_loc in old_allocation.sub_locs() {
+                if let Some(allocations) = self.allocations.get_mut(&sub_loc) {
+                    allocations.remove(&live_range.range);
+                }
+            }
+        }
+        old_allocation
+    }
+    pub fn add_allocations_for(
+        &mut self,
+        live_range_idx: LiveRangeIdx,
+        new_allocation: Option<Loc>,
+    ) {
+        let live_range = &mut self.live_ranges[live_range_idx];
+        assert!(live_range.allocation.is_none());
+        live_range.allocation = new_allocation;
+        if let Some(new_allocation) = new_allocation {
+            for sub_loc in new_allocation.sub_locs() {
+                self.allocations
+                    .entry(sub_loc)
+                    .or_default()
+                    .insert(live_range.range, live_range_idx);
+            }
+        }
+    }
+    pub fn replace_allocation(
+        &mut self,
+        live_range_idx: LiveRangeIdx,
+        new_allocation: Option<Loc>,
+    ) -> Option<Loc> {
+        let old_allocation = self.remove_allocations_for(live_range_idx);
+        self.add_allocations_for(live_range_idx, new_allocation);
+        old_allocation
+    }
+    pub fn add_live_range(&mut self, mut live_range: LiveRange) -> LiveRangeIdx {
+        let allocation = live_range.allocation.take();
+        let live_range_idx = LiveRangeIdx::new(self.live_ranges.len());
+        self.live_ranges.push(live_range);
+        self.add_allocations_for(live_range_idx, allocation);
+        live_range_idx
+    }
+    pub fn set_live_range(&mut self, live_range_idx: LiveRangeIdx, mut new_live_range: LiveRange) {
+        let allocation = new_live_range.allocation.take();
+        self.remove_allocations_for(live_range_idx);
+        self.live_ranges[live_range_idx] = new_live_range;
+        self.add_allocations_for(live_range_idx, allocation);
+    }
 }