diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Nargo.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Nargo.toml new file mode 100644 index 00000000000..e0b467ce5da --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Nargo.toml @@ -0,0 +1,5 @@ +[package] +authors = [""] +compiler_version = "0.1" + +[dependencies] \ No newline at end of file diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Prover.toml b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Prover.toml new file mode 100644 index 00000000000..07890234a19 --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/Prover.toml @@ -0,0 +1 @@ +x = "3" diff --git a/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/src/main.nr b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/src/main.nr new file mode 100644 index 00000000000..d84be844d8e --- /dev/null +++ b/crates/nargo_cli/tests/test_data_ssa_refactor/distinct_keyword/src/main.nr @@ -0,0 +1,4 @@ +// Example that uses the distinct keyword +fn main(x: pub Field) -> distinct pub [Field;2] { + [x+1, x] +} diff --git a/crates/noirc_evaluator/src/ssa_refactor.rs b/crates/noirc_evaluator/src/ssa_refactor.rs index ee76b55c7d3..26be4708fac 100644 --- a/crates/noirc_evaluator/src/ssa_refactor.rs +++ b/crates/noirc_evaluator/src/ssa_refactor.rs @@ -33,6 +33,7 @@ pub(crate) fn optimize_into_acir( allow_log_ops: bool, print_ssa_passes: bool, ) -> GeneratedAcir { + let abi_distinctness = program.return_distinctness; let ssa = ssa_gen::generate_ssa(program).print(print_ssa_passes, "Initial SSA:"); let brillig = ssa.to_brillig(); ssa.inline_functions() @@ -49,7 +50,7 @@ pub(crate) fn optimize_into_acir( .print(print_ssa_passes, "After Constant Folding:") .dead_instruction_elimination() .print(print_ssa_passes, "After Dead Instruction Elimination:") - .into_acir(brillig, allow_log_ops) + .into_acir(brillig, abi_distinctness, allow_log_ops) } /// Compiles the Program into ACIR and applies optimizations to the arithmetic gates 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 47ae9154a77..67b2ce984d9 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 @@ -73,7 +73,7 @@ impl GeneratedAcir { /// This means you cannot multiply an infinite amount of `Expression`s together. /// Once the `Expression` goes over degree-2, then it needs to be reduced to a `Witness` /// which has degree-1 in order to be able to continue the multiplication chain. - fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { + pub(crate) fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { let fresh_witness = self.next_witness_index(); // Create a constraint that sets them to be equal to each other 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 a7e4e8489bc..7fcc0472760 100644 --- a/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs +++ b/crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs @@ -21,10 +21,11 @@ use super::{ }, ssa_gen::Ssa, }; -use acvm::FieldElement; +use acvm::{acir::native_types::Expression, FieldElement}; use iter_extended::vecmap; pub(crate) use acir_ir::generated_acir::GeneratedAcir; +use noirc_abi::AbiDistinctness; mod acir_ir; @@ -71,9 +72,34 @@ impl AcirValue { } impl Ssa { - pub(crate) fn into_acir(self, brillig: Brillig, allow_log_ops: bool) -> GeneratedAcir { + pub(crate) fn into_acir( + self, + brillig: Brillig, + abi_distinctness: AbiDistinctness, + allow_log_ops: bool, + ) -> GeneratedAcir { let context = Context::default(); - context.convert_ssa(self, brillig, allow_log_ops) + let mut generated_acir = context.convert_ssa(self, brillig, allow_log_ops); + + match abi_distinctness { + AbiDistinctness::Distinct => { + // Create a witness for each return witness we have + // to guarantee that the return witnesses are distinct + let distinct_return_witness: Vec<_> = generated_acir + .return_witnesses + .clone() + .into_iter() + .map(|return_witness| { + generated_acir + .create_witness_for_expression(&Expression::from(return_witness)) + }) + .collect(); + + generated_acir.return_witnesses = distinct_return_witness; + generated_acir + } + AbiDistinctness::DuplicationAllowed => generated_acir, + } } }