From 955cdd5f83bd694b1c87d7c69e25cbbee06d675e Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sat, 7 Sep 2019 17:34:08 +0200 Subject: [PATCH] VirtRegs::find: use SmallVec instead of Vec for val_stack. Pushing on the `val_stack` vector is CL's biggest source of calls to malloc/realloc/free, by some margin. It accounts for about 27.7% of all heap blocks allocated when compiling wasm_lua_binarytrees. This change removes pretty much all dynamic allocation by changing to a SmallVec<[Value; 8]> instead. A fixed size of 4 gets all the gains to be had, in testing, so 8 gives some safety margin and is harmless from a stack-use perspective: 8 Values will occupy 32 bytes. As a bonus, this change also reduces the compiler's dynamic instruction count by about 0.5%. --- cranelift/codegen/Cargo.toml | 1 + cranelift/codegen/src/regalloc/virtregs.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 2c5ccb4d2e..2d81a660e8 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -21,6 +21,7 @@ hashmap_core = { version = "0.1.9", optional = true } target-lexicon = "0.8.1" log = { version = "0.4.6", default-features = false } serde = { version = "1.0.94", features = ["derive"], optional = true } +smallvec = { version = "0.6.10" } # It is a goal of the cranelift-codegen crate to have minimal external dependencies. # Please don't add any unless they are essential to the task of creating binary # machine code. Integration tests that need external dependencies can be diff --git a/cranelift/codegen/src/regalloc/virtregs.rs b/cranelift/codegen/src/regalloc/virtregs.rs index 584ad9c53a..fc267c3f61 100644 --- a/cranelift/codegen/src/regalloc/virtregs.rs +++ b/cranelift/codegen/src/regalloc/virtregs.rs @@ -21,6 +21,7 @@ use crate::packed_option::PackedOption; use crate::ref_slice::ref_slice; use core::cmp::Ordering; use core::fmt; +use smallvec::SmallVec; use std::vec::Vec; /// A virtual register reference. @@ -292,7 +293,7 @@ impl VirtRegs { /// Find the leader value and rank of the set containing `v`. /// Compress the path if needed. fn find(&mut self, mut val: Value) -> (Value, u32) { - let mut val_stack = vec![]; + let mut val_stack = SmallVec::<[Value; 8]>::new(); let found = loop { match UFEntry::decode(self.union_find[val]) { UFEntry::Rank(rank) => break (val, rank),