diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index 6eae291ca47..a9a35661539 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -235,6 +235,24 @@ impl DataFlowGraph { block: BasicBlockId, ctrl_typevars: Option>, call_stack: CallStackId, + ) -> InsertInstructionResult { + self.insert_instruction_and_results_if_simplified( + instruction, + block, + ctrl_typevars, + call_stack, + None, + ) + } + + /// Simplifies a potentially existing instruction and inserts it only if it changed. + pub(crate) fn insert_instruction_and_results_if_simplified( + &mut self, + instruction: Instruction, + block: BasicBlockId, + ctrl_typevars: Option>, + call_stack: CallStackId, + existing_id: Option, ) -> InsertInstructionResult { if !self.is_handled_by_runtime(&instruction) { panic!("Attempted to insert instruction not handled by runtime: {instruction:?}"); @@ -251,7 +269,20 @@ impl DataFlowGraph { result @ (SimplifyResult::SimplifiedToInstruction(_) | SimplifyResult::SimplifiedToInstructionMultiple(_) | SimplifyResult::None) => { - let mut instructions = result.instructions().unwrap_or(vec![instruction]); + let instructions = result.instructions(); + if instructions.is_none() { + if let Some(id) = existing_id { + if self[id] == instruction { + // Just (re)insert into the block, no need to redefine. + self.blocks[block].insert_instruction(id); + return InsertInstructionResult::Results( + id, + self.instruction_results(id), + ); + } + } + } + let mut instructions = instructions.unwrap_or(vec![instruction]); assert!(!instructions.is_empty(), "`SimplifyResult::SimplifiedToInstructionMultiple` must not return empty vector"); if instructions.len() > 1 { diff --git a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index 5b75055c09a..e8cae7da5b5 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -423,14 +423,18 @@ impl<'brillig> Context<'brillig> { .then(|| vecmap(old_results, |result| dfg.type_of_value(*result))); let call_stack = dfg.get_instruction_call_stack_id(id); - let new_results = - match dfg.insert_instruction_and_results(instruction, block, ctrl_typevars, call_stack) - { - InsertInstructionResult::SimplifiedTo(new_result) => vec![new_result], - InsertInstructionResult::SimplifiedToMultiple(new_results) => new_results, - InsertInstructionResult::Results(_, new_results) => new_results.to_vec(), - InsertInstructionResult::InstructionRemoved => vec![], - }; + let new_results = match dfg.insert_instruction_and_results_if_simplified( + instruction, + block, + ctrl_typevars, + call_stack, + Some(id), + ) { + InsertInstructionResult::SimplifiedTo(new_result) => vec![new_result], + InsertInstructionResult::SimplifiedToMultiple(new_results) => new_results, + InsertInstructionResult::Results(_, new_results) => new_results.to_vec(), + InsertInstructionResult::InstructionRemoved => vec![], + }; // Optimizations while inserting the instruction should not change the number of results. assert_eq!(old_results.len(), new_results.len());