Use a SmallVec for ABIArgSlots (#4586)

These are always length 1 for Wasm benchmarks.

<h3>Sightglass Benchmark Results</h3>

```
compilation :: nanoseconds :: benchmarks/spidermonkey/benchmark.wasm

  Δ = 328624015.86 ± 40274677.93 (confidence = 99%)

  main.so is 0.88x to 0.91x faster than slots-smallvec.so!
  slots-smallvec.so is 1.10x to 1.13x faster than main.so!

  [3070752447 3203778792.55 3446269274] main.so
  [2503544039 2875154776.69 3197966713] slots-smallvec.so

compilation :: nanoseconds :: benchmarks/pulldown-cmark/benchmark.wasm

  Δ = 9685705.06 ± 3221286.87 (confidence = 99%)

  main.so is 0.91x to 0.96x faster than slots-smallvec.so!
  slots-smallvec.so is 1.05x to 1.09x faster than main.so!

  [129356493 145594942.79 165038803] main.so
  [118555011 135909237.73 188780619] slots-smallvec.so

compilation :: nanoseconds :: benchmarks/bz2/benchmark.wasm

  No difference in performance.

  [79080493 86757564.46 112649639] main.so
  [78083384 85934125.69 94992743] slots-smallvec.so
```
This commit is contained in:
Nick Fitzgerald
2022-08-02 17:40:36 -07:00
committed by GitHub
parent ab1cf3df2d
commit 55215bbd1e
3 changed files with 10 additions and 5 deletions

View File

@@ -212,7 +212,7 @@ impl ABIMachineSpec for AArch64MachineDeps {
let upper_reg = xreg(next_xreg + 1); let upper_reg = xreg(next_xreg + 1);
ret.push(ABIArg::Slots { ret.push(ABIArg::Slots {
slots: vec![ slots: smallvec![
ABIArgSlot::Reg { ABIArgSlot::Reg {
reg: lower_reg.to_real_reg().unwrap(), reg: lower_reg.to_real_reg().unwrap(),
ty: param.value_type, ty: param.value_type,

View File

@@ -125,7 +125,7 @@ impl ABIMachineSpec for X64ABIMachineSpec {
); );
} }
let mut slots = vec![]; let mut slots = ABIArgSlotVec::new();
for (rc, reg_ty) in rcs.iter().zip(reg_tys.iter()) { for (rc, reg_ty) in rcs.iter().zip(reg_tys.iter()) {
let intreg = *rc == RegClass::Int; let intreg = *rc == RegClass::Int;
let nextreg = if intreg { let nextreg = if intreg {

View File

@@ -153,6 +153,11 @@ impl ABIArgSlot {
} }
} }
/// A vector of `ABIArgSlot`s. Inline capacity for one element because basically
/// 100% of values use one slot. Only `i128`s need multiple slots, and they are
/// super rare (and never happen with Wasm).
pub type ABIArgSlotVec = SmallVec<[ABIArgSlot; 1]>;
/// An ABIArg is composed of one or more parts. This allows for a CLIF-level /// An ABIArg is composed of one or more parts. This allows for a CLIF-level
/// Value to be passed with its parts in more than one location at the ABI /// Value to be passed with its parts in more than one location at the ABI
/// level. For example, a 128-bit integer may be passed in two 64-bit registers, /// level. For example, a 128-bit integer may be passed in two 64-bit registers,
@@ -169,7 +174,7 @@ pub enum ABIArg {
/// parts used to store a value of this type. /// parts used to store a value of this type.
Slots { Slots {
/// Slots, one per register part. /// Slots, one per register part.
slots: Vec<ABIArgSlot>, slots: ABIArgSlotVec,
/// Purpose of this arg. /// Purpose of this arg.
purpose: ir::ArgumentPurpose, purpose: ir::ArgumentPurpose,
}, },
@@ -206,7 +211,7 @@ impl ABIArg {
purpose: ir::ArgumentPurpose, purpose: ir::ArgumentPurpose,
) -> ABIArg { ) -> ABIArg {
ABIArg::Slots { ABIArg::Slots {
slots: vec![ABIArgSlot::Reg { reg, ty, extension }], slots: smallvec![ABIArgSlot::Reg { reg, ty, extension }],
purpose, purpose,
} }
} }
@@ -219,7 +224,7 @@ impl ABIArg {
purpose: ir::ArgumentPurpose, purpose: ir::ArgumentPurpose,
) -> ABIArg { ) -> ABIArg {
ABIArg::Slots { ABIArg::Slots {
slots: vec![ABIArgSlot::Stack { slots: smallvec![ABIArgSlot::Stack {
offset, offset,
ty, ty,
extension, extension,