From 5884ff68004165f36dbc15825bfaa6e3252027e5 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:01:20 -0300 Subject: [PATCH 01/25] chore: print ACIR AssertZero as an equation --- acvm-repo/acir/src/circuit/mod.rs | 2 +- acvm-repo/acir/src/circuit/opcodes.rs | 37 +++- acvm-repo/acir/src/parser/lexer.rs | 3 + acvm-repo/acir/src/parser/mod.rs | 73 ++++++- acvm-repo/acir/src/parser/tests.rs | 206 +++++++++--------- acvm-repo/acir/src/parser/token.rs | 9 + .../acvm/src/compiler/optimizers/general.rs | 12 +- .../compiler/optimizers/merge_expressions.rs | 4 +- .../compiler/optimizers/redundant_range.rs | 12 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 72 +++--- .../src/acir/tests/brillig_call.rs | 58 ++--- .../noirc_evaluator/src/acir/tests/call.rs | 30 +-- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 13 files changed, 317 insertions(+), 203 deletions(-) diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 35b8f7440dd..1dd1e2f8bb0 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -544,7 +544,7 @@ mod tests { private parameters: [] public parameters: [w2] return values: [w2] - EXPR [ (2, w1) 8 ] + EXPR 2*w1 + 8 = 0 BLACKBOX::RANGE [w1]:8 bits [] BLACKBOX::AND [w1, w2]:4 bits [w3] BLACKBOX::KECCAKF1600 [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index f8962bad9bf..3a169e535f2 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -146,16 +146,47 @@ pub enum Opcode { impl std::fmt::Display for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Opcode::AssertZero(expr) => expr.fmt(f), + Opcode::AssertZero(expr) => { + write!(f, "EXPR ")?; + + let mut printed_term = false; + + for (coefficient, witness1, witness2) in &expr.mul_terms { + if printed_term { + write!(f, " + ")?; + } + + write!(f, "{coefficient}*{witness1}*{witness2}")?; + printed_term = true; + } + + for (coefficient, witness) in &expr.linear_combinations { + if printed_term { + write!(f, " + ")?; + } + + write!(f, "{coefficient}*{witness}")?; + printed_term = true; + } + + if printed_term { + write!(f, " + ")?; + } + + write!(f, "{}", expr.q_c)?; + write!(f, " = 0")?; + + Ok(()) + } Opcode::BlackBoxFuncCall(g) => g.fmt(f), Opcode::MemoryOp { block_id, op } => { write!(f, "MEM ")?; let is_read = op.operation.is_zero(); if is_read { - write!(f, "(id: {}, read at: {}, value: {}) ", block_id.0, op.index, op.value) + write!(f, "(id: {}, read at: {}, value: {})", block_id.0, op.index, op.value) } else { - write!(f, "(id: {}, write {} at: {}) ", block_id.0, op.value, op.index) + write!(f, "(id: {}, write {} at: {})", block_id.0, op.value, op.index) } } Opcode::MemoryInit { block_id, init, block_type: databus } => { diff --git a/acvm-repo/acir/src/parser/lexer.rs b/acvm-repo/acir/src/parser/lexer.rs index 4049980789c..c30b5badbd7 100644 --- a/acvm-repo/acir/src/parser/lexer.rs +++ b/acvm-repo/acir/src/parser/lexer.rs @@ -64,6 +64,9 @@ impl<'a> Lexer<'a> { ',' => self.single_char_token(Token::Comma), ':' => self.single_char_token(Token::Colon), ';' => self.single_char_token(Token::Semicolon), + '+' => self.single_char_token(Token::Plus), + '*' => self.single_char_token(Token::Star), + '=' => self.single_char_token(Token::Equal), 'w' if self.peek_char().is_some_and(|char| char.is_ascii_digit()) => { let start = self.position; diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 0325d7f7c98..2fe2deb6323 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -235,7 +235,7 @@ impl<'a> Parser<'a> { while let Some(keyword) = self.peek_keyword() { match keyword { Keyword::Expression => { - let expr = self.parse_arithmetic_expression()?; + let expr = self.parse_assert_zero_expression()?; opcodes.push(Opcode::AssertZero(expr)); } Keyword::BlackBoxFuncCall => { @@ -260,8 +260,76 @@ impl<'a> Parser<'a> { Ok(opcodes) } + fn parse_assert_zero_expression(&mut self) -> ParseResult> { + self.eat_keyword_or_error(Keyword::Expression)?; + + // Support the old `EXPR [ ... ]` syntax for old tests, for now + if matches!(self.token.token(), Token::LeftBracket) { + return self.parse_arithmetic_expression_after_expr(); + } + + let mut linear_combinations = Vec::new(); + let mut mul_terms = Vec::new(); + let mut constant: Option = None; + + loop { + let Some(coefficient) = self.eat_field_element()? else { + return self.expected_field_element(); + }; + + if self.eat(Token::Star)? { + let w1 = self.eat_witness_or_error()?; + + if self.eat(Token::Star)? { + let w2 = self.eat_witness_or_error()?; + mul_terms.push((coefficient, w1, w2)); + } else { + linear_combinations.push((coefficient, w1)); + } + } else { + if constant.is_some() { + return Err(ParserError::DuplicatedConstantTerm { + found: self.token.token().clone(), + span: self.token.span(), + }); + } + constant = Some(coefficient); + } + + if self.eat(Token::Plus)? { + continue; + } + + if self.eat(Token::Equal)? { + break; + } + + return self.expected_token(Token::Equal); + } + + let zero_token = self.token.token().clone(); + let span = self.token.span(); + let Some(zero) = self.eat_field_element()? else { + return self.expected_field_element(); + }; + + if !zero.is_zero() { + return Err(ParserError::ExpectedZero { found: zero_token, span }); + } + + let Some(q_c) = constant else { + return Err(ParserError::MissingConstantTerm { span: self.token.span() }); + }; + + Ok(Expression { mul_terms, linear_combinations, q_c }) + } + fn parse_arithmetic_expression(&mut self) -> ParseResult> { self.eat_keyword_or_error(Keyword::Expression)?; + self.parse_arithmetic_expression_after_expr() + } + + fn parse_arithmetic_expression_after_expr(&mut self) -> ParseResult> { self.eat_or_error(Token::LeftBracket)?; let mut linear_combinations = Vec::new(); @@ -1014,6 +1082,8 @@ pub(crate) enum ParserError { ExpectedFieldElement { found: Token, span: Span }, #[error("Expected a witness index, found '{found}'")] ExpectedWitness { found: Token, span: Span }, + #[error("Expected a zero, found '{found}'")] + ExpectedZero { found: Token, span: Span }, #[error("Duplicate constant term in native Expression")] DuplicatedConstantTerm { found: Token, span: Span }, #[error("Missing constant term in native Expression")] @@ -1042,6 +1112,7 @@ impl ParserError { | ExpectedIdentifier { span, .. } | ExpectedFieldElement { span, .. } | ExpectedWitness { span, .. } + | ExpectedZero { span, .. } | DuplicatedConstantTerm { span, .. } | MissingConstantTerm { span } | ExpectedBlackBoxFuncName { span, .. } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index d6a13336af2..f28a2a9eb85 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -102,11 +102,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR [ (1, w0) (-1, w5) 0 ] - EXPR [ (1, w1) (-1, w6) 0 ] - EXPR [ (1, w2) (-1, w7) 0 ] - EXPR [ (1, w3) (-1, w8) 0 ] - EXPR [ (1, w4) (-1, w9) 0 ] + EXPR 1*w0 + -1*w5 + 0 = 0 + EXPR 1*w1 + -1*w6 + 0 = 0 + EXPR 1*w2 + -1*w7 + 0 = 0 + EXPR 1*w3 + -1*w8 + 0 = 0 + EXPR 1*w4 + -1*w9 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -118,11 +118,11 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR [ (1, w0, w1) (-1, w3) 0 ] - EXPR [ (1, w3, w3) (-1, w4) 0 ] - EXPR [ (1, w4, w4) (-1, w5) 0 ] - EXPR [ (1, w5, w5) (-1, w6) 0 ] - EXPR [ (-1, w2) (1, w6) 0 ] + EXPR 1*w0*w1 + -1*w3 + 0 = 0 + EXPR 1*w3*w3 + -1*w4 + 0 = 0 + EXPR 1*w4*w4 + -1*w5 + 0 = 0 + EXPR 1*w5*w5 + -1*w6 + 0 = 0 + EXPR -1*w2 + 1*w6 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -149,7 +149,7 @@ fn xor() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::XOR [w0, w1]:32 bits [w2] - EXPR [ (1, w2) -15 ] + EXPR 1*w2 + -15 = 0 "; assert_circuit_roundtrip(src); } @@ -223,22 +223,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR [ (-1, w44) (1, w60) 0 ] - EXPR [ (-1, w45) (1, w61) 0 ] - EXPR [ (-1, w46) (1, w62) 0 ] - EXPR [ (-1, w47) (1, w63) 0 ] - EXPR [ (-1, w48) (1, w64) 0 ] - EXPR [ (-1, w49) (1, w65) 0 ] - EXPR [ (-1, w50) (1, w66) 0 ] - EXPR [ (-1, w51) (1, w67) 0 ] - EXPR [ (-1, w52) (1, w68) 0 ] - EXPR [ (-1, w53) (1, w69) 0 ] - EXPR [ (-1, w54) (1, w70) 0 ] - EXPR [ (-1, w55) (1, w71) 0 ] - EXPR [ (-1, w56) (1, w72) 0 ] - EXPR [ (-1, w57) (1, w73) 0 ] - EXPR [ (-1, w58) (1, w74) 0 ] - EXPR [ (-1, w59) (1, w75) 0 ] + EXPR -1*w44 + 1*w60 + 0 = 0 + EXPR -1*w45 + 1*w61 + 0 = 0 + EXPR -1*w46 + 1*w62 + 0 = 0 + EXPR -1*w47 + 1*w63 + 0 = 0 + EXPR -1*w48 + 1*w64 + 0 = 0 + EXPR -1*w49 + 1*w65 + 0 = 0 + EXPR -1*w50 + 1*w66 + 0 = 0 + EXPR -1*w51 + 1*w67 + 0 = 0 + EXPR -1*w52 + 1*w68 + 0 = 0 + EXPR -1*w53 + 1*w69 + 0 = 0 + EXPR -1*w54 + 1*w70 + 0 = 0 + EXPR -1*w55 + 1*w71 + 0 = 0 + EXPR -1*w56 + 1*w72 + 0 = 0 + EXPR -1*w57 + 1*w73 + 0 = 0 + EXPR -1*w58 + 1*w74 + 0 = 0 + EXPR -1*w59 + 1*w75 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -463,7 +463,7 @@ fn memory_read() { private parameters: [] public parameters: [] return values: [] - MEM (id: 0, read at: EXPR [ (1, w0) 0 ], value: EXPR [ (1, w1) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w0) 0 ], value: EXPR [ (1, w1) 0 ]) "; assert_circuit_roundtrip(src); } @@ -525,8 +525,8 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w0, w3) (-1, w1, w3) -1 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -540,8 +540,8 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w0, w3) (-1, w1, w3) -1 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -606,97 +606,97 @@ fn array_dynamic() { BLACKBOX::RANGE [w15]:32 bits [] BLACKBOX::RANGE [w16]:32 bits [] BLACKBOX::RANGE [w17]:32 bits [] - EXPR [ (5, w6) (-1, w19) 0 ] + EXPR 5*w6 + -1*w19 + 0 = 0 BLACKBOX::RANGE [w19]:32 bits [] - EXPR [ (1, w5) (-1, w19) (-1, w20) 0 ] + EXPR 1*w5 + -1*w19 + -1*w20 + 0 = 0 BLACKBOX::RANGE [w20]:32 bits [] - EXPR [ (1, w20) (-1, w21) -5 ] - EXPR [ (1, w21) (-1, w22) -3 ] - MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) - EXPR [ (1, w23) -111 ] - MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) - EXPR [ (1, w24) -101 ] + EXPR 1*w20 + -1*w21 + -5 = 0 + EXPR 1*w21 + -1*w22 + -3 = 0 + MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) + EXPR 1*w23 + -111 = 0 + MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) + EXPR 1*w24 + -101 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR [ (1, w22) (-4294967296, w25) (-1, w26) 4294967291 ] - EXPR [ (-1, w25) 0 ] - EXPR [ (-1, w27) 0 ] - MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) - EXPR [ (1, w28) -111 ] - EXPR [ (-1, w29) 1 ] - MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) - EXPR [ (1, w30) 0 ] + EXPR 1*w22 + -4294967296*w25 + -1*w26 + 4294967291 = 0 + EXPR -1*w25 + 0 = 0 + EXPR -1*w27 + 0 = 0 + MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) + EXPR 1*w28 + -111 = 0 + EXPR -1*w29 + 1 = 0 + MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) + EXPR 1*w30 + 0 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR [ (1, w21) (-4294967296, w31) (-1, w32) 4294967286 ] - EXPR [ (-1, w21, w31) (1, w21) (-1, w33) 0 ] - MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) - EXPR [ (-1, w31, w34) (2, w31) (1, w34) (-1, w35) -2 ] + EXPR 1*w21 + -4294967296*w31 + -1*w32 + 4294967286 = 0 + EXPR -1*w21*w31 + 1*w21 + -1*w33 + 0 = 0 + MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) + EXPR -1*w31*w34 + 2*w31 + 1*w34 + -1*w35 + -2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR [ (1, w21) (-4294967296, w36) (-1, w37) 4294967291 ] - EXPR [ (1, w31, w36) (-1, w36) 0 ] - EXPR [ (-1, w21, w31) (1, w21) (-1, w38) 0 ] - MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) - EXPR [ (-1, w42) 2 ] - MEM (id: 0, read at: EXPR [ (1, w42) 0 ], value: EXPR [ (1, w43) 0 ]) - EXPR [ (-1, w44) 3 ] - MEM (id: 0, read at: EXPR [ (1, w44) 0 ], value: EXPR [ (1, w45) 0 ]) - EXPR [ (-1, w46) 4 ] - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) + EXPR 1*w21 + -4294967296*w36 + -1*w37 + 4294967291 = 0 + EXPR 1*w31*w36 + -1*w36 + 0 = 0 + EXPR -1*w21*w31 + 1*w21 + -1*w38 + 0 = 0 + MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) + EXPR -1*w42 + 2 = 0 + MEM (id: 0, read at: EXPR [ (1, w42) 0 ], value: EXPR [ (1, w43) 0 ]) + EXPR -1*w44 + 3 = 0 + MEM (id: 0, read at: EXPR [ (1, w44) 0 ], value: EXPR [ (1, w45) 0 ]) + EXPR -1*w46 + 4 = 0 + MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR [ (-1, w31, w35) (1, w31, w39) (1, w35) (-1, w48) 0 ] - MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) - MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) - EXPR [ (-1, w31, w36) 0 ] - EXPR [ (1, w21, w31) (-1, w51) 0 ] - MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) - EXPR [ (-1, w31, w52) (1, w52) (-1, w53) 0 ] - MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) - EXPR [ (-1, w31) (-1, w55) 1 ] - EXPR [ (-1, w31, w49) (1, w31, w50) (1, w49) (-1, w56) 0 ] - EXPR [ (1, w31, w54) (1, w55, w56) -109 ] - EXPR [ (-1, w57) 246 ] - EXPR [ (-1, w58) 159 ] - EXPR [ (-1, w59) 32 ] - EXPR [ (-1, w60) 176 ] - EXPR [ (-1, w61) 8 ] + EXPR -1*w31*w35 + 1*w31*w39 + 1*w35 + -1*w48 + 0 = 0 + MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) + MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) + EXPR -1*w31*w36 + 0 = 0 + EXPR 1*w21*w31 + -1*w51 + 0 = 0 + MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) + EXPR -1*w31*w52 + 1*w52 + -1*w53 + 0 = 0 + MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) + EXPR -1*w31 + -1*w55 + 1 = 0 + EXPR -1*w31*w49 + 1*w31*w50 + 1*w49 + -1*w56 + 0 = 0 + EXPR 1*w31*w54 + 1*w55*w56 + -109 = 0 + EXPR -1*w57 + 246 = 0 + EXPR -1*w58 + 159 = 0 + EXPR -1*w59 + 32 = 0 + EXPR -1*w60 + 176 = 0 + EXPR -1*w61 + 8 = 0 INIT (id: 4, len: 5, witnesses: [w57, w58, w59, w60, w61]) - MEM (id: 4, read at: EXPR [ (1, w7) 0 ], value: EXPR [ (1, w62) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w63) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w9) 0 ], value: EXPR [ (1, w64) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w65) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w66) 0 ]) + MEM (id: 4, read at: EXPR [ (1, w7) 0 ], value: EXPR [ (1, w62) 0 ]) + MEM (id: 4, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w63) 0 ]) + MEM (id: 4, read at: EXPR [ (1, w9) 0 ], value: EXPR [ (1, w64) 0 ]) + MEM (id: 4, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w65) 0 ]) + MEM (id: 4, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w66) 0 ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) 0 ]], outputs: [w67] - EXPR [ (1, w62, w67) (1, w63, w67) (1, w64, w67) (1, w65, w67) (1, w66, w67) -1 ] + EXPR 1*w62*w67 + 1*w63*w67 + 1*w64*w67 + 1*w65*w67 + 1*w66*w67 + -1 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] - EXPR [ (1, w18) (-4294967296, w68) (-1, w69) 0 ] - EXPR [ (-1, w68) (-1, w70) 5096253676302562286669017222071363378443840053029366383258766538131 ] + EXPR 1*w18 + -4294967296*w68 + -1*w69 + 0 = 0 + EXPR -1*w68 + -1*w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR [ (-1, w68, w71) (5096253676302562286669017222071363378443840053029366383258766538131, w71) (1, w72) -1 ] - EXPR [ (-1, w68, w72) (5096253676302562286669017222071363378443840053029366383258766538131, w72) 0 ] - EXPR [ (1, w69, w72) (268435455, w72) (-1, w73) 0 ] + EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + 1*w72 + -1 = 0 + EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 + 0 = 0 + EXPR 1*w69*w72 + 268435455*w72 + -1*w73 + 0 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR [ (-1, w69) (-4294967296, w74) (-1, w75) 4294967299 ] - EXPR [ (-1, w17, w74) (1, w17) (-3, w74) (-1, w76) 3 ] + EXPR -1*w69 + -4294967296*w74 + -1*w75 + 4294967299 = 0 + EXPR -1*w17*w74 + 1*w17 + -3*w74 + -1*w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] - EXPR [ (-1, w74, w76) (1, w76) (-1, w77) 0 ] - MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) - EXPR [ (1, w15, w74) (-1, w74, w78) (-1, w15) (1, w78) 0 ] + EXPR -1*w74*w76 + 1*w76 + -1*w77 + 0 = 0 + MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) + EXPR 1*w15*w74 + -1*w74*w78 + -1*w15 + 1*w78 + 0 = 0 "; assert_circuit_roundtrip(src); } @@ -711,15 +711,15 @@ fn fold_basic() { return values: [] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w2] - + func 1 current witness: w3 private parameters: [w0, w1] public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w0, w3) (-1, w1, w3) -1 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "; assert_program_roundtrip(src); } @@ -734,7 +734,7 @@ fn fold_basic_mismatched_ids() { return values: [] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w2] - + func 2 current witness: w3 private parameters: [w0, w1] diff --git a/acvm-repo/acir/src/parser/token.rs b/acvm-repo/acir/src/parser/token.rs index 8bd00af391f..b8fb6f4fd97 100644 --- a/acvm-repo/acir/src/parser/token.rs +++ b/acvm-repo/acir/src/parser/token.rs @@ -48,6 +48,12 @@ pub(crate) enum Token { LeftParen, /// ) RightParen, + /// + + Plus, + /// * + Star, + /// = + Equal, Eof, } @@ -75,6 +81,9 @@ impl std::fmt::Display for Token { Token::RightBracket => write!(f, "]"), Token::LeftParen => write!(f, "("), Token::RightParen => write!(f, ")"), + Token::Plus => write!(f, "+"), + Token::Star => write!(f, "*"), + Token::Equal => write!(f, "="), Token::Eof => write!(f, "(end of stream)"), } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index 41ccc1e6dec..fa7b98cdcb5 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -102,7 +102,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (1, w0, w1) 0 ] + EXPR 1*w0*w1 + 0 = 0 "); } @@ -124,7 +124,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (1, w1) 0 ] + EXPR 1*w1 + 0 = 0 "); } @@ -147,7 +147,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (9, w0, w1) 0 ] + EXPR 9*w0*w1 + 0 = 0 "); } @@ -167,7 +167,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ 0 ] + EXPR 0 = 0 "); } @@ -190,7 +190,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (6, w0) 0 ] + EXPR 6*w0 + 0 = 0 "); } @@ -210,7 +210,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ 0 ] + EXPR 0 = 0 "); } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index d574f8dd6d8..308c8e421aa 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,8 +348,8 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (1, w0, w1) (1, w5) 0 ] - EXPR [ (2, w0, w0) (-1, w3) (2, w5) 0 ] + EXPR 1*w0*w1 + 1*w5 + 0 = 0 + EXPR 2*w0*w0 + -1*w3 + 2*w5 + 0 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 38e743400a1..b1bb893065a 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -366,10 +366,10 @@ mod tests { public parameters: [] return values: [] BLACKBOX::RANGE [w1]:16 bits [] - EXPR [ 0 ] - EXPR [ 0 ] - EXPR [ 0 ] - EXPR [ 0 ] + EXPR 0 = 0 + EXPR 0 = 0 + EXPR 0 = 0 + EXPR 0 = 0 "); } @@ -395,7 +395,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - EXPR [ (1, w1) 0 ] + EXPR 1*w1 + 0 = 0 "); } @@ -444,7 +444,7 @@ mod tests { BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] BLACKBOX::RANGE [w1]:16 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] - EXPR [ (1, w1) 0 ] + EXPR 1*w1 + 0 = 0 "); // Applying again should have no effect (despite the range having the same bit size as the assert). diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index f45df4b61d8..1abcf3834d4 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -49,12 +49,12 @@ fn constant_array_access_out_of_bounds() { private parameters: [] public parameters: [] return values: [] - EXPR [ (-1, w0) 0 ] - EXPR [ (-1, w1) 1 ] + EXPR -1*w0 + 0 = 0 + EXPR -1*w1 + 1 = 0 INIT (id: 0, len: 2, witnesses: [w0, w1]) - EXPR [ (-1, w2) 5 ] - MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) - EXPR [ (1, w3) 0 ] + EXPR -1*w2 + 5 = 0 + MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) + EXPR 1*w3 + 0 = 0 "); } @@ -96,8 +96,8 @@ fn generates_memory_op_for_dynamic_read() { public parameters: [] return values: [] INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) - MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) - EXPR [ (1, w4) -10 ] + MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) + EXPR 1*w4 + -10 = 0 "); } @@ -120,17 +120,17 @@ fn generates_memory_op_for_dynamic_write() { public parameters: [] return values: [w4, w5, w6] INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR [ (-1, w7) 10 ] - MEM (id: 1, write EXPR [ (1, w7) 0 ] at: EXPR [ (1, w3) 0 ]) - EXPR [ (-1, w8) 0 ] - MEM (id: 1, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) - EXPR [ (-1, w10) 1 ] - MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) - EXPR [ (-1, w12) 2 ] - MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) - EXPR [ (1, w4) (-1, w9) 0 ] - EXPR [ (1, w5) (-1, w11) 0 ] - EXPR [ (1, w6) (-1, w13) 0 ] + EXPR -1*w7 + 10 = 0 + MEM (id: 1, write EXPR [ (1, w7) 0 ] at: EXPR [ (1, w3) 0 ]) + EXPR -1*w8 + 0 = 0 + MEM (id: 1, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) + EXPR -1*w10 + 1 = 0 + MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) + EXPR -1*w12 + 2 = 0 + MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) + EXPR 1*w4 + -1*w9 + 0 = 0 + EXPR 1*w5 + -1*w11 + 0 = 0 + EXPR 1*w6 + -1*w13 + 0 = 0 "); } @@ -161,9 +161,9 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR [ (1, w3, w4) (-1, w5) 0 ] - MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) - EXPR [ (1, w6) -10 ] + EXPR 1*w3*w4 + -1*w5 + 0 = 0 + MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) + EXPR 1*w6 + -10 = 0 "); } @@ -199,20 +199,20 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR [ (1, w3, w4) (-1, w8) 0 ] - MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) + EXPR 1*w3*w4 + -1*w8 + 0 = 0 + MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR [ (-1, w4, w9) (10, w4) (1, w9) (-1, w10) 0 ] - MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) - EXPR [ (-1, w11) 0 ] - MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) - EXPR [ (-1, w13) 1 ] - MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) - EXPR [ (-1, w15) 2 ] - MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) - EXPR [ (1, w5) (-1, w12) 0 ] - EXPR [ (1, w6) (-1, w14) 0 ] - EXPR [ (1, w7) (-1, w16) 0 ] + EXPR -1*w4*w9 + 10*w4 + 1*w9 + -1*w10 + 0 = 0 + MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) + EXPR -1*w11 + 0 = 0 + MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) + EXPR -1*w13 + 1 = 0 + MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) + EXPR -1*w15 + 2 = 0 + MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) + EXPR 1*w5 + -1*w12 + 0 = 0 + EXPR 1*w6 + -1*w14 + 0 = 0 + EXPR 1*w7 + -1*w16 + 0 = 0 "); } @@ -237,7 +237,7 @@ fn zero_length_array_constant() { private parameters: [] public parameters: [] return values: [] - EXPR [ 1 ] + EXPR 1 = 0 "); } @@ -264,6 +264,6 @@ fn zero_length_array_dynamic_predicate() { private parameters: [w0] public parameters: [] return values: [] - EXPR [ (1, w0) 0 ] + EXPR 1*w0 + 0 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index e0cd71fc08c..dc7ce82389e 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,22 +153,22 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w1, w3) -1 ] + EXPR 1*w1*w3 + -1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] + EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] - EXPR [ (-1, w2) (1, w4) 0 ] + EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 + EXPR -1*w2 + 1*w4 + 0 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] - EXPR [ (1, w2, w7) -1 ] + EXPR 1*w2*w7 + -1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR [ (1, w2) (-1, w9) (-1, w10) -1 ] + EXPR 1*w2 + -1*w9 + -1*w10 + -1 = 0 BLACKBOX::RANGE [w10]:32 bits [] - EXPR [ (-1, w2, w8) (1, w1) (-1, w9) 0 ] - EXPR [ (1, w8) -1 ] + EXPR -1*w2*w8 + 1*w1 + -1*w9 + 0 = 0 + EXPR 1*w8 + -1 = 0 unconstrained func 0 0: @21 = const u32 1 @@ -241,26 +241,26 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w1, w3) -1 ] + EXPR 1*w1*w3 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] + EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] - EXPR [ (-1, w2) (1, w4) 0 ] + EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 + EXPR -1*w2 + 1*w4 + 0 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w9] - EXPR [ (1, w2, w9) -1 ] + EXPR 1*w2*w9 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR [ (1, w2) (-1, w11) (-1, w12) -1 ] + EXPR 1*w2 + -1*w11 + -1*w12 + -1 = 0 BLACKBOX::RANGE [w12]:32 bits [] - EXPR [ (-1, w2, w10) (1, w1) (-1, w11) 0 ] - EXPR [ (1, w10) -1 ] + EXPR -1*w2*w10 + 1*w1 + -1*w11 + 0 = 0 + EXPR 1*w10 + -1 = 0 unconstrained func 0 0: @2 = const u32 1 @@ -375,14 +375,14 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w1, w3) -1 ] + EXPR 1*w1*w3 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR [ (1, w1) (-1, w5) (-1, w6) -1 ] + EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR [ (-1, w1, w4) (1, w0) (-1, w5) 0 ] - EXPR [ (-1, w2) (1, w4) 0 ] + EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 + EXPR -1*w2 + 1*w4 + 0 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -390,13 +390,13 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w10] - EXPR [ (1, w2, w10) -1 ] + EXPR 1*w2*w10 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR [ (1, w2) (-1, w12) (-1, w13) -1 ] + EXPR 1*w2 + -1*w12 + -1*w13 + -1 = 0 BLACKBOX::RANGE [w13]:32 bits [] - EXPR [ (-1, w2, w11) (1, w1) (-1, w12) 0 ] - EXPR [ (1, w11) -1 ] + EXPR -1*w2*w11 + 1*w1 + -1*w12 + 0 = 0 + EXPR 1*w11 + -1 = 0 func 1 current witness: w5 @@ -405,12 +405,12 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR [ (1, w0) (-1, w1) (-1, w3) 0 ] + EXPR 1*w0 + -1*w1 + -1*w3 + 0 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] - EXPR [ (1, w3, w4) (1, w5) -1 ] - EXPR [ (1, w3, w5) 0 ] - EXPR [ (1, w5) 0 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w3*w4 + 1*w5 + -1 = 0 + EXPR 1*w3*w5 + 0 = 0 + EXPR 1*w5 + 0 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 5424d82abb3..990bf406ee7 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,15 +64,15 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR [ (1, w2) (-1, w3) 0 ] - + EXPR 1*w2 + -1*w3 + 0 = 0 + func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR [ (1, w0) (-1, w1) 0 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0 + -1*w1 + 0 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "); } @@ -107,15 +107,15 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR [ (1, w2) (-1, w3) 0 ] - + EXPR 1*w2 + -1*w3 + 0 = 0 + func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR [ (1, w0) (-1, w1) 0 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0 + -1*w1 + 0 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "); } @@ -154,24 +154,24 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR [ (1, w2) (-1, w3) 0 ] - + EXPR 1*w2 + -1*w3 + 0 = 0 + func 1 current witness: w4 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR [ (1, w0) (-1, w3) 2 ] + EXPR 1*w0 + -1*w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR [ (1, w2) (-1, w4) 0 ] - + EXPR 1*w2 + -1*w4 + 0 = 0 + func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR [ (1, w0) (-1, w1) 0 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR 1*w0 + -1*w1 + 0 = 0 + EXPR -1*w0 + 1*w2 + 0 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index 49620a12b2b..f47659e7104 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR [ (-1, w0, w1) (1, w2) 0 ] + EXPR -1*w0*w1 + 1*w2 + 0 = 0 "); } From 6fb656bafb253ede3212c0056bbda3411c412b2a Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:11:04 -0300 Subject: [PATCH 02/25] Omit zero coefficients --- acvm-repo/acir/src/circuit/opcodes.rs | 10 +- acvm-repo/acir/src/parser/mod.rs | 5 +- acvm-repo/acir/src/parser/tests.rs | 94 +++++++++---------- .../acvm/src/compiler/optimizers/general.rs | 8 +- .../compiler/optimizers/merge_expressions.rs | 4 +- .../compiler/optimizers/redundant_range.rs | 4 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 28 +++--- .../src/acir/tests/brillig_call.rs | 26 ++--- .../noirc_evaluator/src/acir/tests/call.rs | 20 ++-- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 10 files changed, 102 insertions(+), 99 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 3a169e535f2..5e32fd26f8d 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -169,11 +169,15 @@ impl std::fmt::Display for Opcode { printed_term = true; } - if printed_term { - write!(f, " + ")?; + if !expr.q_c.is_zero() + || (expr.mul_terms.is_empty() && expr.linear_combinations.is_empty()) + { + if printed_term { + write!(f, " + ")?; + } + write!(f, "{}", expr.q_c)?; } - write!(f, "{}", expr.q_c)?; write!(f, " = 0")?; Ok(()) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 2fe2deb6323..b348c923523 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -317,9 +317,8 @@ impl<'a> Parser<'a> { return Err(ParserError::ExpectedZero { found: zero_token, span }); } - let Some(q_c) = constant else { - return Err(ParserError::MissingConstantTerm { span: self.token.span() }); - }; + // If a constant isn't provided, we default it to zero + let q_c = constant.unwrap_or_default(); Ok(Expression { mul_terms, linear_combinations, q_c }) } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index f28a2a9eb85..8224a759c8c 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -102,11 +102,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR 1*w0 + -1*w5 + 0 = 0 - EXPR 1*w1 + -1*w6 + 0 = 0 - EXPR 1*w2 + -1*w7 + 0 = 0 - EXPR 1*w3 + -1*w8 + 0 = 0 - EXPR 1*w4 + -1*w9 + 0 = 0 + EXPR 1*w0 + -1*w5 = 0 + EXPR 1*w1 + -1*w6 = 0 + EXPR 1*w2 + -1*w7 = 0 + EXPR 1*w3 + -1*w8 = 0 + EXPR 1*w4 + -1*w9 = 0 "; assert_circuit_roundtrip(src); } @@ -118,11 +118,11 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR 1*w0*w1 + -1*w3 + 0 = 0 - EXPR 1*w3*w3 + -1*w4 + 0 = 0 - EXPR 1*w4*w4 + -1*w5 + 0 = 0 - EXPR 1*w5*w5 + -1*w6 + 0 = 0 - EXPR -1*w2 + 1*w6 + 0 = 0 + EXPR 1*w0*w1 + -1*w3 = 0 + EXPR 1*w3*w3 + -1*w4 = 0 + EXPR 1*w4*w4 + -1*w5 = 0 + EXPR 1*w5*w5 + -1*w6 = 0 + EXPR -1*w2 + 1*w6 = 0 "; assert_circuit_roundtrip(src); } @@ -223,22 +223,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR -1*w44 + 1*w60 + 0 = 0 - EXPR -1*w45 + 1*w61 + 0 = 0 - EXPR -1*w46 + 1*w62 + 0 = 0 - EXPR -1*w47 + 1*w63 + 0 = 0 - EXPR -1*w48 + 1*w64 + 0 = 0 - EXPR -1*w49 + 1*w65 + 0 = 0 - EXPR -1*w50 + 1*w66 + 0 = 0 - EXPR -1*w51 + 1*w67 + 0 = 0 - EXPR -1*w52 + 1*w68 + 0 = 0 - EXPR -1*w53 + 1*w69 + 0 = 0 - EXPR -1*w54 + 1*w70 + 0 = 0 - EXPR -1*w55 + 1*w71 + 0 = 0 - EXPR -1*w56 + 1*w72 + 0 = 0 - EXPR -1*w57 + 1*w73 + 0 = 0 - EXPR -1*w58 + 1*w74 + 0 = 0 - EXPR -1*w59 + 1*w75 + 0 = 0 + EXPR -1*w44 + 1*w60 = 0 + EXPR -1*w45 + 1*w61 = 0 + EXPR -1*w46 + 1*w62 = 0 + EXPR -1*w47 + 1*w63 = 0 + EXPR -1*w48 + 1*w64 = 0 + EXPR -1*w49 + 1*w65 = 0 + EXPR -1*w50 + 1*w66 = 0 + EXPR -1*w51 + 1*w67 = 0 + EXPR -1*w52 + 1*w68 = 0 + EXPR -1*w53 + 1*w69 = 0 + EXPR -1*w54 + 1*w70 = 0 + EXPR -1*w55 + 1*w71 = 0 + EXPR -1*w56 + 1*w72 = 0 + EXPR -1*w57 + 1*w73 = 0 + EXPR -1*w58 + 1*w74 = 0 + EXPR -1*w59 + 1*w75 = 0 "; assert_circuit_roundtrip(src); } @@ -526,7 +526,7 @@ fn brillig_call() { return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR -1*w0 + 1*w2 = 0 "; assert_circuit_roundtrip(src); } @@ -541,7 +541,7 @@ fn brillig_call_with_predicate() { BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR -1*w0 + 1*w2 = 0 "; assert_circuit_roundtrip(src); } @@ -606,9 +606,9 @@ fn array_dynamic() { BLACKBOX::RANGE [w15]:32 bits [] BLACKBOX::RANGE [w16]:32 bits [] BLACKBOX::RANGE [w17]:32 bits [] - EXPR 5*w6 + -1*w19 + 0 = 0 + EXPR 5*w6 + -1*w19 = 0 BLACKBOX::RANGE [w19]:32 bits [] - EXPR 1*w5 + -1*w19 + -1*w20 + 0 = 0 + EXPR 1*w5 + -1*w19 + -1*w20 = 0 BLACKBOX::RANGE [w20]:32 bits [] EXPR 1*w20 + -1*w21 + -5 = 0 EXPR 1*w21 + -1*w22 + -3 = 0 @@ -619,19 +619,19 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] EXPR 1*w22 + -4294967296*w25 + -1*w26 + 4294967291 = 0 - EXPR -1*w25 + 0 = 0 - EXPR -1*w27 + 0 = 0 + EXPR -1*w25 = 0 + EXPR -1*w27 = 0 MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) EXPR 1*w28 + -111 = 0 EXPR -1*w29 + 1 = 0 MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) - EXPR 1*w30 + 0 = 0 + EXPR 1*w30 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] EXPR 1*w21 + -4294967296*w31 + -1*w32 + 4294967286 = 0 - EXPR -1*w21*w31 + 1*w21 + -1*w33 + 0 = 0 + EXPR -1*w21*w31 + 1*w21 + -1*w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) EXPR -1*w31*w34 + 2*w31 + 1*w34 + -1*w35 + -2 = 0 BLACKBOX::RANGE [w35]:32 bits [] @@ -639,8 +639,8 @@ fn array_dynamic() { BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] EXPR 1*w21 + -4294967296*w36 + -1*w37 + 4294967291 = 0 - EXPR 1*w31*w36 + -1*w36 + 0 = 0 - EXPR -1*w21*w31 + 1*w21 + -1*w38 + 0 = 0 + EXPR 1*w31*w36 + -1*w36 = 0 + EXPR -1*w21*w31 + 1*w21 + -1*w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) @@ -651,18 +651,18 @@ fn array_dynamic() { EXPR -1*w46 + 4 = 0 MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR -1*w31*w35 + 1*w31*w39 + 1*w35 + -1*w48 + 0 = 0 + EXPR -1*w31*w35 + 1*w31*w39 + 1*w35 + -1*w48 = 0 MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) - EXPR -1*w31*w36 + 0 = 0 - EXPR 1*w21*w31 + -1*w51 + 0 = 0 + EXPR -1*w31*w36 = 0 + EXPR 1*w21*w31 + -1*w51 = 0 MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) - EXPR -1*w31*w52 + 1*w52 + -1*w53 + 0 = 0 + EXPR -1*w31*w52 + 1*w52 + -1*w53 = 0 MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) EXPR -1*w31 + -1*w55 + 1 = 0 - EXPR -1*w31*w49 + 1*w31*w50 + 1*w49 + -1*w56 + 0 = 0 + EXPR -1*w31*w49 + 1*w31*w50 + 1*w49 + -1*w56 = 0 EXPR 1*w31*w54 + 1*w55*w56 + -109 = 0 EXPR -1*w57 + 246 = 0 EXPR -1*w58 + 159 = 0 @@ -680,13 +680,13 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] - EXPR 1*w18 + -4294967296*w68 + -1*w69 + 0 = 0 + EXPR 1*w18 + -4294967296*w68 + -1*w69 = 0 EXPR -1*w68 + -1*w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + 1*w72 + -1 = 0 - EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 + 0 = 0 - EXPR 1*w69*w72 + 268435455*w72 + -1*w73 + 0 = 0 + EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 + EXPR 1*w69*w72 + 268435455*w72 + -1*w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] @@ -694,9 +694,9 @@ fn array_dynamic() { EXPR -1*w69 + -4294967296*w74 + -1*w75 + 4294967299 = 0 EXPR -1*w17*w74 + 1*w17 + -3*w74 + -1*w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] - EXPR -1*w74*w76 + 1*w76 + -1*w77 + 0 = 0 + EXPR -1*w74*w76 + 1*w76 + -1*w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) - EXPR 1*w15*w74 + -1*w74*w78 + -1*w15 + 1*w78 + 0 = 0 + EXPR 1*w15*w74 + -1*w74*w78 + -1*w15 + 1*w78 = 0 "; assert_circuit_roundtrip(src); } @@ -719,7 +719,7 @@ fn fold_basic() { return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR -1*w0 + 1*w2 = 0 "; assert_program_roundtrip(src); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index fa7b98cdcb5..e9fcb6a23a6 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -102,7 +102,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w0*w1 + 0 = 0 + EXPR 1*w0*w1 = 0 "); } @@ -124,7 +124,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w1 + 0 = 0 + EXPR 1*w1 = 0 "); } @@ -147,7 +147,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 9*w0*w1 + 0 = 0 + EXPR 9*w0*w1 = 0 "); } @@ -190,7 +190,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 6*w0 + 0 = 0 + EXPR 6*w0 = 0 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 308c8e421aa..7e746068dc7 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,8 +348,8 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w0*w1 + 1*w5 + 0 = 0 - EXPR 2*w0*w0 + -1*w3 + 2*w5 + 0 = 0 + EXPR 1*w0*w1 + 1*w5 = 0 + EXPR 2*w0*w0 + -1*w3 + 2*w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index b1bb893065a..25ea648dae1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -395,7 +395,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - EXPR 1*w1 + 0 = 0 + EXPR 1*w1 = 0 "); } @@ -444,7 +444,7 @@ mod tests { BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] BLACKBOX::RANGE [w1]:16 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] - EXPR 1*w1 + 0 = 0 + EXPR 1*w1 = 0 "); // Applying again should have no effect (despite the range having the same bit size as the assert). diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 1abcf3834d4..ebf12c54811 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -49,12 +49,12 @@ fn constant_array_access_out_of_bounds() { private parameters: [] public parameters: [] return values: [] - EXPR -1*w0 + 0 = 0 + EXPR -1*w0 = 0 EXPR -1*w1 + 1 = 0 INIT (id: 0, len: 2, witnesses: [w0, w1]) EXPR -1*w2 + 5 = 0 MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) - EXPR 1*w3 + 0 = 0 + EXPR 1*w3 = 0 "); } @@ -122,15 +122,15 @@ fn generates_memory_op_for_dynamic_write() { INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR -1*w7 + 10 = 0 MEM (id: 1, write EXPR [ (1, w7) 0 ] at: EXPR [ (1, w3) 0 ]) - EXPR -1*w8 + 0 = 0 + EXPR -1*w8 = 0 MEM (id: 1, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) EXPR -1*w10 + 1 = 0 MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) EXPR -1*w12 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) - EXPR 1*w4 + -1*w9 + 0 = 0 - EXPR 1*w5 + -1*w11 + 0 = 0 - EXPR 1*w6 + -1*w13 + 0 = 0 + EXPR 1*w4 + -1*w9 = 0 + EXPR 1*w5 + -1*w11 = 0 + EXPR 1*w6 + -1*w13 = 0 "); } @@ -161,7 +161,7 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR 1*w3*w4 + -1*w5 + 0 = 0 + EXPR 1*w3*w4 + -1*w5 = 0 MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) EXPR 1*w6 + -10 = 0 "); @@ -199,20 +199,20 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR 1*w3*w4 + -1*w8 + 0 = 0 + EXPR 1*w3*w4 + -1*w8 = 0 MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -1*w4*w9 + 10*w4 + 1*w9 + -1*w10 + 0 = 0 + EXPR -1*w4*w9 + 10*w4 + 1*w9 + -1*w10 = 0 MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) - EXPR -1*w11 + 0 = 0 + EXPR -1*w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) EXPR -1*w13 + 1 = 0 MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) EXPR -1*w15 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) - EXPR 1*w5 + -1*w12 + 0 = 0 - EXPR 1*w6 + -1*w14 + 0 = 0 - EXPR 1*w7 + -1*w16 + 0 = 0 + EXPR 1*w5 + -1*w12 = 0 + EXPR 1*w6 + -1*w14 = 0 + EXPR 1*w7 + -1*w16 = 0 "); } @@ -264,6 +264,6 @@ fn zero_length_array_dynamic_predicate() { private parameters: [w0] public parameters: [] return values: [] - EXPR 1*w0 + 0 = 0 + EXPR 1*w0 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index dc7ce82389e..b4d5edc1955 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -159,15 +159,15 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w5]:32 bits [] EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 - EXPR -1*w2 + 1*w4 + 0 = 0 + EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 + EXPR -1*w2 + 1*w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] EXPR 1*w2*w7 + -1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] EXPR 1*w2 + -1*w9 + -1*w10 + -1 = 0 BLACKBOX::RANGE [w10]:32 bits [] - EXPR -1*w2*w8 + 1*w1 + -1*w9 + 0 = 0 + EXPR -1*w2*w8 + 1*w1 + -1*w9 = 0 EXPR 1*w8 + -1 = 0 unconstrained func 0 @@ -247,8 +247,8 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w5]:32 bits [] EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 - EXPR -1*w2 + 1*w4 + 0 = 0 + EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 + EXPR -1*w2 + 1*w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -259,7 +259,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w11]:32 bits [] EXPR 1*w2 + -1*w11 + -1*w12 + -1 = 0 BLACKBOX::RANGE [w12]:32 bits [] - EXPR -1*w2*w10 + 1*w1 + -1*w11 + 0 = 0 + EXPR -1*w2*w10 + 1*w1 + -1*w11 = 0 EXPR 1*w10 + -1 = 0 unconstrained func 0 @@ -381,8 +381,8 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w5]:32 bits [] EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 + 0 = 0 - EXPR -1*w2 + 1*w4 + 0 = 0 + EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 + EXPR -1*w2 + 1*w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -395,7 +395,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w12]:32 bits [] EXPR 1*w2 + -1*w12 + -1*w13 + -1 = 0 BLACKBOX::RANGE [w13]:32 bits [] - EXPR -1*w2*w11 + 1*w1 + -1*w12 + 0 = 0 + EXPR -1*w2*w11 + 1*w1 + -1*w12 = 0 EXPR 1*w11 + -1 = 0 func 1 @@ -405,12 +405,12 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR 1*w0 + -1*w1 + -1*w3 + 0 = 0 + EXPR 1*w0 + -1*w1 + -1*w3 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] EXPR 1*w3*w4 + 1*w5 + -1 = 0 - EXPR 1*w3*w5 + 0 = 0 - EXPR 1*w5 + 0 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR 1*w3*w5 = 0 + EXPR 1*w5 = 0 + EXPR -1*w0 + 1*w2 = 0 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 990bf406ee7..4a2e469ab0d 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,15 +64,15 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 + 0 = 0 + EXPR 1*w2 + -1*w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 + 0 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR 1*w0 + -1*w1 = 0 + EXPR -1*w0 + 1*w2 = 0 "); } @@ -107,15 +107,15 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 + 0 = 0 + EXPR 1*w2 + -1*w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 + 0 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR 1*w0 + -1*w1 = 0 + EXPR -1*w0 + 1*w2 = 0 "); } @@ -154,7 +154,7 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 + 0 = 0 + EXPR 1*w2 + -1*w3 = 0 func 1 current witness: w4 @@ -164,14 +164,14 @@ fn basic_nested_call(inline_type: InlineType) { EXPR 1*w0 + -1*w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR 1*w2 + -1*w4 + 0 = 0 + EXPR 1*w2 + -1*w4 = 0 func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 + 0 = 0 - EXPR -1*w0 + 1*w2 + 0 = 0 + EXPR 1*w0 + -1*w1 = 0 + EXPR -1*w0 + 1*w2 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index f47659e7104..c62dca3f6fa 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR -1*w0*w1 + 1*w2 + 0 = 0 + EXPR -1*w0*w1 + 1*w2 = 0 "); } From 88c085921ac25eaaf48ba85cdcc18118c649a31f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:19:51 -0300 Subject: [PATCH 03/25] Don't write coefficient 1 --- acvm-repo/acir/src/circuit/opcodes.rs | 14 ++- acvm-repo/acir/src/parser/mod.rs | 36 +++--- acvm-repo/acir/src/parser/tests.rs | 118 +++++++++--------- .../acvm/src/compiler/optimizers/general.rs | 4 +- .../compiler/optimizers/merge_expressions.rs | 2 +- .../compiler/optimizers/redundant_range.rs | 4 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 26 ++-- .../src/acir/tests/brillig_call.rs | 58 ++++----- .../noirc_evaluator/src/acir/tests/call.rs | 22 ++-- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 10 files changed, 152 insertions(+), 134 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 5e32fd26f8d..f589d664f56 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -156,7 +156,12 @@ impl std::fmt::Display for Opcode { write!(f, " + ")?; } - write!(f, "{coefficient}*{witness1}*{witness2}")?; + if coefficient.is_one() { + write!(f, "{witness1}*{witness2}")?; + } else { + write!(f, "{coefficient}*{witness1}*{witness2}")?; + } + printed_term = true; } @@ -165,7 +170,12 @@ impl std::fmt::Display for Opcode { write!(f, " + ")?; } - write!(f, "{coefficient}*{witness}")?; + if coefficient.is_one() { + write!(f, "{witness}")?; + } else { + write!(f, "{coefficient}*{witness}")?; + } + printed_term = true; } diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index b348c923523..89ee512a5ec 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -273,27 +273,35 @@ impl<'a> Parser<'a> { let mut constant: Option = None; loop { - let Some(coefficient) = self.eat_field_element()? else { - return self.expected_field_element(); - }; - - if self.eat(Token::Star)? { - let w1 = self.eat_witness_or_error()?; - + if let Some(w1) = self.eat_witness()? { + let coefficient = FieldElement::one(); if self.eat(Token::Star)? { let w2 = self.eat_witness_or_error()?; mul_terms.push((coefficient, w1, w2)); } else { linear_combinations.push((coefficient, w1)); } - } else { - if constant.is_some() { - return Err(ParserError::DuplicatedConstantTerm { - found: self.token.token().clone(), - span: self.token.span(), - }); + } else if let Some(coefficient) = self.eat_field_element()? { + if self.eat(Token::Star)? { + let w1 = self.eat_witness_or_error()?; + + if self.eat(Token::Star)? { + let w2 = self.eat_witness_or_error()?; + mul_terms.push((coefficient, w1, w2)); + } else { + linear_combinations.push((coefficient, w1)); + } + } else { + if constant.is_some() { + return Err(ParserError::DuplicatedConstantTerm { + found: self.token.token().clone(), + span: self.token.span(), + }); + } + constant = Some(coefficient); } - constant = Some(coefficient); + } else { + return self.expected_field_element(); } if self.eat(Token::Plus)? { diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 8224a759c8c..2b2d615257c 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -102,11 +102,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR 1*w0 + -1*w5 = 0 - EXPR 1*w1 + -1*w6 = 0 - EXPR 1*w2 + -1*w7 = 0 - EXPR 1*w3 + -1*w8 = 0 - EXPR 1*w4 + -1*w9 = 0 + EXPR w0 + -1*w5 = 0 + EXPR w1 + -1*w6 = 0 + EXPR w2 + -1*w7 = 0 + EXPR w3 + -1*w8 = 0 + EXPR w4 + -1*w9 = 0 "; assert_circuit_roundtrip(src); } @@ -118,11 +118,11 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR 1*w0*w1 + -1*w3 = 0 - EXPR 1*w3*w3 + -1*w4 = 0 - EXPR 1*w4*w4 + -1*w5 = 0 - EXPR 1*w5*w5 + -1*w6 = 0 - EXPR -1*w2 + 1*w6 = 0 + EXPR w0*w1 + -1*w3 = 0 + EXPR w3*w3 + -1*w4 = 0 + EXPR w4*w4 + -1*w5 = 0 + EXPR w5*w5 + -1*w6 = 0 + EXPR -1*w2 + w6 = 0 "; assert_circuit_roundtrip(src); } @@ -149,7 +149,7 @@ fn xor() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::XOR [w0, w1]:32 bits [w2] - EXPR 1*w2 + -15 = 0 + EXPR w2 + -15 = 0 "; assert_circuit_roundtrip(src); } @@ -223,22 +223,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR -1*w44 + 1*w60 = 0 - EXPR -1*w45 + 1*w61 = 0 - EXPR -1*w46 + 1*w62 = 0 - EXPR -1*w47 + 1*w63 = 0 - EXPR -1*w48 + 1*w64 = 0 - EXPR -1*w49 + 1*w65 = 0 - EXPR -1*w50 + 1*w66 = 0 - EXPR -1*w51 + 1*w67 = 0 - EXPR -1*w52 + 1*w68 = 0 - EXPR -1*w53 + 1*w69 = 0 - EXPR -1*w54 + 1*w70 = 0 - EXPR -1*w55 + 1*w71 = 0 - EXPR -1*w56 + 1*w72 = 0 - EXPR -1*w57 + 1*w73 = 0 - EXPR -1*w58 + 1*w74 = 0 - EXPR -1*w59 + 1*w75 = 0 + EXPR -1*w44 + w60 = 0 + EXPR -1*w45 + w61 = 0 + EXPR -1*w46 + w62 = 0 + EXPR -1*w47 + w63 = 0 + EXPR -1*w48 + w64 = 0 + EXPR -1*w49 + w65 = 0 + EXPR -1*w50 + w66 = 0 + EXPR -1*w51 + w67 = 0 + EXPR -1*w52 + w68 = 0 + EXPR -1*w53 + w69 = 0 + EXPR -1*w54 + w70 = 0 + EXPR -1*w55 + w71 = 0 + EXPR -1*w56 + w72 = 0 + EXPR -1*w57 + w73 = 0 + EXPR -1*w58 + w74 = 0 + EXPR -1*w59 + w75 = 0 "; assert_circuit_roundtrip(src); } @@ -525,8 +525,8 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + w2 = 0 "; assert_circuit_roundtrip(src); } @@ -540,8 +540,8 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + w2 = 0 "; assert_circuit_roundtrip(src); } @@ -608,39 +608,39 @@ fn array_dynamic() { BLACKBOX::RANGE [w17]:32 bits [] EXPR 5*w6 + -1*w19 = 0 BLACKBOX::RANGE [w19]:32 bits [] - EXPR 1*w5 + -1*w19 + -1*w20 = 0 + EXPR w5 + -1*w19 + -1*w20 = 0 BLACKBOX::RANGE [w20]:32 bits [] - EXPR 1*w20 + -1*w21 + -5 = 0 - EXPR 1*w21 + -1*w22 + -3 = 0 + EXPR w20 + -1*w21 + -5 = 0 + EXPR w21 + -1*w22 + -3 = 0 MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) - EXPR 1*w23 + -111 = 0 + EXPR w23 + -111 = 0 MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) - EXPR 1*w24 + -101 = 0 + EXPR w24 + -101 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR 1*w22 + -4294967296*w25 + -1*w26 + 4294967291 = 0 + EXPR w22 + -4294967296*w25 + -1*w26 + 4294967291 = 0 EXPR -1*w25 = 0 EXPR -1*w27 = 0 MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) - EXPR 1*w28 + -111 = 0 + EXPR w28 + -111 = 0 EXPR -1*w29 + 1 = 0 MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) - EXPR 1*w30 = 0 + EXPR w30 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR 1*w21 + -4294967296*w31 + -1*w32 + 4294967286 = 0 - EXPR -1*w21*w31 + 1*w21 + -1*w33 = 0 + EXPR w21 + -4294967296*w31 + -1*w32 + 4294967286 = 0 + EXPR -1*w21*w31 + w21 + -1*w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) - EXPR -1*w31*w34 + 2*w31 + 1*w34 + -1*w35 + -2 = 0 + EXPR -1*w31*w34 + 2*w31 + w34 + -1*w35 + -2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR 1*w21 + -4294967296*w36 + -1*w37 + 4294967291 = 0 - EXPR 1*w31*w36 + -1*w36 = 0 - EXPR -1*w21*w31 + 1*w21 + -1*w38 = 0 + EXPR w21 + -4294967296*w36 + -1*w37 + 4294967291 = 0 + EXPR w31*w36 + -1*w36 = 0 + EXPR -1*w21*w31 + w21 + -1*w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) @@ -651,19 +651,19 @@ fn array_dynamic() { EXPR -1*w46 + 4 = 0 MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR -1*w31*w35 + 1*w31*w39 + 1*w35 + -1*w48 = 0 + EXPR -1*w31*w35 + w31*w39 + w35 + -1*w48 = 0 MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) EXPR -1*w31*w36 = 0 - EXPR 1*w21*w31 + -1*w51 = 0 + EXPR w21*w31 + -1*w51 = 0 MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) - EXPR -1*w31*w52 + 1*w52 + -1*w53 = 0 + EXPR -1*w31*w52 + w52 + -1*w53 = 0 MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) EXPR -1*w31 + -1*w55 + 1 = 0 - EXPR -1*w31*w49 + 1*w31*w50 + 1*w49 + -1*w56 = 0 - EXPR 1*w31*w54 + 1*w55*w56 + -109 = 0 + EXPR -1*w31*w49 + w31*w50 + w49 + -1*w56 = 0 + EXPR w31*w54 + w55*w56 + -109 = 0 EXPR -1*w57 + 246 = 0 EXPR -1*w58 + 159 = 0 EXPR -1*w59 + 32 = 0 @@ -676,27 +676,27 @@ fn array_dynamic() { MEM (id: 4, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w65) 0 ]) MEM (id: 4, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w66) 0 ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) 0 ]], outputs: [w67] - EXPR 1*w62*w67 + 1*w63*w67 + 1*w64*w67 + 1*w65*w67 + 1*w66*w67 + -1 = 0 + EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 + -1 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] - EXPR 1*w18 + -4294967296*w68 + -1*w69 = 0 + EXPR w18 + -4294967296*w68 + -1*w69 = 0 EXPR -1*w68 + -1*w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + 1*w72 + -1 = 0 + EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 + -1 = 0 EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 - EXPR 1*w69*w72 + 268435455*w72 + -1*w73 = 0 + EXPR w69*w72 + 268435455*w72 + -1*w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] EXPR -1*w69 + -4294967296*w74 + -1*w75 + 4294967299 = 0 - EXPR -1*w17*w74 + 1*w17 + -3*w74 + -1*w76 + 3 = 0 + EXPR -1*w17*w74 + w17 + -3*w74 + -1*w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] - EXPR -1*w74*w76 + 1*w76 + -1*w77 = 0 + EXPR -1*w74*w76 + w76 + -1*w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) - EXPR 1*w15*w74 + -1*w74*w78 + -1*w15 + 1*w78 = 0 + EXPR w15*w74 + -1*w74*w78 + -1*w15 + w78 = 0 "; assert_circuit_roundtrip(src); } @@ -718,8 +718,8 @@ fn fold_basic() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR 1*w0*w3 + -1*w1*w3 + -1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR -1*w0 + w2 = 0 "; assert_program_roundtrip(src); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index e9fcb6a23a6..e28f7bf95d1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -102,7 +102,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w0*w1 = 0 + EXPR w0*w1 = 0 "); } @@ -124,7 +124,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w1 = 0 + EXPR w1 = 0 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 7e746068dc7..668f222187e 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,7 +348,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 1*w0*w1 + 1*w5 = 0 + EXPR w0*w1 + w5 = 0 EXPR 2*w0*w0 + -1*w3 + 2*w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 25ea648dae1..131f6445de3 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -395,7 +395,7 @@ mod tests { private parameters: [] public parameters: [] return values: [] - EXPR 1*w1 = 0 + EXPR w1 = 0 "); } @@ -444,7 +444,7 @@ mod tests { BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] BLACKBOX::RANGE [w1]:16 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] - EXPR 1*w1 = 0 + EXPR w1 = 0 "); // Applying again should have no effect (despite the range having the same bit size as the assert). diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index ebf12c54811..76205aa8be6 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -54,7 +54,7 @@ fn constant_array_access_out_of_bounds() { INIT (id: 0, len: 2, witnesses: [w0, w1]) EXPR -1*w2 + 5 = 0 MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) - EXPR 1*w3 = 0 + EXPR w3 = 0 "); } @@ -97,7 +97,7 @@ fn generates_memory_op_for_dynamic_read() { return values: [] INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) - EXPR 1*w4 + -10 = 0 + EXPR w4 + -10 = 0 "); } @@ -128,9 +128,9 @@ fn generates_memory_op_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) EXPR -1*w12 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) - EXPR 1*w4 + -1*w9 = 0 - EXPR 1*w5 + -1*w11 = 0 - EXPR 1*w6 + -1*w13 = 0 + EXPR w4 + -1*w9 = 0 + EXPR w5 + -1*w11 = 0 + EXPR w6 + -1*w13 = 0 "); } @@ -161,9 +161,9 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR 1*w3*w4 + -1*w5 = 0 + EXPR w3*w4 + -1*w5 = 0 MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) - EXPR 1*w6 + -10 = 0 + EXPR w6 + -10 = 0 "); } @@ -199,10 +199,10 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR 1*w3*w4 + -1*w8 = 0 + EXPR w3*w4 + -1*w8 = 0 MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -1*w4*w9 + 10*w4 + 1*w9 + -1*w10 = 0 + EXPR -1*w4*w9 + 10*w4 + w9 + -1*w10 = 0 MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) EXPR -1*w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) @@ -210,9 +210,9 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) EXPR -1*w15 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) - EXPR 1*w5 + -1*w12 = 0 - EXPR 1*w6 + -1*w14 = 0 - EXPR 1*w7 + -1*w16 = 0 + EXPR w5 + -1*w12 = 0 + EXPR w6 + -1*w14 = 0 + EXPR w7 + -1*w16 = 0 "); } @@ -264,6 +264,6 @@ fn zero_length_array_dynamic_predicate() { private parameters: [w0] public parameters: [] return values: [] - EXPR 1*w0 = 0 + EXPR w0 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index b4d5edc1955..b231e6ea74d 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,22 +153,22 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR 1*w1*w3 + -1 = 0 + EXPR w1*w3 + -1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 - EXPR -1*w2 + 1*w4 = 0 + EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] - EXPR 1*w2*w7 + -1 = 0 + EXPR w2*w7 + -1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR 1*w2 + -1*w9 + -1*w10 + -1 = 0 + EXPR w2 + -1*w9 + -1*w10 + -1 = 0 BLACKBOX::RANGE [w10]:32 bits [] - EXPR -1*w2*w8 + 1*w1 + -1*w9 = 0 - EXPR 1*w8 + -1 = 0 + EXPR -1*w2*w8 + w1 + -1*w9 = 0 + EXPR w8 + -1 = 0 unconstrained func 0 0: @21 = const u32 1 @@ -241,26 +241,26 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR 1*w1*w3 + -1 = 0 + EXPR w1*w3 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 - EXPR -1*w2 + 1*w4 = 0 + EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w9] - EXPR 1*w2*w9 + -1 = 0 + EXPR w2*w9 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR 1*w2 + -1*w11 + -1*w12 + -1 = 0 + EXPR w2 + -1*w11 + -1*w12 + -1 = 0 BLACKBOX::RANGE [w12]:32 bits [] - EXPR -1*w2*w10 + 1*w1 + -1*w11 = 0 - EXPR 1*w10 + -1 = 0 + EXPR -1*w2*w10 + w1 + -1*w11 = 0 + EXPR w10 + -1 = 0 unconstrained func 0 0: @2 = const u32 1 @@ -375,14 +375,14 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR 1*w1*w3 + -1 = 0 + EXPR w1*w3 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR 1*w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 + -1*w5 + -1*w6 + -1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + 1*w0 + -1*w5 = 0 - EXPR -1*w2 + 1*w4 = 0 + EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -390,13 +390,13 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w10] - EXPR 1*w2*w10 + -1 = 0 + EXPR w2*w10 + -1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR 1*w2 + -1*w12 + -1*w13 + -1 = 0 + EXPR w2 + -1*w12 + -1*w13 + -1 = 0 BLACKBOX::RANGE [w13]:32 bits [] - EXPR -1*w2*w11 + 1*w1 + -1*w12 = 0 - EXPR 1*w11 + -1 = 0 + EXPR -1*w2*w11 + w1 + -1*w12 = 0 + EXPR w11 + -1 = 0 func 1 current witness: w5 @@ -405,12 +405,12 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR 1*w0 + -1*w1 + -1*w3 = 0 + EXPR w0 + -1*w1 + -1*w3 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] - EXPR 1*w3*w4 + 1*w5 + -1 = 0 - EXPR 1*w3*w5 = 0 - EXPR 1*w5 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w3*w4 + w5 + -1 = 0 + EXPR w3*w5 = 0 + EXPR w5 = 0 + EXPR -1*w0 + w2 = 0 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 4a2e469ab0d..5884e36785a 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,15 +64,15 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 = 0 + EXPR w2 + -1*w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0 + -1*w1 = 0 + EXPR -1*w0 + w2 = 0 "); } @@ -107,15 +107,15 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 = 0 + EXPR w2 + -1*w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0 + -1*w1 = 0 + EXPR -1*w0 + w2 = 0 "); } @@ -154,24 +154,24 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR 1*w2 + -1*w3 = 0 + EXPR w2 + -1*w3 = 0 func 1 current witness: w4 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w3 + 2 = 0 + EXPR w0 + -1*w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR 1*w2 + -1*w4 = 0 + EXPR w2 + -1*w4 = 0 func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR 1*w0 + -1*w1 = 0 - EXPR -1*w0 + 1*w2 = 0 + EXPR w0 + -1*w1 = 0 + EXPR -1*w0 + w2 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index c62dca3f6fa..088b42b246e 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR -1*w0*w1 + 1*w2 = 0 + EXPR -1*w0*w1 + w2 = 0 "); } From f78b8a9d2c4a989a9297d3ab9266bcacf2001582 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:32:33 -0300 Subject: [PATCH 04/25] Use standalone minus when possible --- acvm-repo/acir/src/circuit/opcodes.rs | 48 ++++++++++- acvm-repo/acir/src/parser/lexer.rs | 3 + acvm-repo/acir/src/parser/mod.rs | 11 +++ acvm-repo/acir/src/parser/tests.rs | 84 +++++++++---------- acvm-repo/acir/src/parser/token.rs | 3 + .../compiler/optimizers/merge_expressions.rs | 2 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 22 ++--- .../src/acir/tests/brillig_call.rs | 46 +++++----- .../noirc_evaluator/src/acir/tests/call.rs | 16 ++-- 9 files changed, 146 insertions(+), 89 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index f589d664f56..b1c200aa384 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -152,10 +152,23 @@ impl std::fmt::Display for Opcode { let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { + let coefficient_as_string = coefficient.to_string(); + let coefficient_is_negative = coefficient_as_string.starts_with('-'); + if printed_term { - write!(f, " + ")?; + if coefficient_is_negative { + write!(f, " - ")?; + } else { + write!(f, " + ")?; + } } + let coefficient = if printed_term && coefficient_is_negative { + -*coefficient + } else { + *coefficient + }; + if coefficient.is_one() { write!(f, "{witness1}*{witness2}")?; } else { @@ -166,10 +179,23 @@ impl std::fmt::Display for Opcode { } for (coefficient, witness) in &expr.linear_combinations { + let coefficient_as_string = coefficient.to_string(); + let coefficient_is_negative = coefficient_as_string.starts_with('-'); + if printed_term { - write!(f, " + ")?; + if coefficient_is_negative { + write!(f, " - ")?; + } else { + write!(f, " + ")?; + } } + let coefficient = if printed_term && coefficient_is_negative { + -*coefficient + } else { + *coefficient + }; + if coefficient.is_one() { write!(f, "{witness}")?; } else { @@ -182,10 +208,24 @@ impl std::fmt::Display for Opcode { if !expr.q_c.is_zero() || (expr.mul_terms.is_empty() && expr.linear_combinations.is_empty()) { + let coefficient = expr.q_c; + let coefficient_as_string = coefficient.to_string(); + let coefficient_is_negative = coefficient_as_string.starts_with('-'); + if printed_term { - write!(f, " + ")?; + if coefficient_is_negative { + write!(f, " - ")?; + } else { + write!(f, " + ")?; + } } - write!(f, "{}", expr.q_c)?; + + let coefficient = if printed_term && coefficient_is_negative { + -coefficient + } else { + coefficient + }; + write!(f, "{coefficient}")?; } write!(f, " = 0")?; diff --git a/acvm-repo/acir/src/parser/lexer.rs b/acvm-repo/acir/src/parser/lexer.rs index c30b5badbd7..3c6d6592e8a 100644 --- a/acvm-repo/acir/src/parser/lexer.rs +++ b/acvm-repo/acir/src/parser/lexer.rs @@ -65,6 +65,9 @@ impl<'a> Lexer<'a> { ':' => self.single_char_token(Token::Colon), ';' => self.single_char_token(Token::Semicolon), '+' => self.single_char_token(Token::Plus), + '-' if self.peek_char().is_none_or(|char| !char.is_ascii_digit()) => { + self.single_char_token(Token::Minus) + } '*' => self.single_char_token(Token::Star), '=' => self.single_char_token(Token::Equal), 'w' if self.peek_char().is_some_and(|char| char.is_ascii_digit()) => { diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 89ee512a5ec..61aea113f73 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -271,10 +271,13 @@ impl<'a> Parser<'a> { let mut linear_combinations = Vec::new(); let mut mul_terms = Vec::new(); let mut constant: Option = None; + let mut negative = false; loop { if let Some(w1) = self.eat_witness()? { let coefficient = FieldElement::one(); + let coefficient = if negative { -coefficient } else { coefficient }; + if self.eat(Token::Star)? { let w2 = self.eat_witness_or_error()?; mul_terms.push((coefficient, w1, w2)); @@ -282,6 +285,8 @@ impl<'a> Parser<'a> { linear_combinations.push((coefficient, w1)); } } else if let Some(coefficient) = self.eat_field_element()? { + let coefficient = if negative { -coefficient } else { coefficient }; + if self.eat(Token::Star)? { let w1 = self.eat_witness_or_error()?; @@ -305,6 +310,12 @@ impl<'a> Parser<'a> { } if self.eat(Token::Plus)? { + negative = false; + continue; + } + + if self.eat(Token::Minus)? { + negative = true; continue; } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 2b2d615257c..353d3e794af 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -102,11 +102,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR w0 + -1*w5 = 0 - EXPR w1 + -1*w6 = 0 - EXPR w2 + -1*w7 = 0 - EXPR w3 + -1*w8 = 0 - EXPR w4 + -1*w9 = 0 + EXPR w0 - w5 = 0 + EXPR w1 - w6 = 0 + EXPR w2 - w7 = 0 + EXPR w3 - w8 = 0 + EXPR w4 - w9 = 0 "; assert_circuit_roundtrip(src); } @@ -118,10 +118,10 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w0*w1 + -1*w3 = 0 - EXPR w3*w3 + -1*w4 = 0 - EXPR w4*w4 + -1*w5 = 0 - EXPR w5*w5 + -1*w6 = 0 + EXPR w0*w1 - w3 = 0 + EXPR w3*w3 - w4 = 0 + EXPR w4*w4 - w5 = 0 + EXPR w5*w5 - w6 = 0 EXPR -1*w2 + w6 = 0 "; assert_circuit_roundtrip(src); @@ -149,7 +149,7 @@ fn xor() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::XOR [w0, w1]:32 bits [w2] - EXPR w2 + -15 = 0 + EXPR w2 - 15 = 0 "; assert_circuit_roundtrip(src); } @@ -525,7 +525,7 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR -1*w0 + w2 = 0 "; assert_circuit_roundtrip(src); @@ -540,7 +540,7 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR -1*w0 + w2 = 0 "; assert_circuit_roundtrip(src); @@ -606,41 +606,41 @@ fn array_dynamic() { BLACKBOX::RANGE [w15]:32 bits [] BLACKBOX::RANGE [w16]:32 bits [] BLACKBOX::RANGE [w17]:32 bits [] - EXPR 5*w6 + -1*w19 = 0 + EXPR 5*w6 - w19 = 0 BLACKBOX::RANGE [w19]:32 bits [] - EXPR w5 + -1*w19 + -1*w20 = 0 + EXPR w5 - w19 - w20 = 0 BLACKBOX::RANGE [w20]:32 bits [] - EXPR w20 + -1*w21 + -5 = 0 - EXPR w21 + -1*w22 + -3 = 0 + EXPR w20 - w21 - 5 = 0 + EXPR w21 - w22 - 3 = 0 MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) - EXPR w23 + -111 = 0 + EXPR w23 - 111 = 0 MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) - EXPR w24 + -101 = 0 + EXPR w24 - 101 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR w22 + -4294967296*w25 + -1*w26 + 4294967291 = 0 + EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 EXPR -1*w25 = 0 EXPR -1*w27 = 0 MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) - EXPR w28 + -111 = 0 + EXPR w28 - 111 = 0 EXPR -1*w29 + 1 = 0 MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) EXPR w30 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR w21 + -4294967296*w31 + -1*w32 + 4294967286 = 0 - EXPR -1*w21*w31 + w21 + -1*w33 = 0 + EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 + EXPR -1*w21*w31 + w21 - w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) - EXPR -1*w31*w34 + 2*w31 + w34 + -1*w35 + -2 = 0 + EXPR -1*w31*w34 + 2*w31 + w34 - w35 - 2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR w21 + -4294967296*w36 + -1*w37 + 4294967291 = 0 - EXPR w31*w36 + -1*w36 = 0 - EXPR -1*w21*w31 + w21 + -1*w38 = 0 + EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 + EXPR w31*w36 - w36 = 0 + EXPR -1*w21*w31 + w21 - w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) @@ -651,19 +651,19 @@ fn array_dynamic() { EXPR -1*w46 + 4 = 0 MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR -1*w31*w35 + w31*w39 + w35 + -1*w48 = 0 + EXPR -1*w31*w35 + w31*w39 + w35 - w48 = 0 MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) EXPR -1*w31*w36 = 0 - EXPR w21*w31 + -1*w51 = 0 + EXPR w21*w31 - w51 = 0 MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) - EXPR -1*w31*w52 + w52 + -1*w53 = 0 + EXPR -1*w31*w52 + w52 - w53 = 0 MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) - EXPR -1*w31 + -1*w55 + 1 = 0 - EXPR -1*w31*w49 + w31*w50 + w49 + -1*w56 = 0 - EXPR w31*w54 + w55*w56 + -109 = 0 + EXPR -1*w31 - w55 + 1 = 0 + EXPR -1*w31*w49 + w31*w50 + w49 - w56 = 0 + EXPR w31*w54 + w55*w56 - 109 = 0 EXPR -1*w57 + 246 = 0 EXPR -1*w58 + 159 = 0 EXPR -1*w59 + 32 = 0 @@ -676,27 +676,27 @@ fn array_dynamic() { MEM (id: 4, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w65) 0 ]) MEM (id: 4, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w66) 0 ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) 0 ]], outputs: [w67] - EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 + -1 = 0 + EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] - EXPR w18 + -4294967296*w68 + -1*w69 = 0 - EXPR -1*w68 + -1*w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 + EXPR w18 - 4294967296*w68 - w69 = 0 + EXPR -1*w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 + -1 = 0 + EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 - EXPR w69*w72 + 268435455*w72 + -1*w73 = 0 + EXPR w69*w72 + 268435455*w72 - w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR -1*w69 + -4294967296*w74 + -1*w75 + 4294967299 = 0 - EXPR -1*w17*w74 + w17 + -3*w74 + -1*w76 + 3 = 0 + EXPR -1*w69 - 4294967296*w74 - w75 + 4294967299 = 0 + EXPR -1*w17*w74 + w17 - 3*w74 - w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] - EXPR -1*w74*w76 + w76 + -1*w77 = 0 + EXPR -1*w74*w76 + w76 - w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) - EXPR w15*w74 + -1*w74*w78 + -1*w15 + w78 = 0 + EXPR w15*w74 - w74*w78 - w15 + w78 = 0 "; assert_circuit_roundtrip(src); } @@ -718,7 +718,7 @@ fn fold_basic() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR w0*w3 + -1*w1*w3 + -1 = 0 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR -1*w0 + w2 = 0 "; assert_program_roundtrip(src); diff --git a/acvm-repo/acir/src/parser/token.rs b/acvm-repo/acir/src/parser/token.rs index b8fb6f4fd97..7cc805ac06c 100644 --- a/acvm-repo/acir/src/parser/token.rs +++ b/acvm-repo/acir/src/parser/token.rs @@ -50,6 +50,8 @@ pub(crate) enum Token { RightParen, /// + Plus, + /// - + Minus, /// * Star, /// = @@ -82,6 +84,7 @@ impl std::fmt::Display for Token { Token::LeftParen => write!(f, "("), Token::RightParen => write!(f, ")"), Token::Plus => write!(f, "+"), + Token::Minus => write!(f, "-"), Token::Star => write!(f, "*"), Token::Equal => write!(f, "="), Token::Eof => write!(f, "(end of stream)"), diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 668f222187e..9d1d9134cd7 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -349,7 +349,7 @@ mod tests { public parameters: [] return values: [] EXPR w0*w1 + w5 = 0 - EXPR 2*w0*w0 + -1*w3 + 2*w5 = 0 + EXPR 2*w0*w0 - w3 + 2*w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 76205aa8be6..0f7f54b63a3 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -97,7 +97,7 @@ fn generates_memory_op_for_dynamic_read() { return values: [] INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) - EXPR w4 + -10 = 0 + EXPR w4 - 10 = 0 "); } @@ -128,9 +128,9 @@ fn generates_memory_op_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) EXPR -1*w12 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) - EXPR w4 + -1*w9 = 0 - EXPR w5 + -1*w11 = 0 - EXPR w6 + -1*w13 = 0 + EXPR w4 - w9 = 0 + EXPR w5 - w11 = 0 + EXPR w6 - w13 = 0 "); } @@ -161,9 +161,9 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 + -1*w5 = 0 + EXPR w3*w4 - w5 = 0 MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) - EXPR w6 + -10 = 0 + EXPR w6 - 10 = 0 "); } @@ -199,10 +199,10 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 + -1*w8 = 0 + EXPR w3*w4 - w8 = 0 MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -1*w4*w9 + 10*w4 + w9 + -1*w10 = 0 + EXPR -1*w4*w9 + 10*w4 + w9 - w10 = 0 MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) EXPR -1*w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) @@ -210,9 +210,9 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) EXPR -1*w15 + 2 = 0 MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) - EXPR w5 + -1*w12 = 0 - EXPR w6 + -1*w14 = 0 - EXPR w7 + -1*w16 = 0 + EXPR w5 - w12 = 0 + EXPR w6 - w14 = 0 + EXPR w7 - w16 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index b231e6ea74d..10bf89815a3 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,22 +153,22 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR w1*w3 + -1 = 0 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w1*w4 + w0 - w5 = 0 EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] - EXPR w2*w7 + -1 = 0 + EXPR w2*w7 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR w2 + -1*w9 + -1*w10 + -1 = 0 + EXPR w2 - w9 - w10 - 1 = 0 BLACKBOX::RANGE [w10]:32 bits [] - EXPR -1*w2*w8 + w1 + -1*w9 = 0 - EXPR w8 + -1 = 0 + EXPR -1*w2*w8 + w1 - w9 = 0 + EXPR w8 - 1 = 0 unconstrained func 0 0: @21 = const u32 1 @@ -241,26 +241,26 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR w1*w3 + -1 = 0 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w1*w4 + w0 - w5 = 0 EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w9] - EXPR w2*w9 + -1 = 0 + EXPR w2*w9 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR w2 + -1*w11 + -1*w12 + -1 = 0 + EXPR w2 - w11 - w12 - 1 = 0 BLACKBOX::RANGE [w12]:32 bits [] - EXPR -1*w2*w10 + w1 + -1*w11 = 0 - EXPR w10 + -1 = 0 + EXPR -1*w2*w10 + w1 - w11 = 0 + EXPR w10 - 1 = 0 unconstrained func 0 0: @2 = const u32 1 @@ -375,13 +375,13 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] - EXPR w1*w3 + -1 = 0 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 + -1*w5 + -1*w6 + -1 = 0 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 + -1*w5 = 0 + EXPR -1*w1*w4 + w0 - w5 = 0 EXPR -1*w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] @@ -390,13 +390,13 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w10] - EXPR w2*w10 + -1 = 0 + EXPR w2*w10 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR w2 + -1*w12 + -1*w13 + -1 = 0 + EXPR w2 - w12 - w13 - 1 = 0 BLACKBOX::RANGE [w13]:32 bits [] - EXPR -1*w2*w11 + w1 + -1*w12 = 0 - EXPR w11 + -1 = 0 + EXPR -1*w2*w11 + w1 - w12 = 0 + EXPR w11 - 1 = 0 func 1 current witness: w5 @@ -405,9 +405,9 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR w0 + -1*w1 + -1*w3 = 0 + EXPR w0 - w1 - w3 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] - EXPR w3*w4 + w5 + -1 = 0 + EXPR w3*w4 + w5 - 1 = 0 EXPR w3*w5 = 0 EXPR w5 = 0 EXPR -1*w0 + w2 = 0 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 5884e36785a..9a876850291 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,14 +64,14 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 + -1*w3 = 0 + EXPR w2 - w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 + -1*w1 = 0 + EXPR w0 - w1 = 0 EXPR -1*w0 + w2 = 0 "); } @@ -107,14 +107,14 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR w2 + -1*w3 = 0 + EXPR w2 - w3 = 0 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 + -1*w1 = 0 + EXPR w0 - w1 = 0 EXPR -1*w0 + w2 = 0 "); } @@ -154,24 +154,24 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 + -1*w3 = 0 + EXPR w2 - w3 = 0 func 1 current witness: w4 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 + -1*w3 + 2 = 0 + EXPR w0 - w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR w2 + -1*w4 = 0 + EXPR w2 - w4 = 0 func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 + -1*w1 = 0 + EXPR w0 - w1 = 0 EXPR -1*w0 + w2 = 0 "); } From 8a2e7bbc6840380d11b76998bef77c3e97d1c20a Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:47:15 -0300 Subject: [PATCH 05/25] Witness equality to constant --- acvm-repo/acir/src/circuit/opcodes.rs | 15 +++++++++ acvm-repo/acir/src/parser/mod.rs | 32 +++++++++++++------ acvm-repo/acir/src/parser/tests.rs | 8 ++--- .../noirc_evaluator/src/acir/tests/arrays.rs | 4 +-- .../src/acir/tests/brillig_call.rs | 6 ++-- 5 files changed, 46 insertions(+), 19 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index b1c200aa384..ebb27bc9f1e 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -149,6 +149,21 @@ impl std::fmt::Display for Opcode { Opcode::AssertZero(expr) => { write!(f, "EXPR ")?; + // Check if it's `wN - C = 0` and print it as `wN = C`, + // or if its' `wN + C = 0` and print it as `wN = -C`. + if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 1 { + let (coefficient, witness) = expr.linear_combinations[0]; + let constant = expr.q_c; + + if coefficient.is_one() { + // This is `wN + C = 0`, so show it as `wN = -C`. + + let constant = -constant; + write!(f, "{witness} = {constant}")?; + return Ok(()); + } + } + let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 61aea113f73..c6faf399692 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -272,12 +272,22 @@ impl<'a> Parser<'a> { let mut mul_terms = Vec::new(); let mut constant: Option = None; let mut negative = false; + let mut first = true; loop { if let Some(w1) = self.eat_witness()? { let coefficient = FieldElement::one(); let coefficient = if negative { -coefficient } else { coefficient }; + if first && self.eat(Token::Equal)? { + let q_c = self.eat_field_or_error()?; + + // Here we parsed `coefficient*witness = constant` so we produce `coefficient*witness - q_c = 0` + linear_combinations.push((coefficient, w1)); + constant = Some(-q_c); + break; + } + if self.eat(Token::Star)? { let w2 = self.eat_witness_or_error()?; mul_terms.push((coefficient, w1, w2)); @@ -309,6 +319,8 @@ impl<'a> Parser<'a> { return self.expected_field_element(); } + first = false; + if self.eat(Token::Plus)? { negative = false; continue; @@ -320,22 +332,22 @@ impl<'a> Parser<'a> { } if self.eat(Token::Equal)? { + let zero_token = self.token.token().clone(); + let span = self.token.span(); + let Some(zero) = self.eat_field_element()? else { + return self.expected_field_element(); + }; + + if !zero.is_zero() { + return Err(ParserError::ExpectedZero { found: zero_token, span }); + } + break; } return self.expected_token(Token::Equal); } - let zero_token = self.token.token().clone(); - let span = self.token.span(); - let Some(zero) = self.eat_field_element()? else { - return self.expected_field_element(); - }; - - if !zero.is_zero() { - return Err(ParserError::ExpectedZero { found: zero_token, span }); - } - // If a constant isn't provided, we default it to zero let q_c = constant.unwrap_or_default(); diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 353d3e794af..b8569169ba9 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -149,7 +149,7 @@ fn xor() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::XOR [w0, w1]:32 bits [w2] - EXPR w2 - 15 = 0 + EXPR w2 = 15 "; assert_circuit_roundtrip(src); } @@ -613,9 +613,9 @@ fn array_dynamic() { EXPR w20 - w21 - 5 = 0 EXPR w21 - w22 - 3 = 0 MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) - EXPR w23 - 111 = 0 + EXPR w23 = 111 MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) - EXPR w24 - 101 = 0 + EXPR w24 = 101 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 @@ -623,7 +623,7 @@ fn array_dynamic() { EXPR -1*w27 = 0 MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) - EXPR w28 - 111 = 0 + EXPR w28 = 111 EXPR -1*w29 + 1 = 0 MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) EXPR w30 = 0 diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 0f7f54b63a3..c7f148bbbd4 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -97,7 +97,7 @@ fn generates_memory_op_for_dynamic_read() { return values: [] INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) - EXPR w4 - 10 = 0 + EXPR w4 = 10 "); } @@ -163,7 +163,7 @@ fn generates_predicated_index_for_dynamic_read() { BLACKBOX::RANGE [w4]:1 bits [] EXPR w3*w4 - w5 = 0 MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) - EXPR w6 - 10 = 0 + EXPR w6 = 10 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index 10bf89815a3..68a556d854a 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -168,7 +168,7 @@ fn multiple_brillig_stdlib_calls() { EXPR w2 - w9 - w10 - 1 = 0 BLACKBOX::RANGE [w10]:32 bits [] EXPR -1*w2*w8 + w1 - w9 = 0 - EXPR w8 - 1 = 0 + EXPR w8 = 1 unconstrained func 0 0: @21 = const u32 1 @@ -260,7 +260,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { EXPR w2 - w11 - w12 - 1 = 0 BLACKBOX::RANGE [w12]:32 bits [] EXPR -1*w2*w10 + w1 - w11 = 0 - EXPR w10 - 1 = 0 + EXPR w10 = 1 unconstrained func 0 0: @2 = const u32 1 @@ -396,7 +396,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w2 - w12 - w13 - 1 = 0 BLACKBOX::RANGE [w13]:32 bits [] EXPR -1*w2*w11 + w1 - w12 = 0 - EXPR w11 - 1 = 0 + EXPR w11 = 1 func 1 current witness: w5 From e4e358c74f9771fc4ddceda972f504416d51bf8f Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:52:16 -0300 Subject: [PATCH 06/25] Another witness equality to constant --- acvm-repo/acir/src/circuit/opcodes.rs | 7 +++++- acvm-repo/acir/src/parser/tests.rs | 22 +++++++++---------- .../noirc_evaluator/src/acir/tests/arrays.rs | 20 ++++++++--------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index ebb27bc9f1e..f7459f9b283 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -157,11 +157,16 @@ impl std::fmt::Display for Opcode { if coefficient.is_one() { // This is `wN + C = 0`, so show it as `wN = -C`. - let constant = -constant; write!(f, "{witness} = {constant}")?; return Ok(()); } + + if (-coefficient).is_one() { + // This is `-wN + C = 0`, so show it as `wN = C`. + write!(f, "{witness} = {constant}")?; + return Ok(()); + } } let mut printed_term = false; diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index b8569169ba9..84d6f0920ad 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -619,12 +619,12 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 - EXPR -1*w25 = 0 - EXPR -1*w27 = 0 + EXPR w25 = 0 + EXPR w27 = 0 MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) EXPR w28 = 111 - EXPR -1*w29 + 1 = 0 + EXPR w29 = 1 MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) EXPR w30 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] @@ -644,11 +644,11 @@ fn array_dynamic() { MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) - EXPR -1*w42 + 2 = 0 + EXPR w42 = 2 MEM (id: 0, read at: EXPR [ (1, w42) 0 ], value: EXPR [ (1, w43) 0 ]) - EXPR -1*w44 + 3 = 0 + EXPR w44 = 3 MEM (id: 0, read at: EXPR [ (1, w44) 0 ], value: EXPR [ (1, w45) 0 ]) - EXPR -1*w46 + 4 = 0 + EXPR w46 = 0 MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) EXPR -1*w31*w35 + w31*w39 + w35 - w48 = 0 @@ -664,11 +664,11 @@ fn array_dynamic() { EXPR -1*w31 - w55 + 1 = 0 EXPR -1*w31*w49 + w31*w50 + w49 - w56 = 0 EXPR w31*w54 + w55*w56 - 109 = 0 - EXPR -1*w57 + 246 = 0 - EXPR -1*w58 + 159 = 0 - EXPR -1*w59 + 32 = 0 - EXPR -1*w60 + 176 = 0 - EXPR -1*w61 + 8 = 0 + EXPR w57 = 246 + EXPR w58 = 159 + EXPR w59 = 32 + EXPR w60 = 176 + EXPR w61 = 8 INIT (id: 4, len: 5, witnesses: [w57, w58, w59, w60, w61]) MEM (id: 4, read at: EXPR [ (1, w7) 0 ], value: EXPR [ (1, w62) 0 ]) MEM (id: 4, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w63) 0 ]) diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index c7f148bbbd4..6925321ee2b 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -49,10 +49,10 @@ fn constant_array_access_out_of_bounds() { private parameters: [] public parameters: [] return values: [] - EXPR -1*w0 = 0 - EXPR -1*w1 + 1 = 0 + EXPR w0 = 0 + EXPR w1 = 1 INIT (id: 0, len: 2, witnesses: [w0, w1]) - EXPR -1*w2 + 5 = 0 + EXPR w2 = 5 MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) EXPR w3 = 0 "); @@ -120,13 +120,13 @@ fn generates_memory_op_for_dynamic_write() { public parameters: [] return values: [w4, w5, w6] INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -1*w7 + 10 = 0 + EXPR w7 = 10 MEM (id: 1, write EXPR [ (1, w7) 0 ] at: EXPR [ (1, w3) 0 ]) - EXPR -1*w8 = 0 + EXPR w8 = 0 MEM (id: 1, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) - EXPR -1*w10 + 1 = 0 + EXPR w10 = 1 MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) - EXPR -1*w12 + 2 = 0 + EXPR w12 = 2 MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) EXPR w4 - w9 = 0 EXPR w5 - w11 = 0 @@ -204,11 +204,11 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR -1*w4*w9 + 10*w4 + w9 - w10 = 0 MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) - EXPR -1*w11 = 0 + EXPR w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) - EXPR -1*w13 + 1 = 0 + EXPR w13 = 1 MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) - EXPR -1*w15 + 2 = 0 + EXPR w15 = 2 MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) EXPR w5 - w12 = 0 EXPR w6 - w14 = 0 From 8b0e22c487fc4ca5996cec360070ab34670f527c Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 12:58:01 -0300 Subject: [PATCH 07/25] Handle `-1` in first term --- acvm-repo/acir/src/circuit/opcodes.rs | 4 ++ acvm-repo/acir/src/parser/mod.rs | 2 +- acvm-repo/acir/src/parser/tests.rs | 68 +++++++++---------- .../noirc_evaluator/src/acir/tests/arrays.rs | 2 +- .../src/acir/tests/brillig_call.rs | 20 +++--- .../noirc_evaluator/src/acir/tests/call.rs | 6 +- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 7 files changed, 54 insertions(+), 50 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index f7459f9b283..bdbb92fe730 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -191,6 +191,8 @@ impl std::fmt::Display for Opcode { if coefficient.is_one() { write!(f, "{witness1}*{witness2}")?; + } else if (-coefficient).is_one() { + write!(f, "-{witness1}*{witness2}")?; } else { write!(f, "{coefficient}*{witness1}*{witness2}")?; } @@ -218,6 +220,8 @@ impl std::fmt::Display for Opcode { if coefficient.is_one() { write!(f, "{witness}")?; + } else if (-coefficient).is_one() { + write!(f, "-{witness}")?; } else { write!(f, "{coefficient}*{witness}")?; } diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index c6faf399692..ce7e734ce88 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -271,8 +271,8 @@ impl<'a> Parser<'a> { let mut linear_combinations = Vec::new(); let mut mul_terms = Vec::new(); let mut constant: Option = None; - let mut negative = false; let mut first = true; + let mut negative = self.eat(Token::Minus)?; loop { if let Some(w1) = self.eat_witness()? { diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 84d6f0920ad..a084369a318 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -122,7 +122,7 @@ fn assert_zero_with_mul_terms() { EXPR w3*w3 - w4 = 0 EXPR w4*w4 - w5 = 0 EXPR w5*w5 - w6 = 0 - EXPR -1*w2 + w6 = 0 + EXPR -w2 + w6 = 0 "; assert_circuit_roundtrip(src); } @@ -223,22 +223,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR -1*w44 + w60 = 0 - EXPR -1*w45 + w61 = 0 - EXPR -1*w46 + w62 = 0 - EXPR -1*w47 + w63 = 0 - EXPR -1*w48 + w64 = 0 - EXPR -1*w49 + w65 = 0 - EXPR -1*w50 + w66 = 0 - EXPR -1*w51 + w67 = 0 - EXPR -1*w52 + w68 = 0 - EXPR -1*w53 + w69 = 0 - EXPR -1*w54 + w70 = 0 - EXPR -1*w55 + w71 = 0 - EXPR -1*w56 + w72 = 0 - EXPR -1*w57 + w73 = 0 - EXPR -1*w58 + w74 = 0 - EXPR -1*w59 + w75 = 0 + EXPR -w44 + w60 = 0 + EXPR -w45 + w61 = 0 + EXPR -w46 + w62 = 0 + EXPR -w47 + w63 = 0 + EXPR -w48 + w64 = 0 + EXPR -w49 + w65 = 0 + EXPR -w50 + w66 = 0 + EXPR -w51 + w67 = 0 + EXPR -w52 + w68 = 0 + EXPR -w53 + w69 = 0 + EXPR -w54 + w70 = 0 + EXPR -w55 + w71 = 0 + EXPR -w56 + w72 = 0 + EXPR -w57 + w73 = 0 + EXPR -w58 + w74 = 0 + EXPR -w59 + w75 = 0 "; assert_circuit_roundtrip(src); } @@ -526,7 +526,7 @@ fn brillig_call() { return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "; assert_circuit_roundtrip(src); } @@ -541,7 +541,7 @@ fn brillig_call_with_predicate() { BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "; assert_circuit_roundtrip(src); } @@ -631,16 +631,16 @@ fn array_dynamic() { BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 - EXPR -1*w21*w31 + w21 - w33 = 0 + EXPR -w21*w31 + w21 - w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) - EXPR -1*w31*w34 + 2*w31 + w34 - w35 - 2 = 0 + EXPR -w31*w34 + 2*w31 + w34 - w35 - 2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 EXPR w31*w36 - w36 = 0 - EXPR -1*w21*w31 + w21 - w38 = 0 + EXPR -w21*w31 + w21 - w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) @@ -651,18 +651,18 @@ fn array_dynamic() { EXPR w46 = 0 MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR -1*w31*w35 + w31*w39 + w35 - w48 = 0 + EXPR -w31*w35 + w31*w39 + w35 - w48 = 0 MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) - EXPR -1*w31*w36 = 0 + EXPR -w31*w36 = 0 EXPR w21*w31 - w51 = 0 MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) - EXPR -1*w31*w52 + w52 - w53 = 0 + EXPR -w31*w52 + w52 - w53 = 0 MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) - EXPR -1*w31 - w55 + 1 = 0 - EXPR -1*w31*w49 + w31*w50 + w49 - w56 = 0 + EXPR -w31 - w55 + 1 = 0 + EXPR -w31*w49 + w31*w50 + w49 - w56 = 0 EXPR w31*w54 + w55*w56 - 109 = 0 EXPR w57 = 246 EXPR w58 = 159 @@ -681,20 +681,20 @@ fn array_dynamic() { BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] EXPR w18 - 4294967296*w68 - w69 = 0 - EXPR -1*w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 + EXPR -w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -1*w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 - EXPR -1*w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 + EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 + EXPR -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 EXPR w69*w72 + 268435455*w72 - w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR -1*w69 - 4294967296*w74 - w75 + 4294967299 = 0 - EXPR -1*w17*w74 + w17 - 3*w74 - w76 + 3 = 0 + EXPR -w69 - 4294967296*w74 - w75 + 4294967299 = 0 + EXPR -w17*w74 + w17 - 3*w74 - w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] - EXPR -1*w74*w76 + w76 - w77 = 0 + EXPR -w74*w76 + w76 - w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) EXPR w15*w74 - w74*w78 - w15 + w78 = 0 "; @@ -719,7 +719,7 @@ fn fold_basic() { return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "; assert_program_roundtrip(src); } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 6925321ee2b..9e3face0bab 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -202,7 +202,7 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { EXPR w3*w4 - w8 = 0 MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -1*w4*w9 + 10*w4 + w9 - w10 = 0 + EXPR -w4*w9 + 10*w4 + w9 - w10 = 0 MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) EXPR w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index 68a556d854a..bfe76a47592 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -159,15 +159,15 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 - w5 = 0 - EXPR -1*w2 + w4 = 0 + EXPR -w1*w4 + w0 - w5 = 0 + EXPR -w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] EXPR w2*w7 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] EXPR w2 - w9 - w10 - 1 = 0 BLACKBOX::RANGE [w10]:32 bits [] - EXPR -1*w2*w8 + w1 - w9 = 0 + EXPR -w2*w8 + w1 - w9 = 0 EXPR w8 = 1 unconstrained func 0 @@ -247,8 +247,8 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 - w5 = 0 - EXPR -1*w2 + w4 = 0 + EXPR -w1*w4 + w0 - w5 = 0 + EXPR -w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -259,7 +259,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w11]:32 bits [] EXPR w2 - w11 - w12 - 1 = 0 BLACKBOX::RANGE [w12]:32 bits [] - EXPR -1*w2*w10 + w1 - w11 = 0 + EXPR -w2*w10 + w1 - w11 = 0 EXPR w10 = 1 unconstrained func 0 @@ -381,8 +381,8 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -1*w1*w4 + w0 - w5 = 0 - EXPR -1*w2 + w4 = 0 + EXPR -w1*w4 + w0 - w5 = 0 + EXPR -w2 + w4 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -395,7 +395,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w12]:32 bits [] EXPR w2 - w12 - w13 - 1 = 0 BLACKBOX::RANGE [w13]:32 bits [] - EXPR -1*w2*w11 + w1 - w12 = 0 + EXPR -w2*w11 + w1 - w12 = 0 EXPR w11 = 1 func 1 @@ -410,7 +410,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w3*w4 + w5 - 1 = 0 EXPR w3*w5 = 0 EXPR w5 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 9a876850291..5eca1363d05 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -72,7 +72,7 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { public parameters: [] return values: [w2] EXPR w0 - w1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "); } @@ -115,7 +115,7 @@ fn call_output_as_next_call_input(inline_type: InlineType) { public parameters: [] return values: [w2] EXPR w0 - w1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "); } @@ -172,6 +172,6 @@ fn basic_nested_call(inline_type: InlineType) { public parameters: [] return values: [w2] EXPR w0 - w1 = 0 - EXPR -1*w0 + w2 = 0 + EXPR -w0 + w2 = 0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index 088b42b246e..a72290ce958 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR -1*w0*w1 + w2 = 0 + EXPR -w0*w1 + w2 = 0 "); } From 91eed2c6597df7a5dbc1cd81c30c4d1e3e858b7c Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 13:11:21 -0300 Subject: [PATCH 08/25] Stop parsing the old way --- acvm-repo/acir/src/parser/mod.rs | 9 --------- acvm-repo/acir/src/parser/tests.rs | 4 ++-- .../acvm/src/compiler/optimizers/general.rs | 12 +++++------ .../compiler/optimizers/merge_expressions.rs | 20 +++++++++---------- .../compiler/optimizers/redundant_range.rs | 12 +++++------ 5 files changed, 24 insertions(+), 33 deletions(-) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index ce7e734ce88..5d4d4e69d16 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -263,11 +263,6 @@ impl<'a> Parser<'a> { fn parse_assert_zero_expression(&mut self) -> ParseResult> { self.eat_keyword_or_error(Keyword::Expression)?; - // Support the old `EXPR [ ... ]` syntax for old tests, for now - if matches!(self.token.token(), Token::LeftBracket) { - return self.parse_arithmetic_expression_after_expr(); - } - let mut linear_combinations = Vec::new(); let mut mul_terms = Vec::new(); let mut constant: Option = None; @@ -356,10 +351,6 @@ impl<'a> Parser<'a> { fn parse_arithmetic_expression(&mut self) -> ParseResult> { self.eat_keyword_or_error(Keyword::Expression)?; - self.parse_arithmetic_expression_after_expr() - } - - fn parse_arithmetic_expression_after_expr(&mut self) -> ParseResult> { self.eat_or_error(Token::LeftBracket)?; let mut linear_combinations = Vec::new(); diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index a084369a318..05c6d99da3e 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -741,8 +741,8 @@ fn fold_basic_mismatched_ids() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] - EXPR [ (1, w0, w3) (-1, w1, w3) -1 ] - EXPR [ (-1, w0) (1, w2) 0 ] + EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR -w0 + w2 = 0 "; let result = Program::from_str(src).err().unwrap(); let ParserError::UnexpectedFunctionId { expected, found, .. } = result.get_error() else { diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index e28f7bf95d1..4a8d3dbc9d1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -93,7 +93,7 @@ mod tests { return values: [] // The first multiplication should be removed - EXPR [ (0, w0, w1) (1, w0, w1) 0 ] + EXPR 0*w0*w1 + w0*w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); @@ -115,7 +115,7 @@ mod tests { return values: [] // The first linear combination should be removed - EXPR [ (0, w0) (1, w1) 0 ] + EXPR 0*w0 + w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); @@ -138,7 +138,7 @@ mod tests { // There are all mul terms with the same variables so we should end up with just one // that is the sum of all the coefficients - EXPR [ (2, w0, w1) (3, w1, w0) (4, w0, w1) 0 ] + EXPR 2*w0*w1 + 3*w1*w0 + 4*w0*w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); @@ -158,7 +158,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (2, w0, w1) (3, w1, w0) (-5, w0, w1) 0 ] + EXPR 2*w0*w1 + 3*w1*w0 - 5*w0*w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); @@ -181,7 +181,7 @@ mod tests { // These are all linear terms with the same variable so we should end up with just one // that is the sum of all the coefficients - EXPR [ (1, w0) (2, w0) (3, w0) 0 ] + EXPR w0 + 2*w0 + 3*w0 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); @@ -201,7 +201,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (1, w0) (2, w0) (-3, w0) 0 ] + EXPR w0 + 2*w0 - 3*w0 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = optimize(circuit); diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 9d1d9134cd7..a74f07ca8a1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -304,8 +304,8 @@ mod tests { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [], outputs: [w1] - EXPR [ (2, w0) (3, w1) (1, w2) 1 ] - EXPR [ (2, w0) (2, w1) (1, w5) 1 ] + EXPR 2*w0 + 3*w1 + w2 + 1 = 0 + EXPR 2*w0 + 2*w1 + w5 + 1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = merge_expressions(circuit.clone()); @@ -319,8 +319,8 @@ mod tests { private parameters: [w0] public parameters: [] return values: [w1, w2] - EXPR [ (-1, w0, w0) (1, w1) 0 ] - EXPR [ (-1, w1) (1, w2) 0 ] + EXPR -w0*w0 + w1 = 0 + EXPR -w1 + w2 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = merge_expressions(circuit.clone()); @@ -334,10 +334,10 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR [ (1, w0, w0) (-1, w4) 0 ] - EXPR [ (1, w0, w1) (1, w5) 0 ] - EXPR [ (-1, w2) (1, w4) (1, w5) 0 ] - EXPR [ (1, w2) (-1, w3) (1, w4) (1, w5) 0 ] + EXPR w0*w0 - w4 = 0 + EXPR w0*w1 + w5 = 0 + EXPR -w2 + w4 + w5 = 0 + EXPR w2 - w3 + w4 + w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "; let circuit = Circuit::from_str(src).unwrap(); @@ -367,8 +367,8 @@ mod tests { return values: [w2] BRILLIG CALL func 0: inputs: [], outputs: [w3] BLACKBOX::AND [w0, w1]:8 bits [w4] - EXPR [ (1, w3) (-1, w4) 0 ] - EXPR [ (-1, w2) (1, w4) 0 ] + EXPR w3 - w4 = 0 + EXPR -w2 + w4 = 0 "; let circuit = Circuit::from_str(src).unwrap(); let optimized_circuit = merge_expressions(circuit.clone()); diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 131f6445de3..77126b0f5f9 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -349,10 +349,10 @@ mod tests { return values: [] BLACKBOX::RANGE [w1]:16 bits [] BLACKBOX::RANGE [w1]:16 bits [] - EXPR [ 0 ] - EXPR [ 0 ] - EXPR [ 0 ] - EXPR [ 0 ] + EXPR 0 = 0 + EXPR 0 = 0 + EXPR 0 = 0 + EXPR 0 = 0 "; let circuit = Circuit::from_str(src).unwrap(); @@ -382,7 +382,7 @@ mod tests { public parameters: [] return values: [] BLACKBOX::RANGE [w1]:16 bits [] - EXPR [ (1, w1) 0 ] + EXPR w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); @@ -420,7 +420,7 @@ mod tests { BLACKBOX::RANGE [w1]:64 bits [] // assert w1 == 0 - EXPR [ (1, w1) 0 ] + EXPR w1 = 0 "; let circuit = Circuit::from_str(src).unwrap(); From b06db65a8d109e6032c59c92521c80521afff8d3 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 13:20:10 -0300 Subject: [PATCH 09/25] Special case for `w0 = w1` --- acvm-repo/acir/src/circuit/opcodes.rs | 17 +++++++ acvm-repo/acir/src/parser/mod.rs | 9 +++- acvm-repo/acir/src/parser/tests.rs | 50 +++++++++---------- .../noirc_evaluator/src/acir/tests/arrays.rs | 12 ++--- .../src/acir/tests/brillig_call.rs | 8 +-- .../noirc_evaluator/src/acir/tests/call.rs | 20 ++++---- 6 files changed, 70 insertions(+), 46 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index bdbb92fe730..c3513222e24 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -169,6 +169,23 @@ impl std::fmt::Display for Opcode { } } + // Chec if it's `-wN * wM = 0` or `wN * -wM = 0` in which case we can + // print it as `wN = wM`. + if expr.mul_terms.is_empty() + && expr.linear_combinations.len() == 2 + && expr.q_c.is_zero() + { + let (coefficient1, witness1) = expr.linear_combinations[0]; + let (coefficient2, witness2) = expr.linear_combinations[1]; + + if (coefficient1.is_one() && (-coefficient2).is_one()) + || ((-coefficient1).is_one() && coefficient2.is_one()) + { + write!(f, "{witness1} = {witness2}")?; + return Ok(()); + } + } + let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 5d4d4e69d16..42610582398 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -275,9 +275,16 @@ impl<'a> Parser<'a> { let coefficient = if negative { -coefficient } else { coefficient }; if first && self.eat(Token::Equal)? { + if let Some(w2) = self.eat_witness()? { + // Here we parsed `coefficient*w1 = w2` so we produce `coefficient*w1 - w2 = 0` + linear_combinations.push((coefficient, w1)); + linear_combinations.push((-FieldElement::one(), w2)); + break; + } + let q_c = self.eat_field_or_error()?; - // Here we parsed `coefficient*witness = constant` so we produce `coefficient*witness - q_c = 0` + // Here we parsed `coefficient*w1 = constant` so we produce `coefficient*w1 - q_c = 0` linear_combinations.push((coefficient, w1)); constant = Some(-q_c); break; diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 05c6d99da3e..cd2d57f70ef 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -102,11 +102,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR w0 - w5 = 0 - EXPR w1 - w6 = 0 - EXPR w2 - w7 = 0 - EXPR w3 - w8 = 0 - EXPR w4 - w9 = 0 + EXPR w0 = w5 + EXPR w1 = w6 + EXPR w2 = w7 + EXPR w3 = w8 + EXPR w4 = w9 "; assert_circuit_roundtrip(src); } @@ -122,7 +122,7 @@ fn assert_zero_with_mul_terms() { EXPR w3*w3 - w4 = 0 EXPR w4*w4 - w5 = 0 EXPR w5*w5 - w6 = 0 - EXPR -w2 + w6 = 0 + EXPR w2 = w6 "; assert_circuit_roundtrip(src); } @@ -223,22 +223,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR -w44 + w60 = 0 - EXPR -w45 + w61 = 0 - EXPR -w46 + w62 = 0 - EXPR -w47 + w63 = 0 - EXPR -w48 + w64 = 0 - EXPR -w49 + w65 = 0 - EXPR -w50 + w66 = 0 - EXPR -w51 + w67 = 0 - EXPR -w52 + w68 = 0 - EXPR -w53 + w69 = 0 - EXPR -w54 + w70 = 0 - EXPR -w55 + w71 = 0 - EXPR -w56 + w72 = 0 - EXPR -w57 + w73 = 0 - EXPR -w58 + w74 = 0 - EXPR -w59 + w75 = 0 + EXPR w44 = w60 + EXPR w45 = w61 + EXPR w46 = w62 + EXPR w47 = w63 + EXPR w48 = w64 + EXPR w49 = w65 + EXPR w50 = w66 + EXPR w51 = w67 + EXPR w52 = w68 + EXPR w53 = w69 + EXPR w54 = w70 + EXPR w55 = w71 + EXPR w56 = w72 + EXPR w57 = w73 + EXPR w58 = w74 + EXPR w59 = w75 "; assert_circuit_roundtrip(src); } @@ -526,7 +526,7 @@ fn brillig_call() { return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w2 "; assert_circuit_roundtrip(src); } @@ -541,7 +541,7 @@ fn brillig_call_with_predicate() { BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w2 "; assert_circuit_roundtrip(src); } @@ -719,7 +719,7 @@ fn fold_basic() { return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w2 "; assert_program_roundtrip(src); } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 9e3face0bab..7579c054716 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -128,9 +128,9 @@ fn generates_memory_op_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) EXPR w12 = 2 MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) - EXPR w4 - w9 = 0 - EXPR w5 - w11 = 0 - EXPR w6 - w13 = 0 + EXPR w4 = w9 + EXPR w5 = w11 + EXPR w6 = w13 "); } @@ -210,9 +210,9 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) EXPR w15 = 2 MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) - EXPR w5 - w12 = 0 - EXPR w6 - w14 = 0 - EXPR w7 - w16 = 0 + EXPR w5 = w12 + EXPR w6 = w14 + EXPR w7 = w16 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index bfe76a47592..a468340ea07 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -160,7 +160,7 @@ fn multiple_brillig_stdlib_calls() { EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 - EXPR -w2 + w4 = 0 + EXPR w2 = w4 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] EXPR w2*w7 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] @@ -248,7 +248,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 - EXPR -w2 + w4 = 0 + EXPR w2 = w4 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -382,7 +382,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 - EXPR -w2 + w4 = 0 + EXPR w2 = w4 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] @@ -410,7 +410,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w3*w4 + w5 - 1 = 0 EXPR w3*w5 = 0 EXPR w5 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w2 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 5eca1363d05..b7b7fff5a2d 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,15 +64,15 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 - w3 = 0 + EXPR w2 = w3 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w1 + EXPR w0 = w2 "); } @@ -107,15 +107,15 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR w2 - w3 = 0 + EXPR w2 = w3 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w1 + EXPR w0 = w2 "); } @@ -154,7 +154,7 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 - w3 = 0 + EXPR w2 = w3 func 1 current witness: w4 @@ -164,14 +164,14 @@ fn basic_nested_call(inline_type: InlineType) { EXPR w0 - w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR w2 - w4 = 0 + EXPR w2 = w4 func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w1 + EXPR w0 = w2 "); } From 25cdb7574ffb4e31735f5d3637a6f9fd01bed9bc Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 13:28:01 -0300 Subject: [PATCH 10/25] One more tiny change --- acvm-repo/acir/src/parser/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index cd2d57f70ef..88dcd54dd23 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -742,7 +742,7 @@ fn fold_basic_mismatched_ids() { return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR -w0 + w2 = 0 + EXPR w0 = w2 "; let result = Program::from_str(src).err().unwrap(); let ParserError::UnexpectedFunctionId { expected, found, .. } = result.get_error() else { From 62c1e33c092675affdc11e739ed8775b64162888 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 14:05:43 -0300 Subject: [PATCH 11/25] Don't print zero coefficients --- .../acir/src/native_types/expression/mod.rs | 7 +- acvm-repo/acir/src/parser/mod.rs | 8 +-- acvm-repo/acir/src/parser/tests.rs | 64 +++++++++---------- .../compiler/optimizers/redundant_range.rs | 6 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 24 +++---- .../src/acir/tests/brillig_call.rs | 46 ++++++------- 6 files changed, 77 insertions(+), 78 deletions(-) diff --git a/acvm-repo/acir/src/native_types/expression/mod.rs b/acvm-repo/acir/src/native_types/expression/mod.rs index bcbc1aeaced..f3b0d999c6f 100644 --- a/acvm-repo/acir/src/native_types/expression/mod.rs +++ b/acvm-repo/acir/src/native_types/expression/mod.rs @@ -58,9 +58,12 @@ impl std::fmt::Display for Expression { for i in &self.linear_combinations { write!(f, "({}, {}) ", i.0, i.1)?; } - write!(f, "{}", self.q_c)?; - write!(f, " ]") + let q_c_as_string = self.q_c.to_string(); + if q_c_as_string != "0" { + write!(f, "{} ", self.q_c)?; + } + write!(f, "]") } } diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 42610582398..78645d3c72f 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -404,9 +404,8 @@ impl<'a> Parser<'a> { } } - let Some(q_c) = constant else { - return Err(ParserError::MissingConstantTerm { span: self.token.span() }); - }; + // If a constant isn't provided, we default it to zero + let q_c = constant.unwrap_or_default(); Ok(Expression { mul_terms, linear_combinations, q_c }) } @@ -1114,8 +1113,6 @@ pub(crate) enum ParserError { ExpectedZero { found: Token, span: Span }, #[error("Duplicate constant term in native Expression")] DuplicatedConstantTerm { found: Token, span: Span }, - #[error("Missing constant term in native Expression")] - MissingConstantTerm { span: Span }, #[error("Expected valid black box function name, found '{found}'")] ExpectedBlackBoxFuncName { found: Token, span: Span }, #[error("Number does not fit in u32, got: '{number}'")] @@ -1142,7 +1139,6 @@ impl ParserError { | ExpectedWitness { span, .. } | ExpectedZero { span, .. } | DuplicatedConstantTerm { span, .. } - | MissingConstantTerm { span } | ExpectedBlackBoxFuncName { span, .. } | IntegerLargerThanU32 { span, .. } | IncorrectInputLength { span, .. } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 88dcd54dd23..556294cca7a 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -463,7 +463,7 @@ fn memory_read() { private parameters: [] public parameters: [] return values: [] - MEM (id: 0, read at: EXPR [ (1, w0) 0 ], value: EXPR [ (1, w1) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w0) ], value: EXPR [ (1, w1) ]) "; assert_circuit_roundtrip(src); } @@ -475,7 +475,7 @@ fn memory_write() { private parameters: [] public parameters: [] return values: [] - MEM (id: 3, write EXPR [ (1, w0) 0 ] at: EXPR [ (1, w1) 0 ]) + MEM (id: 3, write EXPR [ (1, w0) ] at: EXPR [ (1, w1) ]) "; assert_circuit_roundtrip(src); } @@ -524,7 +524,7 @@ fn brillig_call() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; @@ -539,7 +539,7 @@ fn brillig_call_with_predicate() { public parameters: [] return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] - inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] + inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; @@ -612,27 +612,27 @@ fn array_dynamic() { BLACKBOX::RANGE [w20]:32 bits [] EXPR w20 - w21 - 5 = 0 EXPR w21 - w22 - 3 = 0 - MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w23) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w21) ], value: EXPR [ (1, w23) ]) EXPR w23 = 111 - MEM (id: 0, read at: EXPR [ (1, w22) 0 ], value: EXPR [ (1, w24) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w22) ], value: EXPR [ (1, w24) ]) EXPR w24 = 101 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 EXPR w25 = 0 EXPR w27 = 0 - MEM (id: 0, write EXPR [ (1, w27) 0 ] at: EXPR [ (1, w22) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w21) 0 ], value: EXPR [ (1, w28) 0 ]) + MEM (id: 0, write EXPR [ (1, w27) ] at: EXPR [ (1, w22) ]) + MEM (id: 0, read at: EXPR [ (1, w21) ], value: EXPR [ (1, w28) ]) EXPR w28 = 111 EXPR w29 = 1 - MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w30) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w29) ], value: EXPR [ (1, w30) ]) EXPR w30 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 EXPR -w21*w31 + w21 - w33 = 0 - MEM (id: 0, read at: EXPR [ (1, w33) 0 ], value: EXPR [ (1, w34) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w33) ], value: EXPR [ (1, w34) ]) EXPR -w31*w34 + 2*w31 + w34 - w35 - 2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] @@ -641,26 +641,26 @@ fn array_dynamic() { EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 EXPR w31*w36 - w36 = 0 EXPR -w21*w31 + w21 - w38 = 0 - MEM (id: 0, read at: EXPR [ (1, w38) 0 ], value: EXPR [ (1, w39) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w27) 0 ], value: EXPR [ (1, w40) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w29) 0 ], value: EXPR [ (1, w41) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w38) ], value: EXPR [ (1, w39) ]) + MEM (id: 0, read at: EXPR [ (1, w27) ], value: EXPR [ (1, w40) ]) + MEM (id: 0, read at: EXPR [ (1, w29) ], value: EXPR [ (1, w41) ]) EXPR w42 = 2 - MEM (id: 0, read at: EXPR [ (1, w42) 0 ], value: EXPR [ (1, w43) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w42) ], value: EXPR [ (1, w43) ]) EXPR w44 = 3 - MEM (id: 0, read at: EXPR [ (1, w44) 0 ], value: EXPR [ (1, w45) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w44) ], value: EXPR [ (1, w45) ]) EXPR w46 = 0 - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w47) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w47) ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) EXPR -w31*w35 + w31*w39 + w35 - w48 = 0 - MEM (id: 3, write EXPR [ (1, w48) 0 ] at: EXPR [ (1, w38) 0 ]) - MEM (id: 3, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w49) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w50) 0 ]) + MEM (id: 3, write EXPR [ (1, w48) ] at: EXPR [ (1, w38) ]) + MEM (id: 3, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w49) ]) + MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w50) ]) EXPR -w31*w36 = 0 EXPR w21*w31 - w51 = 0 - MEM (id: 0, read at: EXPR [ (1, w51) 0 ], value: EXPR [ (1, w52) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w51) ], value: EXPR [ (1, w52) ]) EXPR -w31*w52 + w52 - w53 = 0 - MEM (id: 0, write EXPR [ (1, w53) 0 ] at: EXPR [ (1, w51) 0 ]) - MEM (id: 0, read at: EXPR [ (1, w46) 0 ], value: EXPR [ (1, w54) 0 ]) + MEM (id: 0, write EXPR [ (1, w53) ] at: EXPR [ (1, w51) ]) + MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w54) ]) EXPR -w31 - w55 + 1 = 0 EXPR -w31*w49 + w31*w50 + w49 - w56 = 0 EXPR w31*w54 + w55*w56 - 109 = 0 @@ -670,14 +670,14 @@ fn array_dynamic() { EXPR w60 = 176 EXPR w61 = 8 INIT (id: 4, len: 5, witnesses: [w57, w58, w59, w60, w61]) - MEM (id: 4, read at: EXPR [ (1, w7) 0 ], value: EXPR [ (1, w62) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w63) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w9) 0 ], value: EXPR [ (1, w64) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w65) 0 ]) - MEM (id: 4, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w66) 0 ]) - BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) 0 ]], outputs: [w67] + MEM (id: 4, read at: EXPR [ (1, w7) ], value: EXPR [ (1, w62) ]) + MEM (id: 4, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w63) ]) + MEM (id: 4, read at: EXPR [ (1, w9) ], value: EXPR [ (1, w64) ]) + MEM (id: 4, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w65) ]) + MEM (id: 4, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w66) ]) + BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) ]], outputs: [w67] EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 = 0 - BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) 0 ], EXPR [ 4294967296 ]], outputs: [w68, w69] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] EXPR w18 - 4294967296*w68 - w69 = 0 @@ -695,7 +695,7 @@ fn array_dynamic() { EXPR -w17*w74 + w17 - 3*w74 - w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] EXPR -w74*w76 + w76 - w77 = 0 - MEM (id: 1, read at: EXPR [ (1, w77) 0 ], value: EXPR [ (1, w78) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w77) ], value: EXPR [ (1, w78) ]) EXPR w15*w74 - w74*w78 - w15 + w78 = 0 "; assert_circuit_roundtrip(src); @@ -717,7 +717,7 @@ fn fold_basic() { private parameters: [w0, w1] public parameters: [] return values: [w2] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; @@ -740,7 +740,7 @@ fn fold_basic_mismatched_ids() { private parameters: [w0, w1] public parameters: [] return values: [w2] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; diff --git a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs index 77126b0f5f9..b18582a89c4 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/redundant_range.rs @@ -441,9 +441,9 @@ mod tests { public parameters: [] return values: [] BLACKBOX::RANGE [w1]:32 bits [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [] BLACKBOX::RANGE [w1]:16 bits [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [] EXPR w1 = 0 "); @@ -478,7 +478,7 @@ mod tests { public parameters: [] return values: [] INIT (id: 0, len: 8, witnesses: [w0, w0, w0, w0, w0, w0, w0, w0]) - MEM (id: 0, read at: EXPR [ (1, w1) 0 ], value: EXPR [ (1, w2) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w1) ], value: EXPR [ (1, w2) ]) "); } } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 7579c054716..9d2276eabed 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -53,7 +53,7 @@ fn constant_array_access_out_of_bounds() { EXPR w1 = 1 INIT (id: 0, len: 2, witnesses: [w0, w1]) EXPR w2 = 5 - MEM (id: 0, read at: EXPR [ (1, w2) 0 ], value: EXPR [ (1, w3) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w2) ], value: EXPR [ (1, w3) ]) EXPR w3 = 0 "); } @@ -96,7 +96,7 @@ fn generates_memory_op_for_dynamic_read() { public parameters: [] return values: [] INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) - MEM (id: 0, read at: EXPR [ (1, w3) 0 ], value: EXPR [ (1, w4) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w3) ], value: EXPR [ (1, w4) ]) EXPR w4 = 10 "); } @@ -121,13 +121,13 @@ fn generates_memory_op_for_dynamic_write() { return values: [w4, w5, w6] INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR w7 = 10 - MEM (id: 1, write EXPR [ (1, w7) 0 ] at: EXPR [ (1, w3) 0 ]) + MEM (id: 1, write EXPR [ (1, w7) ] at: EXPR [ (1, w3) ]) EXPR w8 = 0 - MEM (id: 1, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w9) ]) EXPR w10 = 1 - MEM (id: 1, read at: EXPR [ (1, w10) 0 ], value: EXPR [ (1, w11) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w11) ]) EXPR w12 = 2 - MEM (id: 1, read at: EXPR [ (1, w12) 0 ], value: EXPR [ (1, w13) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w12) ], value: EXPR [ (1, w13) ]) EXPR w4 = w9 EXPR w5 = w11 EXPR w6 = w13 @@ -162,7 +162,7 @@ fn generates_predicated_index_for_dynamic_read() { BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] EXPR w3*w4 - w5 = 0 - MEM (id: 0, read at: EXPR [ (1, w5) 0 ], value: EXPR [ (1, w6) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w5) ], value: EXPR [ (1, w6) ]) EXPR w6 = 10 "); } @@ -200,16 +200,16 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] EXPR w3*w4 - w8 = 0 - MEM (id: 0, read at: EXPR [ (1, w8) 0 ], value: EXPR [ (1, w9) 0 ]) + MEM (id: 0, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w9) ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR -w4*w9 + 10*w4 + w9 - w10 = 0 - MEM (id: 1, write EXPR [ (1, w10) 0 ] at: EXPR [ (1, w8) 0 ]) + MEM (id: 1, write EXPR [ (1, w10) ] at: EXPR [ (1, w8) ]) EXPR w11 = 0 - MEM (id: 1, read at: EXPR [ (1, w11) 0 ], value: EXPR [ (1, w12) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w12) ]) EXPR w13 = 1 - MEM (id: 1, read at: EXPR [ (1, w13) 0 ], value: EXPR [ (1, w14) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w13) ], value: EXPR [ (1, w14) ]) EXPR w15 = 2 - MEM (id: 1, read at: EXPR [ (1, w15) 0 ], value: EXPR [ (1, w16) 0 ]) + MEM (id: 1, read at: EXPR [ (1, w15) ], value: EXPR [ (1, w16) ]) EXPR w5 = w12 EXPR w6 = w14 EXPR w7 = w16 diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index a468340ea07..cac103cfb96 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -45,12 +45,12 @@ fn multiple_brillig_calls_one_bytecode() { private parameters: [w0, w1] public parameters: [] return values: [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w2] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w3] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w5] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w6] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w2] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w3] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w5] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w6] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w7] unconstrained func 0 0: @2 = const u32 1 @@ -152,18 +152,18 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) ]], outputs: [w3] EXPR w1*w3 - 1 = 0 - BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 - BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w7] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [w7] EXPR w2*w7 - 1 = 0 - BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w8, w9] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] EXPR w2 - w9 - w10 - 1 = 0 BLACKBOX::RANGE [w10]:32 bits [] @@ -240,22 +240,22 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] EXPR w1*w3 - 1 = 0 - BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] + BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w9] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w9] EXPR w2*w9 - 1 = 0 - BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w10, w11] + BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] EXPR w2 - w11 - w12 - 1 = 0 BLACKBOX::RANGE [w12]:32 bits [] @@ -374,24 +374,24 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) 0 ]], outputs: [w3] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] EXPR w1*w3 - 1 = 0 - BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w4, w5] + BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w7] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] - BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) 0 ], EXPR [ (1, w1) 0 ]], outputs: [w8] + BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] - BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) 0 ]], outputs: [w10] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w10] EXPR w2*w10 - 1 = 0 - BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) 0 ], EXPR [ (1, w2) 0 ]], outputs: [w11, w12] + BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] EXPR w2 - w12 - w13 - 1 = 0 BLACKBOX::RANGE [w13]:32 bits [] @@ -406,7 +406,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] EXPR w0 - w1 - w3 = 0 - BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) 0 ]], outputs: [w4] + BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) ]], outputs: [w4] EXPR w3*w4 + w5 - 1 = 0 EXPR w3*w5 = 0 EXPR w5 = 0 From 27fedc6ca2554a073fe17c4ee6e205b91daf93a0 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 14:38:42 -0300 Subject: [PATCH 12/25] Try to show q_c on the right-hand side of the equation --- acvm-repo/acir/src/circuit/mod.rs | 2 +- acvm-repo/acir/src/circuit/opcodes.rs | 13 +++++--- acvm-repo/acir/src/parser/mod.rs | 16 ++++++---- acvm-repo/acir/src/parser/tests.rs | 32 +++++++++---------- .../src/acir/tests/brillig_call.rs | 26 +++++++-------- .../noirc_evaluator/src/acir/tests/call.rs | 2 +- 6 files changed, 49 insertions(+), 42 deletions(-) diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 1dd1e2f8bb0..85056107edc 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -544,7 +544,7 @@ mod tests { private parameters: [] public parameters: [w2] return values: [w2] - EXPR 2*w1 + 8 = 0 + EXPR 2*w1 = -8 BLACKBOX::RANGE [w1]:8 bits [] BLACKBOX::AND [w1, w2]:4 bits [w3] BLACKBOX::KECCAKF1600 [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index c3513222e24..fe4d2ffaa28 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -246,9 +246,13 @@ impl std::fmt::Display for Opcode { printed_term = true; } - if !expr.q_c.is_zero() - || (expr.mul_terms.is_empty() && expr.linear_combinations.is_empty()) - { + if printed_term { + // Change `... + c = 0` to `... = -c` + let q_c = -expr.q_c; + write!(f, " = {q_c}")?; + } else if expr.q_c.is_zero() { + write!(f, "0 = 0")?; + } else { let coefficient = expr.q_c; let coefficient_as_string = coefficient.to_string(); let coefficient_is_negative = coefficient_as_string.starts_with('-'); @@ -267,10 +271,9 @@ impl std::fmt::Display for Opcode { coefficient }; write!(f, "{coefficient}")?; + write!(f, " = 0")?; } - write!(f, " = 0")?; - Ok(()) } Opcode::BlackBoxFuncCall(g) => g.fmt(f), diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 78645d3c72f..0ed30431541 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -336,12 +336,19 @@ impl<'a> Parser<'a> { if self.eat(Token::Equal)? { let zero_token = self.token.token().clone(); let span = self.token.span(); - let Some(zero) = self.eat_field_element()? else { + let Some(q_c) = self.eat_field_element()? else { return self.expected_field_element(); }; - if !zero.is_zero() { - return Err(ParserError::ExpectedZero { found: zero_token, span }); + if !q_c.is_zero() { + if constant.is_some() { + return Err(ParserError::DuplicatedConstantTerm { + found: zero_token, + span, + }); + } + // If we have `... = q_c` we produce `... - q_c = 0` + constant = Some(-q_c); } break; @@ -1109,8 +1116,6 @@ pub(crate) enum ParserError { ExpectedFieldElement { found: Token, span: Span }, #[error("Expected a witness index, found '{found}'")] ExpectedWitness { found: Token, span: Span }, - #[error("Expected a zero, found '{found}'")] - ExpectedZero { found: Token, span: Span }, #[error("Duplicate constant term in native Expression")] DuplicatedConstantTerm { found: Token, span: Span }, #[error("Expected valid black box function name, found '{found}'")] @@ -1137,7 +1142,6 @@ impl ParserError { | ExpectedIdentifier { span, .. } | ExpectedFieldElement { span, .. } | ExpectedWitness { span, .. } - | ExpectedZero { span, .. } | DuplicatedConstantTerm { span, .. } | ExpectedBlackBoxFuncName { span, .. } | IntegerLargerThanU32 { span, .. } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 556294cca7a..9e31399f246 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -525,7 +525,7 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR w0*w3 - w1*w3 = 1 EXPR w0 = w2 "; assert_circuit_roundtrip(src); @@ -540,7 +540,7 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR w0*w3 - w1*w3 = 1 EXPR w0 = w2 "; assert_circuit_roundtrip(src); @@ -610,15 +610,15 @@ fn array_dynamic() { BLACKBOX::RANGE [w19]:32 bits [] EXPR w5 - w19 - w20 = 0 BLACKBOX::RANGE [w20]:32 bits [] - EXPR w20 - w21 - 5 = 0 - EXPR w21 - w22 - 3 = 0 + EXPR w20 - w21 = 5 + EXPR w21 - w22 = 3 MEM (id: 0, read at: EXPR [ (1, w21) ], value: EXPR [ (1, w23) ]) EXPR w23 = 111 MEM (id: 0, read at: EXPR [ (1, w22) ], value: EXPR [ (1, w24) ]) EXPR w24 = 101 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 + EXPR w22 - 4294967296*w25 - w26 = -4294967291 EXPR w25 = 0 EXPR w27 = 0 MEM (id: 0, write EXPR [ (1, w27) ] at: EXPR [ (1, w22) ]) @@ -630,15 +630,15 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 + EXPR w21 - 4294967296*w31 - w32 = -4294967286 EXPR -w21*w31 + w21 - w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) ], value: EXPR [ (1, w34) ]) - EXPR -w31*w34 + 2*w31 + w34 - w35 - 2 = 0 + EXPR -w31*w34 + 2*w31 + w34 - w35 = 2 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 + EXPR w21 - 4294967296*w36 - w37 = -4294967291 EXPR w31*w36 - w36 = 0 EXPR -w21*w31 + w21 - w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) ], value: EXPR [ (1, w39) ]) @@ -661,9 +661,9 @@ fn array_dynamic() { EXPR -w31*w52 + w52 - w53 = 0 MEM (id: 0, write EXPR [ (1, w53) ] at: EXPR [ (1, w51) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w54) ]) - EXPR -w31 - w55 + 1 = 0 + EXPR -w31 - w55 = -1 EXPR -w31*w49 + w31*w50 + w49 - w56 = 0 - EXPR w31*w54 + w55*w56 - 109 = 0 + EXPR w31*w54 + w55*w56 = 109 EXPR w57 = 246 EXPR w58 = 159 EXPR w59 = 32 @@ -676,23 +676,23 @@ fn array_dynamic() { MEM (id: 4, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w65) ]) MEM (id: 4, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w66) ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) ]], outputs: [w67] - EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 = 0 + EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 = 1 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] EXPR w18 - 4294967296*w68 - w69 = 0 - EXPR -w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 + EXPR -w68 - w70 = -5096253676302562286669017222071363378443840053029366383258766538131 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 + EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 = 1 EXPR -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 EXPR w69*w72 + 268435455*w72 - w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR -w69 - 4294967296*w74 - w75 + 4294967299 = 0 - EXPR -w17*w74 + w17 - 3*w74 - w76 + 3 = 0 + EXPR -w69 - 4294967296*w74 - w75 = -4294967299 + EXPR -w17*w74 + w17 - 3*w74 - w76 = -3 BLACKBOX::RANGE [w76]:32 bits [] EXPR -w74*w76 + w76 - w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) ], value: EXPR [ (1, w78) ]) @@ -718,7 +718,7 @@ fn fold_basic() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR w0*w3 - w1*w3 = 1 EXPR w0 = w2 "; assert_program_roundtrip(src); diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index cac103cfb96..049cfef5c26 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,19 +153,19 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR w1*w3 = 1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w1 - w5 - w6 = 1 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [w7] - EXPR w2*w7 - 1 = 0 + EXPR w2*w7 = 1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR w2 - w9 - w10 - 1 = 0 + EXPR w2 - w9 - w10 = 1 BLACKBOX::RANGE [w10]:32 bits [] EXPR -w2*w8 + w1 - w9 = 0 EXPR w8 = 1 @@ -241,11 +241,11 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR w1*w3 = 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w1 - w5 - w6 = 1 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 @@ -254,10 +254,10 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w9] - EXPR w2*w9 - 1 = 0 + EXPR w2*w9 = 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR w2 - w11 - w12 - 1 = 0 + EXPR w2 - w11 - w12 = 1 BLACKBOX::RANGE [w12]:32 bits [] EXPR -w2*w10 + w1 - w11 = 0 EXPR w10 = 1 @@ -375,11 +375,11 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR w1*w3 = 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w1 - w5 - w6 = 1 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 @@ -390,10 +390,10 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w10] - EXPR w2*w10 - 1 = 0 + EXPR w2*w10 = 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR w2 - w12 - w13 - 1 = 0 + EXPR w2 - w12 - w13 = 1 BLACKBOX::RANGE [w13]:32 bits [] EXPR -w2*w11 + w1 - w12 = 0 EXPR w11 = 1 @@ -407,7 +407,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] EXPR w0 - w1 - w3 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) ]], outputs: [w4] - EXPR w3*w4 + w5 - 1 = 0 + EXPR w3*w4 + w5 = 1 EXPR w3*w5 = 0 EXPR w5 = 0 EXPR w0 = w2 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index b7b7fff5a2d..a9b59ff6478 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -161,7 +161,7 @@ fn basic_nested_call(inline_type: InlineType) { private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w3 + 2 = 0 + EXPR w0 - w3 = -2 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] EXPR w2 = w4 From fb83a4aa99abc6c936bf24c947d922fa8387509e Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 15:07:03 -0300 Subject: [PATCH 13/25] Use new syntax in comments --- compiler/noirc_evaluator/src/acir/tests/arrays.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 9d2276eabed..0b75317345f 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -149,7 +149,7 @@ fn generates_predicated_index_for_dynamic_read() { // w0, w1, w2 represents the array // So w3 represents our index and w4 is our predicate - // We can see that before the read we have `EXPR [ (1, w3, w4) (-1, w5) 0 ]` + // We can see that before the read we have `w3*w4 - w5 = 0` // As the index is zero this is a simplified version of `index*predicate + (1-predicate)*offset` // w5 is then used as the index which we use to read from the memory block assert_circuit_snapshot!(program, @r" @@ -180,15 +180,15 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { let program = ssa_to_acir_program(src); // Similar to the `generates_predicated_index_for_dynamic_read` test we can - // see how `EXPR [ (1, w3, w4) (-1, w8) 0 ]` forms our predicated index. + // see how `w3*w4 - w8 = 0` forms our predicated index. // However, now we also have extra logic for generating a dummy value. // The original value we want to write is `Field 10` and our predicate is `w4`. // We read the value at the predicated index into `w9`. This is our dummy value. // We can then see how we form our new store value with: - // `EXPR [ (-1, w4, w9) (10, w4) (1, w9) (-1, w10) 0 ]` -> (predicate*value + (1-predicate)*dummy) - // `(10, w4)` -> predicate*value - // `(-1, w4, w9)` -> (-predicate * dummy) - // `(1, w9)` -> dummy + // `EXPR -w4*w9 + 10*w4 + w9 - w10 = 0` -> (predicate*value + (1-predicate)*dummy) + // `10*w4` -> predicate*value + // `-w4*w9` -> (-predicate * dummy) + // `w9` -> dummy // As expected, we then store `w10` at the predicated index `w8`. assert_circuit_snapshot!(program, @r" func 0 From 32304155a72b46552436a587b1ee72dc12d7f589 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 23 Sep 2025 16:50:22 -0300 Subject: [PATCH 14/25] Update acvm-repo/acir/src/circuit/opcodes.rs --- acvm-repo/acir/src/circuit/opcodes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index fe4d2ffaa28..c53ec06e9d2 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -169,7 +169,7 @@ impl std::fmt::Display for Opcode { } } - // Chec if it's `-wN * wM = 0` or `wN * -wM = 0` in which case we can + // Check if it's `-wN * wM = 0` or `wN * -wM = 0` in which case we can // print it as `wN = wM`. if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 2 From accc53da0b5c93799c3dab094084e1d2ade31018 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 24 Sep 2025 09:36:49 -0300 Subject: [PATCH 15/25] Simpler and better parsing --- acvm-repo/acir/src/parser/mod.rs | 159 ++++++++++++++++--------------- 1 file changed, 83 insertions(+), 76 deletions(-) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 0ed30431541..b83bfbb3858 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -261,67 +261,44 @@ impl<'a> Parser<'a> { } fn parse_assert_zero_expression(&mut self) -> ParseResult> { + // 'EXPR' self.eat_keyword_or_error(Keyword::Expression)?; - let mut linear_combinations = Vec::new(); - let mut mul_terms = Vec::new(); - let mut constant: Option = None; - let mut first = true; - let mut negative = self.eat(Token::Minus)?; + // Parse the left-hand side terms + let lhs_terms = self.parse_terms_or_error()?; - loop { - if let Some(w1) = self.eat_witness()? { - let coefficient = FieldElement::one(); - let coefficient = if negative { -coefficient } else { coefficient }; - - if first && self.eat(Token::Equal)? { - if let Some(w2) = self.eat_witness()? { - // Here we parsed `coefficient*w1 = w2` so we produce `coefficient*w1 - w2 = 0` - linear_combinations.push((coefficient, w1)); - linear_combinations.push((-FieldElement::one(), w2)); - break; - } + // '=' + self.eat_or_error(Token::Equal)?; - let q_c = self.eat_field_or_error()?; + // Parse the right-hand side terms + let rhs_terms = self.parse_terms_or_error()?; - // Here we parsed `coefficient*w1 = constant` so we produce `coefficient*w1 - q_c = 0` - linear_combinations.push((coefficient, w1)); - constant = Some(-q_c); - break; - } + // "Move" the terms to the left by negating them + let rhs_terms = rhs_terms.into_iter().map(|term| term.negate()).collect::>(); - if self.eat(Token::Star)? { - let w2 = self.eat_witness_or_error()?; - mul_terms.push((coefficient, w1, w2)); - } else { - linear_combinations.push((coefficient, w1)); - } - } else if let Some(coefficient) = self.eat_field_element()? { - let coefficient = if negative { -coefficient } else { coefficient }; - - if self.eat(Token::Star)? { - let w1 = self.eat_witness_or_error()?; + // Gather all terms, summing the constants + let mut q_c = FieldElement::zero(); + let mut linear_combinations = Vec::new(); + let mut mul_terms = Vec::new(); - if self.eat(Token::Star)? { - let w2 = self.eat_witness_or_error()?; - mul_terms.push((coefficient, w1, w2)); - } else { - linear_combinations.push((coefficient, w1)); - } - } else { - if constant.is_some() { - return Err(ParserError::DuplicatedConstantTerm { - found: self.token.token().clone(), - span: self.token.span(), - }); - } - constant = Some(coefficient); - } - } else { - return self.expected_field_element(); + for term in lhs_terms.into_iter().chain(rhs_terms) { + match term { + Term::Constant(c) => q_c += c, + Term::Linear(c, w) => linear_combinations.push((c, w)), + Term::Multiplication(c, w1, w2) => mul_terms.push((c, w1, w2)), } + } - first = false; + Ok(Expression { mul_terms, linear_combinations, q_c }) + } + + fn parse_terms_or_error(&mut self) -> ParseResult> { + let mut terms = Vec::new(); + let mut negative = self.eat(Token::Minus)?; + loop { + let term = self.parse_term_or_error()?; + let term = if negative { term.negate() } else { term }; + terms.push(term); if self.eat(Token::Plus)? { negative = false; @@ -333,34 +310,37 @@ impl<'a> Parser<'a> { continue; } - if self.eat(Token::Equal)? { - let zero_token = self.token.token().clone(); - let span = self.token.span(); - let Some(q_c) = self.eat_field_element()? else { - return self.expected_field_element(); - }; - - if !q_c.is_zero() { - if constant.is_some() { - return Err(ParserError::DuplicatedConstantTerm { - found: zero_token, - span, - }); - } - // If we have `... = q_c` we produce `... - q_c = 0` - constant = Some(-q_c); - } + break; + } + Ok(terms) + } - break; + fn parse_term_or_error(&mut self) -> ParseResult { + if let Some(coefficient) = self.eat_field_element()? { + if self.eat(Token::Star)? { + let w1 = self.eat_witness_or_error()?; + self.parse_linear_or_multiplication_term(coefficient, w1) + } else { + Ok(Term::Constant(coefficient)) } - - return self.expected_token(Token::Equal); + } else if let Some(w1) = self.eat_witness()? { + self.parse_linear_or_multiplication_term(FieldElement::one(), w1) + } else { + self.expected_term() } + } - // If a constant isn't provided, we default it to zero - let q_c = constant.unwrap_or_default(); - - Ok(Expression { mul_terms, linear_combinations, q_c }) + fn parse_linear_or_multiplication_term( + &mut self, + coefficient: FieldElement, + w1: Witness, + ) -> Result { + if self.eat(Token::Star)? { + let w2 = self.eat_witness_or_error()?; + Ok(Term::Multiplication(coefficient, w1, w2)) + } else { + Ok(Term::Linear(coefficient, w1)) + } } fn parse_arithmetic_expression(&mut self) -> ParseResult> { @@ -1079,6 +1059,13 @@ impl<'a> Parser<'a> { }) } + fn expected_term(&mut self) -> ParseResult { + Err(ParserError::ExpectedTerm { + found: self.token.token().clone(), + span: self.token.span(), + }) + } + fn expected_token(&mut self, token: Token) -> ParseResult { Err(ParserError::ExpectedToken { token, @@ -1100,6 +1087,23 @@ fn eof_spanned_token() -> SpannedToken { SpannedToken::new(Token::Eof, Default::default()) } +#[derive(Debug, Clone, Copy)] +enum Term { + Constant(FieldElement), + Linear(FieldElement, Witness), + Multiplication(FieldElement, Witness, Witness), +} + +impl Term { + fn negate(self) -> Self { + match self { + Term::Constant(c) => Term::Constant(-c), + Term::Linear(c, w) => Term::Linear(-c, w), + Term::Multiplication(c, w1, w2) => Term::Multiplication(-c, w1, w2), + } + } +} + type ParseResult = Result; #[derive(Debug, Error)] @@ -1116,6 +1120,8 @@ pub(crate) enum ParserError { ExpectedFieldElement { found: Token, span: Span }, #[error("Expected a witness index, found '{found}'")] ExpectedWitness { found: Token, span: Span }, + #[error("Expected a term, found '{found}'")] + ExpectedTerm { found: Token, span: Span }, #[error("Duplicate constant term in native Expression")] DuplicatedConstantTerm { found: Token, span: Span }, #[error("Expected valid black box function name, found '{found}'")] @@ -1142,6 +1148,7 @@ impl ParserError { | ExpectedIdentifier { span, .. } | ExpectedFieldElement { span, .. } | ExpectedWitness { span, .. } + | ExpectedTerm { span, .. } | DuplicatedConstantTerm { span, .. } | ExpectedBlackBoxFuncName { span, .. } | IntegerLargerThanU32 { span, .. } From b22518eb28f750588bf1bda812b7328f01c489f6 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Wed, 24 Sep 2025 09:52:49 -0300 Subject: [PATCH 16/25] One more special case --- acvm-repo/acir/src/circuit/opcodes.rs | 33 ++++++++++++++++--- acvm-repo/acir/src/parser/tests.rs | 31 ++++++++++++++--- .../compiler/optimizers/merge_expressions.rs | 2 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 4 +-- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index c53ec06e9d2..90b6f3a1e51 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -149,8 +149,8 @@ impl std::fmt::Display for Opcode { Opcode::AssertZero(expr) => { write!(f, "EXPR ")?; - // Check if it's `wN - C = 0` and print it as `wN = C`, - // or if its' `wN + C = 0` and print it as `wN = -C`. + // Check if it's `w - C = 0` and print it as `w = C`, + // or if its' `w + C = 0` and print it as `w = -C`. if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 1 { let (coefficient, witness) = expr.linear_combinations[0]; let constant = expr.q_c; @@ -169,8 +169,8 @@ impl std::fmt::Display for Opcode { } } - // Check if it's `-wN * wM = 0` or `wN * -wM = 0` in which case we can - // print it as `wN = wM`. + // Check if it's `-w1 * w2 = 0` or `w1 * -w2 = 0` in which case we can + // print it as `w1 = w2`. if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 2 && expr.q_c.is_zero() @@ -186,6 +186,31 @@ impl std::fmt::Display for Opcode { } } + // Check if it's `c1*w1*w2 - w3 = 0` or similar, in which case we can print it + // as `w1 = c1*w2*w3`. + if expr.mul_terms.len() == 1 + && expr.linear_combinations.len() == 1 + && expr.q_c.is_zero() + { + let (coefficient1, witness1, witness2) = expr.mul_terms[0]; + let (coefficient2, witness3) = expr.linear_combinations[0]; + if witness1 != witness3 + && witness2 != witness3 + && (coefficient2.is_one() || (-coefficient2).is_one()) + { + let coefficient1 = + if coefficient2.is_one() { -coefficient1 } else { coefficient1 }; + if coefficient1.is_one() { + write!(f, "{witness3} = {witness1}*{witness2}")?; + } else if (-coefficient1).is_one() { + write!(f, "{witness3} = -{witness1}*{witness2}")?; + } else { + write!(f, "{witness3} = {coefficient1}*{witness1}*{witness2}")?; + } + return Ok(()); + } + } + let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 9e31399f246..bcd1ad72de1 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -1,3 +1,5 @@ +use insta::assert_snapshot; + use crate::{ circuit::{Circuit, Program}, parser::ParserError, @@ -118,10 +120,10 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w0*w1 - w3 = 0 - EXPR w3*w3 - w4 = 0 - EXPR w4*w4 - w5 = 0 - EXPR w5*w5 - w6 = 0 + EXPR w3 = w0*w1 + EXPR w4 = w3*w3 + EXPR w5 = w4*w4 + EXPR w6 = w5*w5 EXPR w2 = w6 "; assert_circuit_roundtrip(src); @@ -656,7 +658,7 @@ fn array_dynamic() { MEM (id: 3, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w49) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w50) ]) EXPR -w31*w36 = 0 - EXPR w21*w31 - w51 = 0 + EXPR w51 = w21*w31 MEM (id: 0, read at: EXPR [ (1, w51) ], value: EXPR [ (1, w52) ]) EXPR -w31*w52 + w52 - w53 = 0 MEM (id: 0, write EXPR [ (1, w53) ] at: EXPR [ (1, w51) ]) @@ -751,3 +753,22 @@ fn fold_basic_mismatched_ids() { assert_eq!(expected, 1); assert_eq!(found, 2); } + +#[test] +fn assert_zero_equation() { + let src = " + current witness: w9 + private parameters: [w0, w1, w2, w2] + public parameters: [] + return values: [] + EXPR - w0 + w1 - 10 + 20 + w0*w2 = w2 - w3 + w0*w1 - w1*w2 - 30 + "; + let circuit = Circuit::from_str(src).unwrap(); + assert_snapshot!(circuit.to_string(), @r" + current witness: w9 + private parameters: [w0, w1, w2] + public parameters: [] + return values: [] + EXPR w0*w2 - w0*w1 + w1*w2 - w0 + w1 - w2 + w3 = -40 + "); +} diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index a74f07ca8a1..35636d5c830 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,7 +348,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR w0*w1 + w5 = 0 + EXPR w5 = -w0*w1 EXPR 2*w0*w0 - w3 + 2*w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 0b75317345f..1e2df87929b 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -161,7 +161,7 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 - w5 = 0 + EXPR w5 = w3*w4 MEM (id: 0, read at: EXPR [ (1, w5) ], value: EXPR [ (1, w6) ]) EXPR w6 = 10 "); @@ -199,7 +199,7 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 - w8 = 0 + EXPR w8 = w3*w4 MEM (id: 0, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w9) ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR -w4*w9 + 10*w4 + w9 - w10 = 0 diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index a72290ce958..7d639e4f2ab 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR -w0*w1 + w2 = 0 + EXPR w2 = w0*w1 "); } From 56c48f0e1e459644b419edcdbaf84e580e445a6a Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 10:28:35 -0300 Subject: [PATCH 17/25] Don't simplify too much --- acvm-repo/acir/src/circuit/mod.rs | 2 +- acvm-repo/acir/src/circuit/opcodes.rs | 50 +++---------------- acvm-repo/acir/src/parser/tests.rs | 44 ++++++++-------- .../compiler/optimizers/merge_expressions.rs | 2 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 4 +- .../src/acir/tests/brillig_call.rs | 26 +++++----- .../noirc_evaluator/src/acir/tests/call.rs | 2 +- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 8 files changed, 49 insertions(+), 83 deletions(-) diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 85056107edc..1dd1e2f8bb0 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -544,7 +544,7 @@ mod tests { private parameters: [] public parameters: [w2] return values: [w2] - EXPR 2*w1 = -8 + EXPR 2*w1 + 8 = 0 BLACKBOX::RANGE [w1]:8 bits [] BLACKBOX::AND [w1, w2]:4 bits [w3] BLACKBOX::KECCAKF1600 [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 90b6f3a1e51..e4b518323ed 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -153,17 +153,8 @@ impl std::fmt::Display for Opcode { // or if its' `w + C = 0` and print it as `w = -C`. if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 1 { let (coefficient, witness) = expr.linear_combinations[0]; - let constant = expr.q_c; - - if coefficient.is_one() { - // This is `wN + C = 0`, so show it as `wN = -C`. - let constant = -constant; - write!(f, "{witness} = {constant}")?; - return Ok(()); - } - - if (-coefficient).is_one() { - // This is `-wN + C = 0`, so show it as `wN = C`. + if coefficient.is_one() || (-coefficient).is_one() { + let constant = if coefficient.is_one() { -expr.q_c } else { expr.q_c }; write!(f, "{witness} = {constant}")?; return Ok(()); } @@ -186,31 +177,6 @@ impl std::fmt::Display for Opcode { } } - // Check if it's `c1*w1*w2 - w3 = 0` or similar, in which case we can print it - // as `w1 = c1*w2*w3`. - if expr.mul_terms.len() == 1 - && expr.linear_combinations.len() == 1 - && expr.q_c.is_zero() - { - let (coefficient1, witness1, witness2) = expr.mul_terms[0]; - let (coefficient2, witness3) = expr.linear_combinations[0]; - if witness1 != witness3 - && witness2 != witness3 - && (coefficient2.is_one() || (-coefficient2).is_one()) - { - let coefficient1 = - if coefficient2.is_one() { -coefficient1 } else { coefficient1 }; - if coefficient1.is_one() { - write!(f, "{witness3} = {witness1}*{witness2}")?; - } else if (-coefficient1).is_one() { - write!(f, "{witness3} = -{witness1}*{witness2}")?; - } else { - write!(f, "{witness3} = {coefficient1}*{witness1}*{witness2}")?; - } - return Ok(()); - } - } - let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { @@ -271,12 +237,12 @@ impl std::fmt::Display for Opcode { printed_term = true; } - if printed_term { - // Change `... + c = 0` to `... = -c` - let q_c = -expr.q_c; - write!(f, " = {q_c}")?; - } else if expr.q_c.is_zero() { - write!(f, "0 = 0")?; + if expr.q_c.is_zero() { + if printed_term { + write!(f, " = 0")?; + } else { + write!(f, "0 = 0")?; + } } else { let coefficient = expr.q_c; let coefficient_as_string = coefficient.to_string(); diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index bcd1ad72de1..5afdcd43114 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -120,10 +120,10 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w3 = w0*w1 - EXPR w4 = w3*w3 - EXPR w5 = w4*w4 - EXPR w6 = w5*w5 + EXPR -w0*w1 + w3 = 0 + EXPR -w3*w3 + w4 = 0 + EXPR -w4*w4 + w5 = 0 + EXPR -w5*w5 + w6 = 0 EXPR w2 = w6 "; assert_circuit_roundtrip(src); @@ -527,7 +527,7 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 = 1 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; assert_circuit_roundtrip(src); @@ -542,7 +542,7 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 = 1 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; assert_circuit_roundtrip(src); @@ -612,15 +612,15 @@ fn array_dynamic() { BLACKBOX::RANGE [w19]:32 bits [] EXPR w5 - w19 - w20 = 0 BLACKBOX::RANGE [w20]:32 bits [] - EXPR w20 - w21 = 5 - EXPR w21 - w22 = 3 + EXPR w20 - w21 - 5 = 0 + EXPR w21 - w22 - 3 = 0 MEM (id: 0, read at: EXPR [ (1, w21) ], value: EXPR [ (1, w23) ]) EXPR w23 = 111 MEM (id: 0, read at: EXPR [ (1, w22) ], value: EXPR [ (1, w24) ]) EXPR w24 = 101 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR w22 - 4294967296*w25 - w26 = -4294967291 + EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 EXPR w25 = 0 EXPR w27 = 0 MEM (id: 0, write EXPR [ (1, w27) ] at: EXPR [ (1, w22) ]) @@ -632,15 +632,15 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR w21 - 4294967296*w31 - w32 = -4294967286 + EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 EXPR -w21*w31 + w21 - w33 = 0 MEM (id: 0, read at: EXPR [ (1, w33) ], value: EXPR [ (1, w34) ]) - EXPR -w31*w34 + 2*w31 + w34 - w35 = 2 + EXPR -w31*w34 + 2*w31 + w34 - w35 - 2 = 0 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR w21 - 4294967296*w36 - w37 = -4294967291 + EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 EXPR w31*w36 - w36 = 0 EXPR -w21*w31 + w21 - w38 = 0 MEM (id: 0, read at: EXPR [ (1, w38) ], value: EXPR [ (1, w39) ]) @@ -658,14 +658,14 @@ fn array_dynamic() { MEM (id: 3, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w49) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w50) ]) EXPR -w31*w36 = 0 - EXPR w51 = w21*w31 + EXPR -w21*w31 + w51 = 0 MEM (id: 0, read at: EXPR [ (1, w51) ], value: EXPR [ (1, w52) ]) EXPR -w31*w52 + w52 - w53 = 0 MEM (id: 0, write EXPR [ (1, w53) ] at: EXPR [ (1, w51) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w54) ]) - EXPR -w31 - w55 = -1 + EXPR -w31 - w55 + 1 = 0 EXPR -w31*w49 + w31*w50 + w49 - w56 = 0 - EXPR w31*w54 + w55*w56 = 109 + EXPR w31*w54 + w55*w56 - 109 = 0 EXPR w57 = 246 EXPR w58 = 159 EXPR w59 = 32 @@ -678,23 +678,23 @@ fn array_dynamic() { MEM (id: 4, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w65) ]) MEM (id: 4, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w66) ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) ]], outputs: [w67] - EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 = 1 + EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 = 0 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] EXPR w18 - 4294967296*w68 - w69 = 0 - EXPR -w68 - w70 = -5096253676302562286669017222071363378443840053029366383258766538131 + EXPR -w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 = 1 + EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 EXPR -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 EXPR w69*w72 + 268435455*w72 - w73 = 0 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR -w69 - 4294967296*w74 - w75 = -4294967299 - EXPR -w17*w74 + w17 - 3*w74 - w76 = -3 + EXPR -w69 - 4294967296*w74 - w75 + 4294967299 = 0 + EXPR -w17*w74 + w17 - 3*w74 - w76 + 3 = 0 BLACKBOX::RANGE [w76]:32 bits [] EXPR -w74*w76 + w76 - w77 = 0 MEM (id: 1, read at: EXPR [ (1, w77) ], value: EXPR [ (1, w78) ]) @@ -720,7 +720,7 @@ fn fold_basic() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 = 1 + EXPR w0*w3 - w1*w3 - 1 = 0 EXPR w0 = w2 "; assert_program_roundtrip(src); @@ -769,6 +769,6 @@ fn assert_zero_equation() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w0*w2 - w0*w1 + w1*w2 - w0 + w1 - w2 + w3 = -40 + EXPR w0*w2 - w0*w1 + w1*w2 - w0 + w1 - w2 + w3 + 40 = 0 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 35636d5c830..a74f07ca8a1 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,7 +348,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR w5 = -w0*w1 + EXPR w0*w1 + w5 = 0 EXPR 2*w0*w0 - w3 + 2*w5 = 0 BLACKBOX::RANGE [w3]:32 bits [] "); diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 1e2df87929b..0b75317345f 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -161,7 +161,7 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w5 = w3*w4 + EXPR w3*w4 - w5 = 0 MEM (id: 0, read at: EXPR [ (1, w5) ], value: EXPR [ (1, w6) ]) EXPR w6 = 10 "); @@ -199,7 +199,7 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w8 = w3*w4 + EXPR w3*w4 - w8 = 0 MEM (id: 0, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w9) ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) EXPR -w4*w9 + 10*w4 + w9 - w10 = 0 diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index 049cfef5c26..cac103cfb96 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,19 +153,19 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 = 1 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 = 1 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [w7] - EXPR w2*w7 = 1 + EXPR w2*w7 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR w2 - w9 - w10 = 1 + EXPR w2 - w9 - w10 - 1 = 0 BLACKBOX::RANGE [w10]:32 bits [] EXPR -w2*w8 + w1 - w9 = 0 EXPR w8 = 1 @@ -241,11 +241,11 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 = 1 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 = 1 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 @@ -254,10 +254,10 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w9] - EXPR w2*w9 = 1 + EXPR w2*w9 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR w2 - w11 - w12 = 1 + EXPR w2 - w11 - w12 - 1 = 0 BLACKBOX::RANGE [w12]:32 bits [] EXPR -w2*w10 + w1 - w11 = 0 EXPR w10 = 1 @@ -375,11 +375,11 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 = 1 + EXPR w1*w3 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 = 1 + EXPR w1 - w5 - w6 - 1 = 0 BLACKBOX::RANGE [w6]:32 bits [] EXPR -w1*w4 + w0 - w5 = 0 EXPR w2 = w4 @@ -390,10 +390,10 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w10] - EXPR w2*w10 = 1 + EXPR w2*w10 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR w2 - w12 - w13 = 1 + EXPR w2 - w12 - w13 - 1 = 0 BLACKBOX::RANGE [w13]:32 bits [] EXPR -w2*w11 + w1 - w12 = 0 EXPR w11 = 1 @@ -407,7 +407,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] EXPR w0 - w1 - w3 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) ]], outputs: [w4] - EXPR w3*w4 + w5 = 1 + EXPR w3*w4 + w5 - 1 = 0 EXPR w3*w5 = 0 EXPR w5 = 0 EXPR w0 = w2 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index a9b59ff6478..b7b7fff5a2d 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -161,7 +161,7 @@ fn basic_nested_call(inline_type: InlineType) { private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w3 = -2 + EXPR w0 - w3 + 2 = 0 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] EXPR w2 = w4 diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index 7d639e4f2ab..a72290ce958 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR w2 = w0*w1 + EXPR -w0*w1 + w2 = 0 "); } From 257818be292a89cf2ea3efe8575c928fed4e1aaf Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 11:17:33 -0300 Subject: [PATCH 18/25] Show AssertZero based on actual code --- acvm-repo/acir/src/circuit/opcodes.rs | 91 +++++++++------ acvm-repo/acir/src/parser/tests.rs | 108 +++++++++--------- .../compiler/optimizers/merge_expressions.rs | 4 +- .../noirc_evaluator/src/acir/tests/arrays.rs | 18 +-- .../src/acir/tests/brillig_call.rs | 36 +++--- .../noirc_evaluator/src/acir/tests/call.rs | 6 +- .../noirc_evaluator/src/acir/tests/mod.rs | 2 +- 7 files changed, 142 insertions(+), 123 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index e4b518323ed..5e721044369 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -149,37 +149,39 @@ impl std::fmt::Display for Opcode { Opcode::AssertZero(expr) => { write!(f, "EXPR ")?; - // Check if it's `w - C = 0` and print it as `w = C`, - // or if its' `w + C = 0` and print it as `w = -C`. - if expr.mul_terms.is_empty() && expr.linear_combinations.len() == 1 { - let (coefficient, witness) = expr.linear_combinations[0]; - if coefficient.is_one() || (-coefficient).is_one() { - let constant = if coefficient.is_one() { -expr.q_c } else { expr.q_c }; - write!(f, "{witness} = {constant}")?; - return Ok(()); - } - } - - // Check if it's `-w1 * w2 = 0` or `w1 * -w2 = 0` in which case we can - // print it as `w1 = w2`. - if expr.mul_terms.is_empty() - && expr.linear_combinations.len() == 2 - && expr.q_c.is_zero() - { - let (coefficient1, witness1) = expr.linear_combinations[0]; - let (coefficient2, witness2) = expr.linear_combinations[1]; - - if (coefficient1.is_one() && (-coefficient2).is_one()) - || ((-coefficient1).is_one() && coefficient2.is_one()) - { - write!(f, "{witness1} = {witness2}")?; - return Ok(()); - } + // This is set to an index if we show this expression "as an assignment", meaning + // that the linear combination at this index must not be printed again. + let mut show_as_assignment: Option = None; + + // If true, negate all coefficients when printing. + // This is set to true if we show this expression "as an assignment", and the witness + // had a coefficient of 1 and we "moved" everything to the right of the equal sign. + let mut negate_coefficients = false; + + // Find a linear combination with a coefficient of 1 or -1 and, if there are many, + // keep the one with the largest witness. + let linear_witness_one = expr + .linear_combinations + .iter() + .enumerate() + .filter(|(_, (coefficient, _))| { + coefficient.is_one() || (-*coefficient).is_one() + }) + .max_by_key(|(_, (_, witness))| witness); + + // If we find one, show the expression as equaling this witness to everything else + // (this is likely to happen as in ACIR gen we tend to equate a witness to previous expressions) + if let Some((index, (coefficient, witness))) = linear_witness_one { + show_as_assignment = Some(index); + negate_coefficients = coefficient.is_one(); + write!(f, "{witness} = ")?; } let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { + let coefficient = + if negate_coefficients { -*coefficient } else { *coefficient }; let coefficient_as_string = coefficient.to_string(); let coefficient_is_negative = coefficient_as_string.starts_with('-'); @@ -192,9 +194,9 @@ impl std::fmt::Display for Opcode { } let coefficient = if printed_term && coefficient_is_negative { - -*coefficient + -coefficient } else { - *coefficient + coefficient }; if coefficient.is_one() { @@ -208,7 +210,16 @@ impl std::fmt::Display for Opcode { printed_term = true; } - for (coefficient, witness) in &expr.linear_combinations { + for (index, (coefficient, witness)) in expr.linear_combinations.iter().enumerate() { + if show_as_assignment + .is_some_and(|show_as_assignment_index| show_as_assignment_index == index) + { + // We already printed this term as part of the assignment + continue; + } + + let coefficient = + if negate_coefficients { -*coefficient } else { *coefficient }; let coefficient_as_string = coefficient.to_string(); let coefficient_is_negative = coefficient_as_string.starts_with('-'); @@ -221,9 +232,9 @@ impl std::fmt::Display for Opcode { } let coefficient = if printed_term && coefficient_is_negative { - -*coefficient + -coefficient } else { - *coefficient + coefficient }; if coefficient.is_one() { @@ -238,13 +249,18 @@ impl std::fmt::Display for Opcode { } if expr.q_c.is_zero() { - if printed_term { - write!(f, " = 0")?; - } else { - write!(f, "0 = 0")?; + if show_as_assignment.is_none() { + if printed_term { + write!(f, " = 0")?; + } else { + write!(f, "0 = 0")?; + } + } else if !printed_term { + write!(f, "0")?; } } else { let coefficient = expr.q_c; + let coefficient = if negate_coefficients { -coefficient } else { coefficient }; let coefficient_as_string = coefficient.to_string(); let coefficient_is_negative = coefficient_as_string.starts_with('-'); @@ -262,7 +278,10 @@ impl std::fmt::Display for Opcode { coefficient }; write!(f, "{coefficient}")?; - write!(f, " = 0")?; + + if show_as_assignment.is_none() { + write!(f, " = 0")?; + } } Ok(()) diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 5afdcd43114..41e9488ccc7 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -104,11 +104,11 @@ fn assert_zero_opcodes() { private parameters: [w0, w1, w2, w3, w4] public parameters: [w5, w6, w7, w8, w9] return values: [] - EXPR w0 = w5 - EXPR w1 = w6 - EXPR w2 = w7 - EXPR w3 = w8 - EXPR w4 = w9 + EXPR w5 = w0 + EXPR w6 = w1 + EXPR w7 = w2 + EXPR w8 = w3 + EXPR w9 = w4 "; assert_circuit_roundtrip(src); } @@ -120,11 +120,11 @@ fn assert_zero_with_mul_terms() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR -w0*w1 + w3 = 0 - EXPR -w3*w3 + w4 = 0 - EXPR -w4*w4 + w5 = 0 - EXPR -w5*w5 + w6 = 0 - EXPR w2 = w6 + EXPR w3 = w0*w1 + EXPR w4 = w3*w3 + EXPR w5 = w4*w4 + EXPR w6 = w5*w5 + EXPR w6 = w2 "; assert_circuit_roundtrip(src); } @@ -225,22 +225,22 @@ fn aes128_encrypt() { BLACKBOX::RANGE [w58]:8 bits [] BLACKBOX::RANGE [w59]:8 bits [] BLACKBOX::AES128_ENCRYPT [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43] [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] - EXPR w44 = w60 - EXPR w45 = w61 - EXPR w46 = w62 - EXPR w47 = w63 - EXPR w48 = w64 - EXPR w49 = w65 - EXPR w50 = w66 - EXPR w51 = w67 - EXPR w52 = w68 - EXPR w53 = w69 - EXPR w54 = w70 - EXPR w55 = w71 - EXPR w56 = w72 - EXPR w57 = w73 - EXPR w58 = w74 - EXPR w59 = w75 + EXPR w60 = w44 + EXPR w61 = w45 + EXPR w62 = w46 + EXPR w63 = w47 + EXPR w64 = w48 + EXPR w65 = w49 + EXPR w66 = w50 + EXPR w67 = w51 + EXPR w68 = w52 + EXPR w69 = w53 + EXPR w70 = w54 + EXPR w71 = w55 + EXPR w72 = w56 + EXPR w73 = w57 + EXPR w74 = w58 + EXPR w75 = w59 "; assert_circuit_roundtrip(src); } @@ -528,7 +528,7 @@ fn brillig_call() { return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR w0 = w2 + EXPR w2 = w0 "; assert_circuit_roundtrip(src); } @@ -543,7 +543,7 @@ fn brillig_call_with_predicate() { BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR w0 = w2 + EXPR w2 = w0 "; assert_circuit_roundtrip(src); } @@ -608,19 +608,19 @@ fn array_dynamic() { BLACKBOX::RANGE [w15]:32 bits [] BLACKBOX::RANGE [w16]:32 bits [] BLACKBOX::RANGE [w17]:32 bits [] - EXPR 5*w6 - w19 = 0 + EXPR w19 = 5*w6 BLACKBOX::RANGE [w19]:32 bits [] - EXPR w5 - w19 - w20 = 0 + EXPR w20 = w5 - w19 BLACKBOX::RANGE [w20]:32 bits [] - EXPR w20 - w21 - 5 = 0 - EXPR w21 - w22 - 3 = 0 + EXPR w21 = w20 - 5 + EXPR w22 = w21 - 3 MEM (id: 0, read at: EXPR [ (1, w21) ], value: EXPR [ (1, w23) ]) EXPR w23 = 111 MEM (id: 0, read at: EXPR [ (1, w22) ], value: EXPR [ (1, w24) ]) EXPR w24 = 101 BRILLIG CALL func 0: inputs: [EXPR [ (1, w22) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w25, w26] BLACKBOX::RANGE [w26]:32 bits [] - EXPR w22 - 4294967296*w25 - w26 + 4294967291 = 0 + EXPR w26 = w22 - 4294967296*w25 + 4294967291 EXPR w25 = 0 EXPR w27 = 0 MEM (id: 0, write EXPR [ (1, w27) ] at: EXPR [ (1, w22) ]) @@ -632,17 +632,17 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967286 ], EXPR [ 4294967296 ]], outputs: [w31, w32] BLACKBOX::RANGE [w31]:1 bits [] BLACKBOX::RANGE [w32]:32 bits [] - EXPR w21 - 4294967296*w31 - w32 + 4294967286 = 0 - EXPR -w21*w31 + w21 - w33 = 0 + EXPR w32 = w21 - 4294967296*w31 + 4294967286 + EXPR w33 = -w21*w31 + w21 MEM (id: 0, read at: EXPR [ (1, w33) ], value: EXPR [ (1, w34) ]) - EXPR -w31*w34 + 2*w31 + w34 - w35 - 2 = 0 + EXPR w35 = -w31*w34 + 2*w31 + w34 - 2 BLACKBOX::RANGE [w35]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w21) 4294967291 ], EXPR [ 4294967296 ]], outputs: [w36, w37] BLACKBOX::RANGE [w36]:1 bits [] BLACKBOX::RANGE [w37]:32 bits [] - EXPR w21 - 4294967296*w36 - w37 + 4294967291 = 0 - EXPR w31*w36 - w36 = 0 - EXPR -w21*w31 + w21 - w38 = 0 + EXPR w37 = w21 - 4294967296*w36 + 4294967291 + EXPR w36 = w31*w36 + EXPR w38 = -w21*w31 + w21 MEM (id: 0, read at: EXPR [ (1, w38) ], value: EXPR [ (1, w39) ]) MEM (id: 0, read at: EXPR [ (1, w27) ], value: EXPR [ (1, w40) ]) MEM (id: 0, read at: EXPR [ (1, w29) ], value: EXPR [ (1, w41) ]) @@ -653,18 +653,18 @@ fn array_dynamic() { EXPR w46 = 0 MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w47) ]) INIT (id: 3, len: 5, witnesses: [w40, w41, w43, w45, w47]) - EXPR -w31*w35 + w31*w39 + w35 - w48 = 0 + EXPR w48 = -w31*w35 + w31*w39 + w35 MEM (id: 3, write EXPR [ (1, w48) ] at: EXPR [ (1, w38) ]) MEM (id: 3, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w49) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w50) ]) EXPR -w31*w36 = 0 - EXPR -w21*w31 + w51 = 0 + EXPR w51 = w21*w31 MEM (id: 0, read at: EXPR [ (1, w51) ], value: EXPR [ (1, w52) ]) - EXPR -w31*w52 + w52 - w53 = 0 + EXPR w53 = -w31*w52 + w52 MEM (id: 0, write EXPR [ (1, w53) ] at: EXPR [ (1, w51) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w54) ]) - EXPR -w31 - w55 + 1 = 0 - EXPR -w31*w49 + w31*w50 + w49 - w56 = 0 + EXPR w55 = -w31 + 1 + EXPR w56 = -w31*w49 + w31*w50 + w49 EXPR w31*w54 + w55*w56 - 109 = 0 EXPR w57 = 246 EXPR w58 = 159 @@ -682,23 +682,23 @@ fn array_dynamic() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] - EXPR w18 - 4294967296*w68 - w69 = 0 - EXPR -w68 - w70 + 5096253676302562286669017222071363378443840053029366383258766538131 = 0 + EXPR w69 = w18 - 4294967296*w68 + EXPR w70 = -w68 + 5096253676302562286669017222071363378443840053029366383258766538131 BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] - EXPR -w68*w71 + 5096253676302562286669017222071363378443840053029366383258766538131*w71 + w72 - 1 = 0 + EXPR w72 = w68*w71 - 5096253676302562286669017222071363378443840053029366383258766538131*w71 + 1 EXPR -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 - EXPR w69*w72 + 268435455*w72 - w73 = 0 + EXPR w73 = w69*w72 + 268435455*w72 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] BLACKBOX::RANGE [w74]:1 bits [] BLACKBOX::RANGE [w75]:32 bits [] - EXPR -w69 - 4294967296*w74 - w75 + 4294967299 = 0 - EXPR -w17*w74 + w17 - 3*w74 - w76 + 3 = 0 + EXPR w75 = -w69 - 4294967296*w74 + 4294967299 + EXPR w76 = -w17*w74 + w17 - 3*w74 + 3 BLACKBOX::RANGE [w76]:32 bits [] - EXPR -w74*w76 + w76 - w77 = 0 + EXPR w77 = -w74*w76 + w76 MEM (id: 1, read at: EXPR [ (1, w77) ], value: EXPR [ (1, w78) ]) - EXPR w15*w74 - w74*w78 - w15 + w78 = 0 + EXPR w78 = -w15*w74 + w74*w78 + w15 "; assert_circuit_roundtrip(src); } @@ -721,7 +721,7 @@ fn fold_basic() { return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] EXPR w0*w3 - w1*w3 - 1 = 0 - EXPR w0 = w2 + EXPR w2 = w0 "; assert_program_roundtrip(src); } @@ -769,6 +769,6 @@ fn assert_zero_equation() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w0*w2 - w0*w1 + w1*w2 - w0 + w1 - w2 + w3 + 40 = 0 + EXPR w3 = -w0*w2 + w0*w1 - w1*w2 + w0 - w1 + w2 - 40 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index a74f07ca8a1..7d13dfbe427 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -348,8 +348,8 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR w0*w1 + w5 = 0 - EXPR 2*w0*w0 - w3 + 2*w5 = 0 + EXPR w5 = -w0*w1 + EXPR w3 = 2*w0*w0 + 2*w5 BLACKBOX::RANGE [w3]:32 bits [] "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 0b75317345f..231db2fb085 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -128,9 +128,9 @@ fn generates_memory_op_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w11) ]) EXPR w12 = 2 MEM (id: 1, read at: EXPR [ (1, w12) ], value: EXPR [ (1, w13) ]) - EXPR w4 = w9 - EXPR w5 = w11 - EXPR w6 = w13 + EXPR w9 = w4 + EXPR w11 = w5 + EXPR w13 = w6 "); } @@ -161,7 +161,7 @@ fn generates_predicated_index_for_dynamic_read() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 - w5 = 0 + EXPR w5 = w3*w4 MEM (id: 0, read at: EXPR [ (1, w5) ], value: EXPR [ (1, w6) ]) EXPR w6 = 10 "); @@ -199,10 +199,10 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { INIT (id: 0, len: 3, witnesses: [w0, w1, w2]) BLACKBOX::RANGE [w3]:32 bits [] BLACKBOX::RANGE [w4]:1 bits [] - EXPR w3*w4 - w8 = 0 + EXPR w8 = w3*w4 MEM (id: 0, read at: EXPR [ (1, w8) ], value: EXPR [ (1, w9) ]) INIT (id: 1, len: 3, witnesses: [w0, w1, w2]) - EXPR -w4*w9 + 10*w4 + w9 - w10 = 0 + EXPR w10 = -w4*w9 + 10*w4 + w9 MEM (id: 1, write EXPR [ (1, w10) ] at: EXPR [ (1, w8) ]) EXPR w11 = 0 MEM (id: 1, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w12) ]) @@ -210,9 +210,9 @@ fn generates_predicated_index_and_dummy_value_for_dynamic_write() { MEM (id: 1, read at: EXPR [ (1, w13) ], value: EXPR [ (1, w14) ]) EXPR w15 = 2 MEM (id: 1, read at: EXPR [ (1, w15) ], value: EXPR [ (1, w16) ]) - EXPR w5 = w12 - EXPR w6 = w14 - EXPR w7 = w16 + EXPR w12 = w5 + EXPR w14 = w6 + EXPR w16 = w7 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index cac103cfb96..8a7dd222bac 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -157,17 +157,17 @@ fn multiple_brillig_stdlib_calls() { BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w6 = w1 - w5 - 1 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -w1*w4 + w0 - w5 = 0 - EXPR w2 = w4 + EXPR w5 = -w1*w4 + w0 + EXPR w4 = w2 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [w7] EXPR w2*w7 - 1 = 0 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] - EXPR w2 - w9 - w10 - 1 = 0 + EXPR w10 = w2 - w9 - 1 BLACKBOX::RANGE [w10]:32 bits [] - EXPR -w2*w8 + w1 - w9 = 0 + EXPR w9 = -w2*w8 + w1 EXPR w8 = 1 unconstrained func 0 @@ -245,10 +245,10 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w6 = w1 - w5 - 1 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -w1*w4 + w0 - w5 = 0 - EXPR w2 = w4 + EXPR w5 = -w1*w4 + w0 + EXPR w4 = w2 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] @@ -257,9 +257,9 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { EXPR w2*w9 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] - EXPR w2 - w11 - w12 - 1 = 0 + EXPR w12 = w2 - w11 - 1 BLACKBOX::RANGE [w12]:32 bits [] - EXPR -w2*w10 + w1 - w11 = 0 + EXPR w11 = -w2*w10 + w1 EXPR w10 = 1 unconstrained func 0 @@ -379,10 +379,10 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] - EXPR w1 - w5 - w6 - 1 = 0 + EXPR w6 = w1 - w5 - 1 BLACKBOX::RANGE [w6]:32 bits [] - EXPR -w1*w4 + w0 - w5 = 0 - EXPR w2 = w4 + EXPR w5 = -w1*w4 + w0 + EXPR w4 = w2 BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w7] BLACKBOX::RANGE [w7]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] @@ -393,9 +393,9 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w2*w10 - 1 = 0 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] - EXPR w2 - w12 - w13 - 1 = 0 + EXPR w13 = w2 - w12 - 1 BLACKBOX::RANGE [w13]:32 bits [] - EXPR -w2*w11 + w1 - w12 = 0 + EXPR w12 = -w2*w11 + w1 EXPR w11 = 1 func 1 @@ -405,12 +405,12 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR w0 - w1 - w3 = 0 + EXPR w3 = w0 - w1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) ]], outputs: [w4] - EXPR w3*w4 + w5 - 1 = 0 + EXPR w5 = -w3*w4 + 1 EXPR w3*w5 = 0 EXPR w5 = 0 - EXPR w0 = w2 + EXPR w2 = w0 unconstrained func 0 0: @2 = const u32 1 diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index b7b7fff5a2d..f8271d34788 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -64,15 +64,15 @@ fn basic_call_with_outputs_assert(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 = w3 + EXPR w3 = w2 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 = w1 - EXPR w0 = w2 + EXPR w1 = w0 + EXPR w2 = w0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/mod.rs b/compiler/noirc_evaluator/src/acir/tests/mod.rs index a72290ce958..7d639e4f2ab 100644 --- a/compiler/noirc_evaluator/src/acir/tests/mod.rs +++ b/compiler/noirc_evaluator/src/acir/tests/mod.rs @@ -95,7 +95,7 @@ fn unchecked_mul_should_not_have_range_check() { return values: [w2] BLACKBOX::RANGE [w0]:32 bits [] BLACKBOX::RANGE [w1]:32 bits [] - EXPR -w0*w1 + w2 = 0 + EXPR w2 = w0*w1 "); } From 13f4812d5173f18230927926f136e03b6be4e0bf Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 11:35:37 -0300 Subject: [PATCH 19/25] Fix snapshot --- compiler/noirc_evaluator/src/acir/tests/call.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index f8271d34788..3ce187a7dc1 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -107,15 +107,15 @@ fn call_output_as_next_call_input(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w2, w1], outputs: [w3] - EXPR w2 = w3 + EXPR w3 = w2 func 1 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 = w1 - EXPR w0 = w2 + EXPR w1 = w0 + EXPR w2 = w0 "); } From 4aec25957aec38eb7e7e4920098448d419521b84 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 11:35:44 -0300 Subject: [PATCH 20/25] Extract `display_term` --- acvm-repo/acir/src/circuit/opcodes.rs | 98 ++++++++++++--------------- 1 file changed, 44 insertions(+), 54 deletions(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 5e721044369..7e81d4d02ed 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -180,33 +180,8 @@ impl std::fmt::Display for Opcode { let mut printed_term = false; for (coefficient, witness1, witness2) in &expr.mul_terms { - let coefficient = - if negate_coefficients { -*coefficient } else { *coefficient }; - let coefficient_as_string = coefficient.to_string(); - let coefficient_is_negative = coefficient_as_string.starts_with('-'); - - if printed_term { - if coefficient_is_negative { - write!(f, " - ")?; - } else { - write!(f, " + ")?; - } - } - - let coefficient = if printed_term && coefficient_is_negative { - -coefficient - } else { - coefficient - }; - - if coefficient.is_one() { - write!(f, "{witness1}*{witness2}")?; - } else if (-coefficient).is_one() { - write!(f, "-{witness1}*{witness2}")?; - } else { - write!(f, "{coefficient}*{witness1}*{witness2}")?; - } - + let witnesses = [*witness1, *witness2]; + display_term(*coefficient, witnesses, printed_term, negate_coefficients, f)?; printed_term = true; } @@ -218,33 +193,8 @@ impl std::fmt::Display for Opcode { continue; } - let coefficient = - if negate_coefficients { -*coefficient } else { *coefficient }; - let coefficient_as_string = coefficient.to_string(); - let coefficient_is_negative = coefficient_as_string.starts_with('-'); - - if printed_term { - if coefficient_is_negative { - write!(f, " - ")?; - } else { - write!(f, " + ")?; - } - } - - let coefficient = if printed_term && coefficient_is_negative { - -coefficient - } else { - coefficient - }; - - if coefficient.is_one() { - write!(f, "{witness}")?; - } else if (-coefficient).is_one() { - write!(f, "-{witness}")?; - } else { - write!(f, "{coefficient}*{witness}")?; - } - + let witnesses = [*witness]; + display_term(*coefficient, witnesses, printed_term, negate_coefficients, f)?; printed_term = true; } @@ -346,6 +296,46 @@ impl std::fmt::Display for Opcode { } } +fn display_term( + coefficient: F, + witnesses: [Witness; N], + printed_term: bool, + negate_coefficients: bool, + f: &mut std::fmt::Formatter<'_>, +) -> std::fmt::Result { + let coefficient = if negate_coefficients { -coefficient } else { coefficient }; + let coefficient_as_string = coefficient.to_string(); + let coefficient_is_negative = coefficient_as_string.starts_with('-'); + + if printed_term { + if coefficient_is_negative { + write!(f, " - ")?; + } else { + write!(f, " + ")?; + } + } + + let coefficient = + if printed_term && coefficient_is_negative { -coefficient } else { coefficient }; + + if coefficient.is_one() { + // Don't print the cofficient + } else if (-coefficient).is_one() { + write!(f, "-")?; + } else { + write!(f, "{coefficient}*")?; + } + + for (index, witness) in witnesses.iter().enumerate() { + if index != 0 { + write!(f, "*")?; + } + write!(f, "{witness}")?; + } + + Ok(()) +} + impl std::fmt::Debug for Opcode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self, f) From c86a544f9250fafa8ed10d2350ddfc078dae8f8e Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 12:16:36 -0300 Subject: [PATCH 21/25] More snapshots --- compiler/noirc_evaluator/src/acir/tests/call.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/noirc_evaluator/src/acir/tests/call.rs b/compiler/noirc_evaluator/src/acir/tests/call.rs index 3ce187a7dc1..e47b6fab008 100644 --- a/compiler/noirc_evaluator/src/acir/tests/call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/call.rs @@ -154,24 +154,24 @@ fn basic_nested_call(inline_type: InlineType) { inputs: [w0, w1], outputs: [w2] CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w3] - EXPR w2 = w3 + EXPR w3 = w2 func 1 current witness: w4 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 - w3 + 2 = 0 + EXPR w3 = w0 + 2 CALL func 2: PREDICATE: EXPR [ 1 ] inputs: [w3, w1], outputs: [w4] - EXPR w2 = w4 + EXPR w4 = w2 func 2 current witness: w2 private parameters: [w0, w1] public parameters: [] return values: [w2] - EXPR w0 = w1 - EXPR w0 = w2 + EXPR w1 = w0 + EXPR w2 = w0 "); } From b08b7707eedad93c20c77c92878cb97cd28db0ac Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 14:06:50 -0300 Subject: [PATCH 22/25] Update acvm-repo/acir/src/circuit/opcodes.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/opcodes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 7e81d4d02ed..94760ae5d46 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -319,7 +319,7 @@ fn display_term( if printed_term && coefficient_is_negative { -coefficient } else { coefficient }; if coefficient.is_one() { - // Don't print the cofficient + // Don't print the coefficient } else if (-coefficient).is_one() { write!(f, "-")?; } else { From 959add074c5c5417fe6e304be51450319c6813fc Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 14:10:54 -0300 Subject: [PATCH 23/25] Remove extra space in test --- acvm-repo/acir/src/parser/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 41e9488ccc7..8ee8c5d269d 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -761,7 +761,7 @@ fn assert_zero_equation() { private parameters: [w0, w1, w2, w2] public parameters: [] return values: [] - EXPR - w0 + w1 - 10 + 20 + w0*w2 = w2 - w3 + w0*w1 - w1*w2 - 30 + EXPR -w0 + w1 - 10 + 20 + w0*w2 = w2 - w3 + w0*w1 - w1*w2 - 30 "; let circuit = Circuit::from_str(src).unwrap(); assert_snapshot!(circuit.to_string(), @r" From 5e04384ce09077bb3c9873dcbc879a78c0f49026 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 14:25:40 -0300 Subject: [PATCH 24/25] Show expressions that equal zero as `0 = ...` --- acvm-repo/acir/src/circuit/mod.rs | 2 +- acvm-repo/acir/src/circuit/opcodes.rs | 24 +++++++------------ acvm-repo/acir/src/parser/mod.rs | 6 ++--- acvm-repo/acir/src/parser/tests.rs | 16 ++++++------- .../acvm/src/compiler/optimizers/general.rs | 6 ++--- .../noirc_evaluator/src/acir/tests/arrays.rs | 2 +- .../src/acir/tests/brillig_call.rs | 14 +++++------ 7 files changed, 31 insertions(+), 39 deletions(-) diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 1dd1e2f8bb0..9b56183d047 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -544,7 +544,7 @@ mod tests { private parameters: [] public parameters: [w2] return values: [w2] - EXPR 2*w1 + 8 = 0 + EXPR 0 = 2*w1 + 8 BLACKBOX::RANGE [w1]:8 bits [] BLACKBOX::AND [w1, w2]:4 bits [w3] BLACKBOX::KECCAKF1600 [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25] [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index 7e81d4d02ed..9fb8c487405 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -149,12 +149,12 @@ impl std::fmt::Display for Opcode { Opcode::AssertZero(expr) => { write!(f, "EXPR ")?; - // This is set to an index if we show this expression "as an assignment", meaning + // This is set to an index if we show this expression "as a witness assignment", meaning // that the linear combination at this index must not be printed again. - let mut show_as_assignment: Option = None; + let mut assignment_witness: Option = None; // If true, negate all coefficients when printing. - // This is set to true if we show this expression "as an assignment", and the witness + // This is set to true if we show this expression "as a witness assignment", and the witness // had a coefficient of 1 and we "moved" everything to the right of the equal sign. let mut negate_coefficients = false; @@ -172,9 +172,11 @@ impl std::fmt::Display for Opcode { // If we find one, show the expression as equaling this witness to everything else // (this is likely to happen as in ACIR gen we tend to equate a witness to previous expressions) if let Some((index, (coefficient, witness))) = linear_witness_one { - show_as_assignment = Some(index); + assignment_witness = Some(index); negate_coefficients = coefficient.is_one(); write!(f, "{witness} = ")?; + } else { + write!(f, "0 = ")?; } let mut printed_term = false; @@ -186,7 +188,7 @@ impl std::fmt::Display for Opcode { } for (index, (coefficient, witness)) in expr.linear_combinations.iter().enumerate() { - if show_as_assignment + if assignment_witness .is_some_and(|show_as_assignment_index| show_as_assignment_index == index) { // We already printed this term as part of the assignment @@ -199,13 +201,7 @@ impl std::fmt::Display for Opcode { } if expr.q_c.is_zero() { - if show_as_assignment.is_none() { - if printed_term { - write!(f, " = 0")?; - } else { - write!(f, "0 = 0")?; - } - } else if !printed_term { + if !printed_term { write!(f, "0")?; } } else { @@ -228,10 +224,6 @@ impl std::fmt::Display for Opcode { coefficient }; write!(f, "{coefficient}")?; - - if show_as_assignment.is_none() { - write!(f, " = 0")?; - } } Ok(()) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index b83bfbb3858..29ab7ec6c4e 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -273,15 +273,15 @@ impl<'a> Parser<'a> { // Parse the right-hand side terms let rhs_terms = self.parse_terms_or_error()?; - // "Move" the terms to the left by negating them - let rhs_terms = rhs_terms.into_iter().map(|term| term.negate()).collect::>(); + // "Move" the terms to the right by negating them + let lhs_terms = lhs_terms.into_iter().map(|term| term.negate()).collect::>(); // Gather all terms, summing the constants let mut q_c = FieldElement::zero(); let mut linear_combinations = Vec::new(); let mut mul_terms = Vec::new(); - for term in lhs_terms.into_iter().chain(rhs_terms) { + for term in rhs_terms.into_iter().chain(lhs_terms) { match term { Term::Constant(c) => q_c += c, Term::Linear(c, w) => linear_combinations.push((c, w)), diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 8ee8c5d269d..1e9834c7439 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -527,7 +527,7 @@ fn brillig_call() { public parameters: [] return values: [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR 0 = w0*w3 - w1*w3 - 1 EXPR w2 = w0 "; assert_circuit_roundtrip(src); @@ -542,7 +542,7 @@ fn brillig_call_with_predicate() { return values: [] BRILLIG CALL func 0: PREDICATE: EXPR [ 1 ] inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR 0 = w0*w3 - w1*w3 - 1 EXPR w2 = w0 "; assert_circuit_roundtrip(src); @@ -657,7 +657,7 @@ fn array_dynamic() { MEM (id: 3, write EXPR [ (1, w48) ] at: EXPR [ (1, w38) ]) MEM (id: 3, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w49) ]) MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w50) ]) - EXPR -w31*w36 = 0 + EXPR 0 = -w31*w36 EXPR w51 = w21*w31 MEM (id: 0, read at: EXPR [ (1, w51) ], value: EXPR [ (1, w52) ]) EXPR w53 = -w31*w52 + w52 @@ -665,7 +665,7 @@ fn array_dynamic() { MEM (id: 0, read at: EXPR [ (1, w46) ], value: EXPR [ (1, w54) ]) EXPR w55 = -w31 + 1 EXPR w56 = -w31*w49 + w31*w50 + w49 - EXPR w31*w54 + w55*w56 - 109 = 0 + EXPR 0 = w31*w54 + w55*w56 - 109 EXPR w57 = 246 EXPR w58 = 159 EXPR w59 = 32 @@ -678,7 +678,7 @@ fn array_dynamic() { MEM (id: 4, read at: EXPR [ (1, w10) ], value: EXPR [ (1, w65) ]) MEM (id: 4, read at: EXPR [ (1, w11) ], value: EXPR [ (1, w66) ]) BRILLIG CALL func 1: inputs: [EXPR [ (1, w62) (1, w63) (1, w64) (1, w65) (1, w66) ]], outputs: [w67] - EXPR w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 = 0 + EXPR 0 = w62*w67 + w63*w67 + w64*w67 + w65*w67 + w66*w67 - 1 BRILLIG CALL func 0: inputs: [EXPR [ (1, w18) ], EXPR [ 4294967296 ]], outputs: [w68, w69] BLACKBOX::RANGE [w68]:222 bits [] BLACKBOX::RANGE [w69]:32 bits [] @@ -687,7 +687,7 @@ fn array_dynamic() { BLACKBOX::RANGE [w70]:222 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (-1, w68) 5096253676302562286669017222071363378443840053029366383258766538131 ]], outputs: [w71] EXPR w72 = w68*w71 - 5096253676302562286669017222071363378443840053029366383258766538131*w71 + 1 - EXPR -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 = 0 + EXPR 0 = -w68*w72 + 5096253676302562286669017222071363378443840053029366383258766538131*w72 EXPR w73 = w69*w72 + 268435455*w72 BLACKBOX::RANGE [w73]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (-1, w69) 4294967299 ], EXPR [ 4294967296 ]], outputs: [w74, w75] @@ -720,7 +720,7 @@ fn fold_basic() { public parameters: [] return values: [w2] BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) (-1, w1) ]], outputs: [w3] - EXPR w0*w3 - w1*w3 - 1 = 0 + EXPR 0 = w0*w3 - w1*w3 - 1 EXPR w2 = w0 "; assert_program_roundtrip(src); @@ -769,6 +769,6 @@ fn assert_zero_equation() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w3 = -w0*w2 + w0*w1 - w1*w2 + w0 - w1 + w2 - 40 + EXPR w3 = w0*w1 - w1*w2 - w0*w2 + w2 + w0 - w1 - 40 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index 4a8d3dbc9d1..45a458c7e53 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -102,7 +102,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR w0*w1 = 0 + EXPR 0 = -w0*w1 "); } @@ -147,7 +147,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 9*w0*w1 = 0 + EXPR 0 = -9*w0*w1 "); } @@ -190,7 +190,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 6*w0 = 0 + EXPR 0 = -6*w0 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/arrays.rs b/compiler/noirc_evaluator/src/acir/tests/arrays.rs index 231db2fb085..2b235dcb579 100644 --- a/compiler/noirc_evaluator/src/acir/tests/arrays.rs +++ b/compiler/noirc_evaluator/src/acir/tests/arrays.rs @@ -237,7 +237,7 @@ fn zero_length_array_constant() { private parameters: [] public parameters: [] return values: [] - EXPR 1 = 0 + EXPR 0 = 1 "); } diff --git a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs index 8a7dd222bac..719ff18a90b 100644 --- a/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs +++ b/compiler/noirc_evaluator/src/acir/tests/brillig_call.rs @@ -153,7 +153,7 @@ fn multiple_brillig_stdlib_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 0: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR 0 = w1*w3 - 1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] @@ -162,7 +162,7 @@ fn multiple_brillig_stdlib_calls() { EXPR w5 = -w1*w4 + w0 EXPR w4 = w2 BRILLIG CALL func 0: inputs: [EXPR [ (1, w2) ]], outputs: [w7] - EXPR w2*w7 - 1 = 0 + EXPR 0 = w2*w7 - 1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w8, w9] BLACKBOX::RANGE [w9]:32 bits [] EXPR w10 = w2 - w9 - 1 @@ -241,7 +241,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR 0 = w1*w3 - 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] @@ -254,7 +254,7 @@ fn brillig_stdlib_calls_with_regular_brillig_call() { BRILLIG CALL func 0: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w8] BLACKBOX::RANGE [w8]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w9] - EXPR w2*w9 - 1 = 0 + EXPR 0 = w2*w9 - 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w10, w11] BLACKBOX::RANGE [w11]:32 bits [] EXPR w12 = w2 - w11 - 1 @@ -375,7 +375,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { BLACKBOX::RANGE [w1]:32 bits [] BLACKBOX::RANGE [w2]:32 bits [] BRILLIG CALL func 1: inputs: [EXPR [ (1, w1) ]], outputs: [w3] - EXPR w1*w3 - 1 = 0 + EXPR 0 = w1*w3 - 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w0) ], EXPR [ (1, w1) ]], outputs: [w4, w5] BLACKBOX::RANGE [w4]:32 bits [] BLACKBOX::RANGE [w5]:32 bits [] @@ -390,7 +390,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { CALL func 1: PREDICATE: EXPR [ 1 ] inputs: [w0, w1], outputs: [w9] BRILLIG CALL func 1: inputs: [EXPR [ (1, w2) ]], outputs: [w10] - EXPR w2*w10 - 1 = 0 + EXPR 0 = w2*w10 - 1 BRILLIG CALL func 2: inputs: [EXPR [ (1, w1) ], EXPR [ (1, w2) ]], outputs: [w11, w12] BLACKBOX::RANGE [w12]:32 bits [] EXPR w13 = w2 - w12 - 1 @@ -408,7 +408,7 @@ fn brillig_stdlib_calls_with_multiple_acir_calls() { EXPR w3 = w0 - w1 BRILLIG CALL func 1: inputs: [EXPR [ (1, w3) ]], outputs: [w4] EXPR w5 = -w3*w4 + 1 - EXPR w3*w5 = 0 + EXPR 0 = w3*w5 EXPR w5 = 0 EXPR w2 = w0 From ecfb272712388ecbec34a18c0e95e4f39056d344 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Thu, 25 Sep 2025 14:36:03 -0300 Subject: [PATCH 25/25] Preserve original signs when it's a zero equality --- acvm-repo/acir/src/parser/mod.rs | 50 +++++++++++++------ acvm-repo/acir/src/parser/tests.rs | 21 +++++++- .../acvm/src/compiler/optimizers/general.rs | 6 +-- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 29ab7ec6c4e..a9e0667488d 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -273,23 +273,20 @@ impl<'a> Parser<'a> { // Parse the right-hand side terms let rhs_terms = self.parse_terms_or_error()?; - // "Move" the terms to the right by negating them - let lhs_terms = lhs_terms.into_iter().map(|term| term.negate()).collect::>(); - - // Gather all terms, summing the constants - let mut q_c = FieldElement::zero(); - let mut linear_combinations = Vec::new(); - let mut mul_terms = Vec::new(); - - for term in rhs_terms.into_iter().chain(lhs_terms) { - match term { - Term::Constant(c) => q_c += c, - Term::Linear(c, w) => linear_combinations.push((c, w)), - Term::Multiplication(c, w1, w2) => mul_terms.push((c, w1, w2)), - } - } + // If we have something like `0 = ...` or `... = 0`, just consider the expressions + // on the non-zero side. Otherwise we could be "moving" terms to the other side and + // negating them, which won't accurately reflect the original expression. + let expression = if is_zero_term(&lhs_terms) { + build_expression_from_terms(rhs_terms.into_iter()) + } else if is_zero_term(&rhs_terms) { + build_expression_from_terms(lhs_terms.into_iter()) + } else { + // "Move" the terms to the left by negating them + let rhs_terms = rhs_terms.into_iter().map(|term| term.negate()).collect::>(); + build_expression_from_terms(lhs_terms.into_iter().chain(rhs_terms)) + }; - Ok(Expression { mul_terms, linear_combinations, q_c }) + Ok(expression) } fn parse_terms_or_error(&mut self) -> ParseResult> { @@ -1083,6 +1080,27 @@ impl<'a> Parser<'a> { } } +fn build_expression_from_terms(terms: impl Iterator) -> Expression { + // Gather all terms, summing the constants + let mut q_c = FieldElement::zero(); + let mut linear_combinations = Vec::new(); + let mut mul_terms = Vec::new(); + + for term in terms { + match term { + Term::Constant(c) => q_c += c, + Term::Linear(c, w) => linear_combinations.push((c, w)), + Term::Multiplication(c, w1, w2) => mul_terms.push((c, w1, w2)), + } + } + + Expression { mul_terms, linear_combinations, q_c } +} + +fn is_zero_term(terms: &[Term]) -> bool { + terms.len() == 1 && matches!(terms[0], Term::Constant(c) if c.is_zero()) +} + fn eof_spanned_token() -> SpannedToken { SpannedToken::new(Token::Eof, Default::default()) } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 1e9834c7439..98b0e418dea 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -769,6 +769,25 @@ fn assert_zero_equation() { private parameters: [w0, w1, w2] public parameters: [] return values: [] - EXPR w3 = w0*w1 - w1*w2 - w0*w2 + w2 + w0 - w1 - 40 + EXPR w3 = -w0*w2 + w0*w1 - w1*w2 + w0 - w1 + w2 - 40 + "); +} + +#[test] +fn does_not_negate_when_equal_to_zero() { + let src = " + current witness: w9 + private parameters: [w0, w1, w2] + public parameters: [] + return values: [] + EXPR w0*w1 + w0*w2 = 0 + "; + let circuit = Circuit::from_str(src).unwrap(); + assert_snapshot!(circuit.to_string(), @r" + current witness: w9 + private parameters: [w0, w1, w2] + public parameters: [] + return values: [] + EXPR 0 = w0*w1 + w0*w2 "); } diff --git a/acvm-repo/acvm/src/compiler/optimizers/general.rs b/acvm-repo/acvm/src/compiler/optimizers/general.rs index 45a458c7e53..788981b33af 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/general.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/general.rs @@ -102,7 +102,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 0 = -w0*w1 + EXPR 0 = w0*w1 "); } @@ -147,7 +147,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 0 = -9*w0*w1 + EXPR 0 = 9*w0*w1 "); } @@ -190,7 +190,7 @@ mod tests { private parameters: [w0, w1] public parameters: [] return values: [] - EXPR 0 = -6*w0 + EXPR 0 = 6*w0 "); }