little tweak to avoid a div/mod on every iter of a PReg alloc loop

This commit is contained in:
Chris Fallin
2021-05-26 00:38:53 -07:00
parent b3dc2b25a5
commit 4e0dd1f296

View File

@@ -23,15 +23,7 @@
Performance and code-quality ideas:
- Reduced spilling when spillslot is still "clean":
- When we allocate spillsets, use the whole bundle of a given
spillset to check for fit. Add all bundles to spillset as we
split; then SpillSet::bundles always corresponds to original
merged bundle.
- Then a single bundle will never move between spillslots, so we
know that when we reload from the one single spillslot, it is
the last value that we spilled.
- So we can track 'dirty' status of reg and elide spill when not
dirty.
- Track 'dirty' status of reg and elide spill when not dirty.
- This is slightly tricky: fixpoint problem, across edges.
- We can simplify by assuming spillslot is dirty if value came
in on BB edge; only clean if we reload in same block we spill
@@ -49,6 +41,11 @@
- For a spillslot->spillslot move, push a fixed reg (say the
first preferred one), reload into it, spill out of it, and then
pop old val
- Avoid rebuilding MachineEnv on every function allocation in
regalloc.rs shim
- Profile allocations
*/
#![allow(dead_code, unused_imports)]
@@ -137,7 +134,7 @@ struct LiveRangeListEntry {
}
type LiveRangeList = SmallVec<[LiveRangeListEntry; 4]>;
type UseList = SmallVec<[Use; 4]>;
type UseList = SmallVec<[Use; 2]>;
#[derive(Clone, Debug)]
struct LiveRange {
@@ -689,7 +686,8 @@ struct RegTraversalIter<'a> {
hint_idx: usize,
pref_idx: usize,
non_pref_idx: usize,
offset: usize,
offset_pref: usize,
offset_non_pref: usize,
}
impl<'a> RegTraversalIter<'a> {
@@ -716,14 +714,26 @@ impl<'a> RegTraversalIter<'a> {
hint2_reg = None;
}
let hints = [hint_reg, hint2_reg];
let class = class as u8 as usize;
let offset_pref = if env.preferred_regs_by_class[class].len() > 0 {
offset % env.preferred_regs_by_class[class].len()
} else {
0
};
let offset_non_pref = if env.non_preferred_regs_by_class[class].len() > 0 {
offset % env.non_preferred_regs_by_class[class].len()
} else {
0
};
Self {
env,
class: class as u8 as usize,
class,
hints,
hint_idx: 0,
pref_idx: 0,
non_pref_idx: 0,
offset,
offset_pref,
offset_non_pref,
}
}
}
@@ -732,6 +742,13 @@ impl<'a> std::iter::Iterator for RegTraversalIter<'a> {
type Item = PReg;
fn next(&mut self) -> Option<PReg> {
fn wrap(idx: usize, limit: usize) -> usize {
if idx >= limit {
idx - limit
} else {
idx
}
}
if self.hint_idx < 2 && self.hints[self.hint_idx].is_some() {
let h = self.hints[self.hint_idx];
self.hint_idx += 1;
@@ -739,7 +756,7 @@ impl<'a> std::iter::Iterator for RegTraversalIter<'a> {
}
while self.pref_idx < self.env.preferred_regs_by_class[self.class].len() {
let arr = &self.env.preferred_regs_by_class[self.class][..];
let r = arr[(self.pref_idx + self.offset) % arr.len()];
let r = arr[wrap(self.pref_idx + self.offset_pref, arr.len())];
self.pref_idx += 1;
if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
continue;
@@ -748,7 +765,7 @@ impl<'a> std::iter::Iterator for RegTraversalIter<'a> {
}
while self.non_pref_idx < self.env.non_preferred_regs_by_class[self.class].len() {
let arr = &self.env.non_preferred_regs_by_class[self.class][..];
let r = arr[(self.non_pref_idx + self.offset) % arr.len()];
let r = arr[wrap(self.non_pref_idx + self.offset_non_pref, arr.len())];
self.non_pref_idx += 1;
if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
continue;