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: Performance and code-quality ideas:
- Reduced spilling when spillslot is still "clean": - Reduced spilling when spillslot is still "clean":
- When we allocate spillsets, use the whole bundle of a given - Track 'dirty' status of reg and elide spill when not dirty.
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.
- This is slightly tricky: fixpoint problem, across edges. - This is slightly tricky: fixpoint problem, across edges.
- We can simplify by assuming spillslot is dirty if value came - 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 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 - For a spillslot->spillslot move, push a fixed reg (say the
first preferred one), reload into it, spill out of it, and then first preferred one), reload into it, spill out of it, and then
pop old val pop old val
- Avoid rebuilding MachineEnv on every function allocation in
regalloc.rs shim
- Profile allocations
*/ */
#![allow(dead_code, unused_imports)] #![allow(dead_code, unused_imports)]
@@ -137,7 +134,7 @@ struct LiveRangeListEntry {
} }
type LiveRangeList = SmallVec<[LiveRangeListEntry; 4]>; type LiveRangeList = SmallVec<[LiveRangeListEntry; 4]>;
type UseList = SmallVec<[Use; 4]>; type UseList = SmallVec<[Use; 2]>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct LiveRange { struct LiveRange {
@@ -689,7 +686,8 @@ struct RegTraversalIter<'a> {
hint_idx: usize, hint_idx: usize,
pref_idx: usize, pref_idx: usize,
non_pref_idx: usize, non_pref_idx: usize,
offset: usize, offset_pref: usize,
offset_non_pref: usize,
} }
impl<'a> RegTraversalIter<'a> { impl<'a> RegTraversalIter<'a> {
@@ -716,14 +714,26 @@ impl<'a> RegTraversalIter<'a> {
hint2_reg = None; hint2_reg = None;
} }
let hints = [hint_reg, hint2_reg]; 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 { Self {
env, env,
class: class as u8 as usize, class,
hints, hints,
hint_idx: 0, hint_idx: 0,
pref_idx: 0, pref_idx: 0,
non_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; type Item = PReg;
fn next(&mut self) -> Option<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() { if self.hint_idx < 2 && self.hints[self.hint_idx].is_some() {
let h = self.hints[self.hint_idx]; let h = self.hints[self.hint_idx];
self.hint_idx += 1; 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() { while self.pref_idx < self.env.preferred_regs_by_class[self.class].len() {
let arr = &self.env.preferred_regs_by_class[self.class][..]; 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; self.pref_idx += 1;
if Some(r) == self.hints[0] || Some(r) == self.hints[1] { if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
continue; 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() { 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 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; self.non_pref_idx += 1;
if Some(r) == self.hints[0] || Some(r) == self.hints[1] { if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
continue; continue;