From 62f528929b13f8b27dde2a4694d335bc5341e759 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 19 Dec 2024 11:59:01 -0600 Subject: [PATCH 1/2] Use smallvec for instruction results --- Cargo.lock | 4 ++++ compiler/noirc_evaluator/Cargo.toml | 1 + compiler/noirc_evaluator/src/ssa/ir/dfg.rs | 7 ++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4907de7ae62..f08467e0172 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3184,6 +3184,7 @@ dependencies = [ "serde_json", "serde_with", "similar-asserts", + "smallvec", "test-case", "thiserror", "tracing", @@ -4487,6 +4488,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "smawk" diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index 72fba8aadc2..15531fafff7 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -28,6 +28,7 @@ tracing.workspace = true chrono = "0.4.37" rayon.workspace = true cfg-if.workspace = true +smallvec = { version = "1.13.2", features = ["serde"] } [dev-dependencies] proptest.workspace = true diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index 27eeaa0e15b..f5e1ecc57f7 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -42,7 +42,7 @@ pub(crate) struct DataFlowGraph { /// Call instructions require the func signature, but /// other instructions may need some more reading on my part #[serde_as(as = "HashMap")] - results: HashMap>, + results: HashMap>, /// Storage for all of the values defined in this /// function. @@ -346,10 +346,11 @@ impl DataFlowGraph { ctrl_typevars: Option>, ) { let result_types = self.instruction_result_types(instruction_id, ctrl_typevars); - let results = vecmap(result_types.into_iter().enumerate(), |(position, typ)| { + + let results = result_types.into_iter().enumerate().map(|(position, typ)| { let instruction = instruction_id; self.values.insert(Value::Instruction { typ, position, instruction }) - }); + }).collect(); self.results.insert(instruction_id, results); } From ad0bfc799eed9e3b1351e58bc3e91a1e0c9ef1c5 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Thu, 19 Dec 2024 12:07:30 -0600 Subject: [PATCH 2/2] Avoid allocating in instruction_result_type --- compiler/noirc_evaluator/src/ssa/ir/dfg.rs | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index f5e1ecc57f7..9ccf7f11512 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -342,17 +342,18 @@ impl DataFlowGraph { /// Returns the results of the instruction pub(crate) fn make_instruction_results( &mut self, - instruction_id: InstructionId, + instruction: InstructionId, ctrl_typevars: Option>, ) { - let result_types = self.instruction_result_types(instruction_id, ctrl_typevars); - - let results = result_types.into_iter().enumerate().map(|(position, typ)| { - let instruction = instruction_id; - self.values.insert(Value::Instruction { typ, position, instruction }) - }).collect(); + let mut results = smallvec::SmallVec::new(); + let mut position = 0; + self.for_each_instruction_result_type(instruction, ctrl_typevars, |this, typ| { + let result = this.values.insert(Value::Instruction { typ, position, instruction }); + position += 1; + results.push(result); + }); - self.results.insert(instruction_id, results); + self.results.insert(instruction, results); } /// Return the result types of this instruction. @@ -363,18 +364,21 @@ impl DataFlowGraph { /// the type of an instruction that does not require them. Compared to passing an empty Vec, /// Option has the benefit of panicking if it is accidentally used for a Call instruction, /// rather than silently returning the empty Vec and continuing. - fn instruction_result_types( - &self, + fn for_each_instruction_result_type( + &mut self, instruction_id: InstructionId, ctrl_typevars: Option>, - ) -> Vec { + mut f: impl FnMut(&mut Self, Type), + ) { let instruction = &self.instructions[instruction_id]; match instruction.result_type() { - InstructionResultType::Known(typ) => vec![typ], - InstructionResultType::Operand(value) => vec![self.type_of_value(value)], - InstructionResultType::None => vec![], + InstructionResultType::Known(typ) => f(self, typ), + InstructionResultType::Operand(value) => f(self, self.type_of_value(value)), + InstructionResultType::None => (), InstructionResultType::Unknown => { - ctrl_typevars.expect("Control typevars required but not given") + for typ in ctrl_typevars.expect("Control typevars required but not given") { + f(self, typ); + } } } }