Some preallocation and removal of one u32 from LiveRange struct

This commit is contained in:
Chris Fallin
2021-05-07 18:52:46 -07:00
parent a453501ebb
commit bfe1c632c9

View File

@@ -117,8 +117,7 @@ struct LiveRange {
range: CodeRange, range: CodeRange,
vreg: VRegIndex, vreg: VRegIndex,
bundle: LiveBundleIndex, bundle: LiveBundleIndex,
uses_spill_weight: u32, uses_spill_weight_and_flags: u32,
num_fixed_uses_and_flags: u32,
first_use: UseIndex, first_use: UseIndex,
last_use: UseIndex, last_use: UseIndex,
@@ -137,36 +136,27 @@ enum LiveRangeFlag {
} }
impl LiveRange { impl LiveRange {
#[inline(always)]
pub fn num_fixed_uses(&self) -> u32 {
self.num_fixed_uses_and_flags & ((1 << 24) - 1)
}
#[inline(always)]
pub fn set_num_fixed_uses(&mut self, count: u32) {
debug_assert!(count < (1 << 24));
self.num_fixed_uses_and_flags = (self.num_fixed_uses_and_flags & !((1 << 24) - 1)) | count;
}
#[inline(always)]
pub fn inc_num_fixed_uses(&mut self) {
debug_assert!(self.num_fixed_uses_and_flags & ((1 << 24) - 1) < ((1 << 24) - 1));
self.num_fixed_uses_and_flags += 1;
}
#[inline(always)]
pub fn dec_num_fixed_uses(&mut self) {
debug_assert!(self.num_fixed_uses_and_flags & ((1 << 24) - 1) > 0);
self.num_fixed_uses_and_flags -= 1;
}
#[inline(always)] #[inline(always)]
pub fn set_flag(&mut self, flag: LiveRangeFlag) { pub fn set_flag(&mut self, flag: LiveRangeFlag) {
self.num_fixed_uses_and_flags |= (flag as u32) << 24; self.uses_spill_weight_and_flags |= (flag as u32) << 30;
} }
#[inline(always)] #[inline(always)]
pub fn clear_flag(&mut self, flag: LiveRangeFlag) { pub fn clear_flag(&mut self, flag: LiveRangeFlag) {
self.num_fixed_uses_and_flags &= !((flag as u32) << 24); self.uses_spill_weight_and_flags &= !((flag as u32) << 30);
} }
#[inline(always)] #[inline(always)]
pub fn has_flag(&self, flag: LiveRangeFlag) -> bool { pub fn has_flag(&self, flag: LiveRangeFlag) -> bool {
self.num_fixed_uses_and_flags & ((flag as u32) << 24) != 0 self.uses_spill_weight_and_flags & ((flag as u32) << 30) != 0
}
#[inline(always)]
pub fn uses_spill_weight(&self) -> u32 {
self.uses_spill_weight_and_flags & 0x3fff_ffff
}
#[inline(always)]
pub fn set_uses_spill_weight(&mut self, weight: u32) {
assert!(weight < (1 << 30));
self.uses_spill_weight_and_flags =
(self.uses_spill_weight_and_flags & 0xc000_0000) | weight;
} }
} }
@@ -739,23 +729,24 @@ impl<'a> std::iter::Iterator for RegTraversalIter<'a> {
impl<'a, F: Function> Env<'a, F> { impl<'a, F: Function> Env<'a, F> {
pub(crate) fn new(func: &'a F, env: &'a MachineEnv, cfginfo: CFGInfo) -> Self { pub(crate) fn new(func: &'a F, env: &'a MachineEnv, cfginfo: CFGInfo) -> Self {
let n = func.insts();
Self { Self {
func, func,
env, env,
cfginfo, cfginfo,
liveins: vec![], liveins: Vec::with_capacity(func.blocks()),
liveouts: vec![], liveouts: Vec::with_capacity(func.blocks()),
blockparam_outs: vec![], blockparam_outs: vec![],
blockparam_ins: vec![], blockparam_ins: vec![],
blockparam_allocs: vec![], blockparam_allocs: vec![],
bundles: vec![], bundles: Vec::with_capacity(n),
ranges: vec![], ranges: Vec::with_capacity(4 * n),
range_ranges: vec![], range_ranges: Vec::with_capacity(4 * n),
spillsets: vec![], spillsets: Vec::with_capacity(n),
uses: vec![], uses: Vec::with_capacity(4 * n),
vregs: vec![], vregs: Vec::with_capacity(n),
vreg_regs: vec![], vreg_regs: Vec::with_capacity(n),
pregs: vec![], pregs: vec![],
allocation_queue: PrioQueue::new(), allocation_queue: PrioQueue::new(),
clobbers: vec![], clobbers: vec![],
@@ -766,14 +757,14 @@ impl<'a, F: Function> Env<'a, F> {
spillslots: vec![], spillslots: vec![],
slots_by_size: vec![], slots_by_size: vec![],
prog_move_srcs: vec![], prog_move_srcs: Vec::with_capacity(n / 2),
prog_move_dsts: vec![], prog_move_dsts: Vec::with_capacity(n / 2),
prog_move_merges: vec![], prog_move_merges: Vec::with_capacity(n / 2),
multi_fixed_reg_fixups: vec![], multi_fixed_reg_fixups: vec![],
inserted_moves: vec![], inserted_moves: vec![],
edits: vec![], edits: Vec::with_capacity(n),
allocs: vec![], allocs: Vec::with_capacity(4 * n),
inst_alloc_offsets: vec![], inst_alloc_offsets: vec![],
num_spillslots: 0, num_spillslots: 0,
safepoint_slots: vec![], safepoint_slots: vec![],
@@ -835,14 +826,17 @@ impl<'a, F: Function> Env<'a, F> {
range, range,
vreg: VRegIndex::invalid(), vreg: VRegIndex::invalid(),
bundle: LiveBundleIndex::invalid(), bundle: LiveBundleIndex::invalid(),
uses_spill_weight: 0, uses_spill_weight_and_flags: 0,
num_fixed_uses_and_flags: 0,
first_use: UseIndex::invalid(), first_use: UseIndex::invalid(),
last_use: UseIndex::invalid(), last_use: UseIndex::invalid(),
next_in_bundle: LiveRangeIndex::invalid(), next_in_bundle: LiveRangeIndex::invalid(),
next_in_reg: LiveRangeIndex::invalid(), next_in_reg: LiveRangeIndex::invalid(),
merged_into: LiveRangeIndex::invalid(), merged_into: LiveRangeIndex::invalid(),
}); });
LiveRangeIndex::new(idx) LiveRangeIndex::new(idx)
} }
@@ -1003,19 +997,16 @@ impl<'a, F: Function> Env<'a, F> {
debug_assert!(u.is_valid()); debug_assert!(u.is_valid());
let usedata = &self.uses[u.index()]; let usedata = &self.uses[u.index()];
let lrdata = &mut self.ranges[from.index()]; let lrdata = &mut self.ranges[from.index()];
if let OperandPolicy::FixedReg(_) = usedata.operand.policy() {
lrdata.dec_num_fixed_uses();
}
log::debug!( log::debug!(
" -> subtract {} from uses_spill_weight {}; now {}", " -> subtract {} from uses_spill_weight {}; now {}",
spill_weight_from_policy(usedata.operand.policy()), spill_weight_from_policy(usedata.operand.policy()),
lrdata.uses_spill_weight, lrdata.uses_spill_weight(),
lrdata.uses_spill_weight - spill_weight_from_policy(usedata.operand.policy()), lrdata.uses_spill_weight() - spill_weight_from_policy(usedata.operand.policy()),
); );
lrdata.uses_spill_weight -= spill_weight_from_policy(usedata.operand.policy()); lrdata.uses_spill_weight_and_flags -= spill_weight_from_policy(usedata.operand.policy());
if usedata.operand.kind() == OperandKind::Def { if usedata.operand.kind() == OperandKind::Def {
lrdata.uses_spill_weight -= 2000; lrdata.uses_spill_weight_and_flags -= 2000;
} }
} }
@@ -1056,20 +1047,17 @@ impl<'a, F: Function> Env<'a, F> {
// Update stats. // Update stats.
let policy = self.uses[u.index()].operand.policy(); let policy = self.uses[u.index()].operand.policy();
if let OperandPolicy::FixedReg(_) = policy {
self.ranges[into.index()].inc_num_fixed_uses();
}
log::debug!( log::debug!(
"insert use {:?} into lr {:?} with weight {}", "insert use {:?} into lr {:?} with weight {}",
u, u,
into, into,
spill_weight_from_policy(policy) spill_weight_from_policy(policy)
); );
self.ranges[into.index()].uses_spill_weight += spill_weight_from_policy(policy); self.ranges[into.index()].uses_spill_weight_and_flags += spill_weight_from_policy(policy);
if self.uses[u.index()].operand.kind() == OperandKind::Def { if self.uses[u.index()].operand.kind() == OperandKind::Def {
self.ranges[into.index()].uses_spill_weight += 2000; self.ranges[into.index()].uses_spill_weight_and_flags += 2000;
} }
log::debug!(" -> now {}", self.ranges[into.index()].uses_spill_weight); log::debug!(" -> now {}", self.ranges[into.index()].uses_spill_weight());
} }
fn find_vreg_liverange_for_pos( fn find_vreg_liverange_for_pos(
@@ -1940,9 +1928,11 @@ impl<'a, F: Function> Env<'a, F> {
to_vreg.index(), to_vreg.index(),
from_vreg.index() from_vreg.index()
); );
let to_bundle = self.ranges[self.vregs[to_vreg.index()].first_range.index()].bundle; let to_bundle =
self.ranges[self.vregs[to_vreg.index()].first_range.index()].bundle;
assert!(to_bundle.is_valid()); assert!(to_bundle.is_valid());
let from_bundle = self.ranges[self.vregs[from_vreg.index()].first_range.index()].bundle; let from_bundle =
self.ranges[self.vregs[from_vreg.index()].first_range.index()].bundle;
assert!(from_bundle.is_valid()); assert!(from_bundle.is_valid());
log::debug!( log::debug!(
" -> from bundle{} to bundle{}", " -> from bundle{} to bundle{}",
@@ -2097,23 +2087,22 @@ impl<'a, F: Function> Env<'a, F> {
log::debug!("vreg{}: first_range={:?}", i, v.first_range,); log::debug!("vreg{}: first_range={:?}", i, v.first_range,);
} }
log::debug!("Ranges:"); log::debug!("Ranges:");
for (i, r) in self.ranges.iter().enumerate() { for (i, (r, rc)) in self.ranges.iter().zip(self.ranges.iter()).enumerate() {
log::debug!( log::debug!(
concat!( concat!(
"range{}: range={:?} vreg={:?} bundle={:?} ", "range{}: range={:?} vreg={:?} bundle={:?} ",
"weight={} fixed={} first_use={:?} last_use={:?} ", "weight={} first_use={:?} last_use={:?} ",
"next_in_bundle={:?} next_in_reg={:?}" "next_in_bundle={:?} next_in_reg={:?}"
), ),
i, i,
r.range, r.range,
r.vreg, rc.vreg,
r.bundle, rc.bundle,
r.uses_spill_weight, r.uses_spill_weight(),
r.num_fixed_uses(),
r.first_use, r.first_use,
r.last_use, rc.last_use,
r.next_in_bundle, r.next_in_bundle,
r.next_in_reg rc.next_in_reg
); );
} }
log::debug!("Uses:"); log::debug!("Uses:");
@@ -2210,7 +2199,10 @@ impl<'a, F: Function> Env<'a, F> {
{ {
log::debug!(" -> btree contains range {:?} that overlaps", preg_range); log::debug!(" -> btree contains range {:?} that overlaps", preg_range);
if self.ranges[preg_range.index()].vreg.is_valid() { if self.ranges[preg_range.index()].vreg.is_valid() {
log::debug!(" -> from vreg {:?}", self.ranges[preg_range.index()].vreg); log::debug!(
" -> from vreg {:?}",
self.ranges[preg_range.index()].vreg
);
// range from an allocated bundle: find the bundle and add to // range from an allocated bundle: find the bundle and add to
// conflicts list. // conflicts list.
let conflict_bundle = self.ranges[preg_range.index()].bundle; let conflict_bundle = self.ranges[preg_range.index()].bundle;
@@ -2361,8 +2353,11 @@ impl<'a, F: Function> Env<'a, F> {
let mut range = self.bundles[bundle.index()].first_range; let mut range = self.bundles[bundle.index()].first_range;
while range.is_valid() { while range.is_valid() {
let range_data = &self.ranges[range.index()]; let range_data = &self.ranges[range.index()];
log::debug!(" -> uses spill weight: +{}", range_data.uses_spill_weight); log::debug!(
total += range_data.uses_spill_weight; " -> uses spill weight: +{}",
range_data.uses_spill_weight()
);
total += range_data.uses_spill_weight();
range = range_data.next_in_bundle; range = range_data.next_in_bundle;
} }
@@ -2798,7 +2793,8 @@ impl<'a, F: Function> Env<'a, F> {
// tail-pointer so we do not need to update that.) // tail-pointer so we do not need to update that.)
let rest_lr = self.create_liverange(rest_range); let rest_lr = self.create_liverange(rest_range);
self.ranges[rest_lr.index()].vreg = self.ranges[iter.index()].vreg; self.ranges[rest_lr.index()].vreg = self.ranges[iter.index()].vreg;
self.ranges[rest_lr.index()].next_in_reg = self.ranges[iter.index()].next_in_reg; self.ranges[rest_lr.index()].next_in_reg =
self.ranges[iter.index()].next_in_reg;
self.ranges[iter.index()].next_in_reg = rest_lr; self.ranges[iter.index()].next_in_reg = rest_lr;
log::debug!( log::debug!(
@@ -2812,7 +2808,6 @@ impl<'a, F: Function> Env<'a, F> {
// moves to the rest range. // moves to the rest range.
let mut last_use_in_first_range = UseIndex::invalid(); let mut last_use_in_first_range = UseIndex::invalid();
let mut use_iter = self.ranges[iter.index()].first_use; let mut use_iter = self.ranges[iter.index()].first_use;
let mut num_fixed_uses = 0;
let mut uses_spill_weight = 0; let mut uses_spill_weight = 0;
while use_iter.is_valid() { while use_iter.is_valid() {
if self.uses[use_iter.index()].pos >= split_point { if self.uses[use_iter.index()].pos >= split_point {
@@ -2825,9 +2820,6 @@ impl<'a, F: Function> Env<'a, F> {
use_iter, use_iter,
policy policy
); );
if let OperandPolicy::FixedReg(_) = policy {
num_fixed_uses += 1;
}
uses_spill_weight += spill_weight_from_policy(policy); uses_spill_weight += spill_weight_from_policy(policy);
log::debug!(" -> use {:?} remains in orig", use_iter); log::debug!(" -> use {:?} remains in orig", use_iter);
use_iter = self.uses[use_iter.index()].next_use; use_iter = self.uses[use_iter.index()].next_use;
@@ -2841,7 +2833,8 @@ impl<'a, F: Function> Env<'a, F> {
use_iter use_iter
); );
self.ranges[rest_lr.index()].first_use = use_iter; self.ranges[rest_lr.index()].first_use = use_iter;
self.ranges[rest_lr.index()].last_use = self.ranges[iter.index()].last_use; self.ranges[rest_lr.index()].last_use =
self.ranges[iter.index()].last_use;
self.ranges[iter.index()].last_use = last_use_in_first_range; self.ranges[iter.index()].last_use = last_use_in_first_range;
if last_use_in_first_range.is_valid() { if last_use_in_first_range.is_valid() {
@@ -2850,13 +2843,10 @@ impl<'a, F: Function> Env<'a, F> {
self.ranges[iter.index()].first_use = UseIndex::invalid(); self.ranges[iter.index()].first_use = UseIndex::invalid();
} }
let rest_fixed_uses = let new_spill_weight =
self.ranges[iter.index()].num_fixed_uses() - num_fixed_uses; self.ranges[iter.index()].uses_spill_weight() - uses_spill_weight;
self.ranges[rest_lr.index()].set_num_fixed_uses(rest_fixed_uses); self.ranges[rest_lr.index()].set_uses_spill_weight(new_spill_weight);
self.ranges[rest_lr.index()].uses_spill_weight = self.ranges[iter.index()].set_uses_spill_weight(uses_spill_weight);
self.ranges[iter.index()].uses_spill_weight - uses_spill_weight;
self.ranges[iter.index()].set_num_fixed_uses(num_fixed_uses);
self.ranges[iter.index()].uses_spill_weight = uses_spill_weight;
} }
log::debug!( log::debug!(
@@ -3458,9 +3448,8 @@ impl<'a, F: Function> Env<'a, F> {
} }
} }
let mut half_moves: Vec<HalfMove> = vec![]; let mut half_moves: Vec<HalfMove> = Vec::with_capacity(6 * self.func.insts());
let mut reuse_input_insts = Vec::with_capacity(self.func.insts() / 2);
let mut reuse_input_insts = vec![];
let mut blockparam_in_idx = 0; let mut blockparam_in_idx = 0;
let mut blockparam_out_idx = 0; let mut blockparam_out_idx = 0;
@@ -4129,7 +4118,8 @@ impl<'a, F: Function> Env<'a, F> {
} }
// Ensure edits are in sorted ProgPoint order. // Ensure edits are in sorted ProgPoint order.
self.edits.sort_unstable_by_key(|&(pos, prio, _)| (pos, prio)); self.edits
.sort_unstable_by_key(|&(pos, prio, _)| (pos, prio));
self.stats.edits_count = self.edits.len(); self.stats.edits_count = self.edits.len();
// Add debug annotations. // Add debug annotations.