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..9ccf7f11512 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. @@ -342,16 +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 = vecmap(result_types.into_iter().enumerate(), |(position, typ)| { - let instruction = instruction_id; - self.values.insert(Value::Instruction { typ, position, instruction }) + 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. @@ -362,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); + } } } }