From c86f9624170a29acf99416555fba14aa4f373992 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Fri, 13 Dec 2024 23:59:09 +0000 Subject: [PATCH 1/2] feat: use more efficient field merger code --- .../src/ssa/opt/flatten_cfg/value_merger.rs | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index c2b071a9c9..c9b70398e9 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs @@ -116,20 +116,44 @@ impl<'a> ValueMerger<'a> { let then_condition = dfg.insert_instruction_and_results(cast, block, None, call_stack.clone()).first(); - let cast = Instruction::Cast(else_condition, else_type); - let else_condition = - dfg.insert_instruction_and_results(cast, block, None, call_stack.clone()).first(); - - let mul = Instruction::binary(BinaryOp::Mul, then_condition, then_value); - let then_value = - dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); - - let mul = Instruction::binary(BinaryOp::Mul, else_condition, else_value); - let else_value = - dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); + if then_type == NumericType::NativeField { + // We're merging two fields so we can do a more efficient value merger as by converting + // the expression `if c { a } else { b }` as `c * (a-b) + b`. + // + // This removes a multiplication compared to the standard `c*a + (!c)*b`. + + let diff = Instruction::binary(BinaryOp::Sub, then_value, else_value); + let diff_value = + dfg.insert_instruction_and_results(diff, block, None, call_stack.clone()).first(); + + let conditional_diff = Instruction::binary(BinaryOp::Mul, then_condition, diff_value); + let conditional_diff_value = dfg + .insert_instruction_and_results(conditional_diff, block, None, call_stack.clone()) + .first(); + + let merged_field = + Instruction::binary(BinaryOp::Add, else_value, conditional_diff_value); + dfg + .insert_instruction_and_results(merged_field, block, None, call_stack.clone()) + .first() + } else { + let cast = Instruction::Cast(else_condition, else_type); + let else_condition = + dfg.insert_instruction_and_results(cast, block, None, call_stack.clone()).first(); + + let mul = Instruction::binary(BinaryOp::Mul, then_condition, then_value); + let then_value = + dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); + + let mul = Instruction::binary(BinaryOp::Mul, else_condition, else_value); + let else_value = + dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); + + let add = Instruction::binary(BinaryOp::Add, then_value, else_value); + dfg.insert_instruction_and_results(add, block, None, call_stack).first() + } - let add = Instruction::binary(BinaryOp::Add, then_value, else_value); - dfg.insert_instruction_and_results(add, block, None, call_stack).first() + } /// Given an if expression that returns an array: `if c { array1 } else { array2 }`, From 16ba340c8ac49833e0a2fc3a2ee8566aa4e27b92 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Sat, 14 Dec 2024 00:01:54 +0000 Subject: [PATCH 2/2] . --- .../src/ssa/opt/flatten_cfg/value_merger.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index c9b70398e9..d199a06c1a 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs @@ -130,30 +130,27 @@ impl<'a> ValueMerger<'a> { let conditional_diff_value = dfg .insert_instruction_and_results(conditional_diff, block, None, call_stack.clone()) .first(); - + let merged_field = Instruction::binary(BinaryOp::Add, else_value, conditional_diff_value); - dfg - .insert_instruction_and_results(merged_field, block, None, call_stack.clone()) + dfg.insert_instruction_and_results(merged_field, block, None, call_stack.clone()) .first() } else { let cast = Instruction::Cast(else_condition, else_type); let else_condition = dfg.insert_instruction_and_results(cast, block, None, call_stack.clone()).first(); - + let mul = Instruction::binary(BinaryOp::Mul, then_condition, then_value); let then_value = dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); - + let mul = Instruction::binary(BinaryOp::Mul, else_condition, else_value); let else_value = dfg.insert_instruction_and_results(mul, block, None, call_stack.clone()).first(); - + let add = Instruction::binary(BinaryOp::Add, then_value, else_value); dfg.insert_instruction_and_results(add, block, None, call_stack).first() } - - } /// Given an if expression that returns an array: `if c { array1 } else { array2 }`,