From 8900f8110728895102e718fc4b50736fbb2b0d61 Mon Sep 17 00:00:00 2001 From: Kevaundray Wedderburn Date: Sat, 27 May 2023 18:12:46 +0100 Subject: [PATCH] add research on region labelling --- crates/noirc_evaluator/src/ssa_refactor.rs | 3 +- .../acir_gen/acir_ir/acir_variable.rs | 2 +- .../acir_gen/acir_ir/generated_acir.rs | 66 +++++++++++++++++++ .../src/ssa_refactor/acir_gen/mod.rs | 5 +- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/crates/noirc_evaluator/src/ssa_refactor.rs b/crates/noirc_evaluator/src/ssa_refactor.rs index 2959aef9661..acf2e42fcf5 100644 --- a/crates/noirc_evaluator/src/ssa_refactor.rs +++ b/crates/noirc_evaluator/src/ssa_refactor.rs @@ -43,6 +43,7 @@ pub(crate) fn optimize_into_acir(program: Program) -> GeneratedAcir { .mem2reg() .print("After Mem2Reg:") .into_acir(func_signature) + .print_acir() } /// Compiles the Program into ACIR and applies optimizations to the arithmetic gates @@ -56,7 +57,7 @@ pub fn experimental_create_circuit( _show_output: bool, ) -> Result<(Circuit, Abi), RuntimeError> { let func_sig = program.main_function_signature.clone(); - let GeneratedAcir { current_witness_index, opcodes, return_witnesses } = + let GeneratedAcir { current_witness_index, opcodes, return_witnesses, .. } = optimize_into_acir(program); let abi = gen_abi(func_sig, return_witnesses.clone()); diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs index 90bae15dbc1..b1ba08d0546 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/acir_variable.rs @@ -28,7 +28,7 @@ pub(crate) struct AcirContext { /// For example, If one was to add two Variables together, /// then the `acir_ir` will be populated to assert this /// addition. - acir_ir: GeneratedAcir, + pub(crate) acir_ir: GeneratedAcir, } impl AcirContext { diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs index bd53136557c..bfe6774d43a 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/acir_ir/generated_acir.rs @@ -10,6 +10,18 @@ use acvm::{ FieldElement, }; +#[derive(Debug, Default)] +pub(crate) struct OpcodeRegionLabel { + /// Range of the opcodes included in the region + start_range: usize, + /// The end range is `None` while its on the region_stack + /// and the caller has not finalized the region. + end_range_inclusive: Option, + + /// Label to apply to this region of code + label: String, +} + #[derive(Debug, Default)] /// The output of the Acir-gen pass pub(crate) struct GeneratedAcir { @@ -26,9 +38,63 @@ pub(crate) struct GeneratedAcir { /// Note: This may contain repeated indices, which is necessary for later mapping into the /// abi's return type. pub(crate) return_witnesses: Vec, + + /// For debugging purposes, one can label blocks of the opcode. + finalized_regions: Vec, + region_stack: Vec, } impl GeneratedAcir { + pub(crate) fn start_region_label(&mut self, region_name: String) { + self.region_stack.push(OpcodeRegionLabel { + start_range: self.opcodes.len(), + end_range_inclusive: None, + label: region_name, + }) + } + pub(crate) fn end_label(&mut self) { + let mut region_label = self.region_stack.pop().expect("tried to pop a region label from the stack without first pushing a region onto the stack"); + region_label.end_range_inclusive = Some(self.opcodes.len()); + self.finalized_regions.push(region_label) + } + + pub(crate) fn print_acir(self) -> Self { + fn check_if_region_starting( + index: usize, + regions: &[OpcodeRegionLabel], + ) -> Vec<&OpcodeRegionLabel> { + regions.into_iter().filter(|region| region.start_range == index).collect() + } + fn check_if_region_ending( + index: usize, + regions: &[OpcodeRegionLabel], + ) -> Vec<&OpcodeRegionLabel> { + regions + .into_iter() + .filter(|region| { + region.end_range_inclusive.expect("region has not been finalized") == index + }) + .collect() + } + + for (index, opcode) in self.opcodes.iter().enumerate() { + let regions_starting = check_if_region_starting(index, &self.finalized_regions); + let regions_ending = check_if_region_ending(index, &self.finalized_regions); + + for region in regions_starting { + println!("region start: {}", region.label) + } + + println!("OPCODE : {}", opcode); + + for region in regions_ending { + println!("region end: {}", region.label) + } + } + + self + } + /// Returns the current witness index. pub(crate) fn current_witness_index(&self) -> Witness { Witness(self.current_witness_index) diff --git a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs index 07c78b2a377..84388bb2913 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -92,6 +92,7 @@ impl Context { /// Converts an SSA instruction into its ACIR representation fn convert_ssa_instruction(&mut self, instruction_id: InstructionId, dfg: &DataFlowGraph) { let instruction = &dfg[instruction_id]; + self.acir_context.acir_ir.start_region_label(format!("{instruction:?}")); match instruction { Instruction::Binary(binary) => { let result_acir_var = self.convert_ssa_binary(binary, dfg); @@ -101,6 +102,7 @@ impl Context { } _ => todo!(), } + self.acir_context.acir_ir.end_label(); } /// Converts an SSA terminator's return values into their ACIR representations @@ -110,7 +112,8 @@ impl Context { _ => unreachable!("ICE: Program must have a singular return"), }; - let is_return_unit_type = return_values.len() == 1 && dfg.type_of_value(return_values[0]) == Type::Unit; + let is_return_unit_type = + return_values.len() == 1 && dfg.type_of_value(return_values[0]) == Type::Unit; if is_return_unit_type { return; }