Cleanup: split allocator implemntation into 11 files of more reasonable size.

This commit is contained in:
Chris Fallin
2021-06-18 16:51:08 -07:00
parent 6944bc4735
commit b36a563d69
13 changed files with 5214 additions and 5036 deletions

142
src/ion/redundant_moves.rs Normal file
View File

@@ -0,0 +1,142 @@
//! Redundant-move elimination.
use crate::{Allocation, VReg};
use fxhash::FxHashMap;
use smallvec::{smallvec, SmallVec};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RedundantMoveState {
Copy(Allocation, Option<VReg>),
Orig(VReg),
None,
}
#[derive(Clone, Debug, Default)]
pub struct RedundantMoveEliminator {
allocs: FxHashMap<Allocation, RedundantMoveState>,
reverse_allocs: FxHashMap<Allocation, SmallVec<[Allocation; 4]>>,
}
#[derive(Copy, Clone, Debug)]
pub struct RedundantMoveAction {
pub elide: bool,
pub def_alloc: Option<(Allocation, VReg)>,
}
impl RedundantMoveEliminator {
pub fn process_move(
&mut self,
from: Allocation,
to: Allocation,
to_vreg: Option<VReg>,
) -> RedundantMoveAction {
// Look up the src and dest.
let from_state = self
.allocs
.get(&from)
.map(|&p| p)
.unwrap_or(RedundantMoveState::None);
let to_state = self
.allocs
.get(&to)
.map(|&p| p)
.unwrap_or(RedundantMoveState::None);
log::debug!(
" -> redundant move tracker: from {} to {} to_vreg {:?}",
from,
to,
to_vreg
);
log::debug!(
" -> from_state {:?} to_state {:?}",
from_state,
to_state
);
if from == to && to_vreg.is_some() {
self.clear_alloc(to);
self.allocs
.insert(to, RedundantMoveState::Orig(to_vreg.unwrap()));
return RedundantMoveAction {
elide: true,
def_alloc: Some((to, to_vreg.unwrap())),
};
}
let src_vreg = match from_state {
RedundantMoveState::Copy(_, opt_r) => opt_r,
RedundantMoveState::Orig(r) => Some(r),
_ => None,
};
log::debug!(" -> src_vreg {:?}", src_vreg);
let dst_vreg = to_vreg.or(src_vreg);
log::debug!(" -> dst_vreg {:?}", dst_vreg);
let existing_dst_vreg = match to_state {
RedundantMoveState::Copy(_, opt_r) => opt_r,
RedundantMoveState::Orig(r) => Some(r),
_ => None,
};
log::debug!(" -> existing_dst_vreg {:?}", existing_dst_vreg);
let elide = match (from_state, to_state) {
(_, RedundantMoveState::Copy(orig_alloc, _)) if orig_alloc == from => true,
(RedundantMoveState::Copy(new_alloc, _), _) if new_alloc == to => true,
_ => false,
};
log::debug!(" -> elide {}", elide);
let def_alloc = if dst_vreg != existing_dst_vreg && dst_vreg.is_some() {
Some((to, dst_vreg.unwrap()))
} else {
None
};
log::debug!(" -> def_alloc {:?}", def_alloc);
// Invalidate all existing copies of `to` if `to` actually changed value.
if !elide {
self.clear_alloc(to);
}
// Set up forward and reverse mapping. Don't track stack-to-stack copies.
if from.is_reg() || to.is_reg() {
self.allocs
.insert(to, RedundantMoveState::Copy(from, dst_vreg));
log::debug!(
" -> create mapping {} -> {:?}",
to,
RedundantMoveState::Copy(from, dst_vreg)
);
self.reverse_allocs
.entry(from)
.or_insert_with(|| smallvec![])
.push(to);
}
RedundantMoveAction { elide, def_alloc }
}
pub fn clear(&mut self) {
log::debug!(" redundant move eliminator cleared");
self.allocs.clear();
self.reverse_allocs.clear();
}
pub fn clear_alloc(&mut self, alloc: Allocation) {
log::debug!(" redundant move eliminator: clear {:?}", alloc);
if let Some(ref mut existing_copies) = self.reverse_allocs.get_mut(&alloc) {
for to_inval in existing_copies.iter() {
log::debug!(" -> clear existing copy: {:?}", to_inval);
if let Some(val) = self.allocs.get_mut(to_inval) {
match val {
RedundantMoveState::Copy(_, Some(vreg)) => {
*val = RedundantMoveState::Orig(*vreg);
}
_ => *val = RedundantMoveState::None,
}
}
self.allocs.remove(to_inval);
}
existing_copies.clear();
}
self.allocs.remove(&alloc);
}
}