Avoid indexing and use iteration (#98)

...while still appeasing the borrow checker by taking spillsets out of `self`
and then putting them back in again when we're done.

I was just doing this to enable playing with some data structures in follow up
commits, but decided to benchmark this commit as-is and found 2-4% speed ups to
Cranelift compilation!

```
compilation :: instructions-retired :: benchmarks/bz2/benchmark.wasm

  Δ = 39946528.13 ± 38398.29 (confidence = 99%)

  no-index.so is 1.04x to 1.04x faster than main.so!

  [985704952 985984130.24 986180413] main.so
  [945649144 946037602.11 946262076] no-index.so

compilation :: instructions-retired :: benchmarks/pulldown-cmark/benchmark.wasm

  Δ = 48413802.56 ± 34288.05 (confidence = 99%)

  no-index.so is 1.03x to 1.03x faster than main.so!

  [1593663899 1593926801.92 1594246604] main.so
  [1545196678 1545512999.36 1545802144] no-index.so

compilation :: instructions-retired :: benchmarks/spidermonkey/benchmark.wasm

  Δ = 841028066.56 ± 253404.59 (confidence = 99%)

  no-index.so is 1.02x to 1.02x faster than main.so!

  [34798712681 34801346430.28 34802786661] main.so
  [33958847844 33960318363.72 33962177143] no-index.so
```
This commit is contained in:
Nick Fitzgerald
2022-11-01 10:00:09 -07:00
committed by GitHub
parent b4eedf3f32
commit fdcf7b694f

View File

@@ -89,9 +89,11 @@ impl<'a, F: Function> Env<'a, F> {
spillslot: SpillSlotIndex,
) {
self.spillsets[spillset.index()].slot = spillslot;
for i in 0..self.spillsets[spillset.index()].vregs.len() {
// don't borrow self
let vreg = self.spillsets[spillset.index()].vregs[i];
// Take `spillsets` to avoid a conflicting borrow of `self`.
let spillsets = std::mem::take(&mut self.spillsets);
for vreg in &spillsets[spillset.index()].vregs {
trace!(
"spillslot {:?} alloc'ed to spillset {:?}: vreg {:?}",
spillslot,
@@ -112,6 +114,10 @@ impl<'a, F: Function> Env<'a, F> {
.insert(LiveRangeKey::from_range(&entry.range), entry.index);
}
}
// Replace `spillsets`.
let default = std::mem::replace(&mut self.spillsets, spillsets);
debug_assert!(default.is_empty());
}
pub fn allocate_spillslots(&mut self) {