diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 3482a8c25c7..f9fd5f41f77 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -9,10 +9,7 @@ use std::collections::BTreeSet; -use crate::{ - brillig::Brillig, - errors::{RuntimeError, SsaReport}, -}; +use crate::errors::{RuntimeError, SsaReport}; use acvm::acir::{ circuit::{ brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs, @@ -318,10 +315,6 @@ impl SsaBuilder { Ok(self.print(msg)) } - fn to_brillig(&self, print_brillig_trace: bool) -> Brillig { - self.ssa.to_brillig(print_brillig_trace) - } - fn print(self, msg: &str) -> Self { if self.print_ssa_passes { println!("{msg}\n{}", self.ssa); diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 0b04d1b63ab..9f305a28c25 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -420,55 +420,6 @@ impl GeneratedAcir { Ok(limb_witnesses) } - /// Returns an expression which represents `lhs * rhs` - /// - /// If one has multiplicative term and the other is of degree one or more, - /// the function creates [intermediate variables][`Witness`] accordingly. - /// There are two cases where we can optimize the multiplication between two expressions: - /// 1. If the sum of the degrees of both expressions is at most 2, then we can just multiply them - /// as each term in the result will be degree-2. - /// 2. If one expression is a constant, then we can just multiply the constant with the other expression - /// - /// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial - /// which is what you get when you multiply two degree-1 univariate polynomials. - pub(crate) fn mul_with_witness(&mut self, lhs: &Expression, rhs: &Expression) -> Expression { - use std::borrow::Cow; - let lhs_is_linear = lhs.is_linear(); - let rhs_is_linear = rhs.is_linear(); - - // Case 1: The sum of the degrees of both expressions is at most 2. - // - // If one of the expressions is constant then it does not increase the degree when multiplying by another expression. - // If both of the expressions are linear (degree <=1) then the product will be at most degree 2. - let both_are_linear = lhs_is_linear && rhs_is_linear; - let either_is_const = lhs.is_const() || rhs.is_const(); - if both_are_linear || either_is_const { - return (lhs * rhs).expect("Both expressions are degree <= 1"); - } - - // Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial - let lhs_reduced = if lhs_is_linear { - Cow::Borrowed(lhs) - } else { - Cow::Owned(self.get_or_create_witness(lhs).into()) - }; - - // If the lhs and rhs are the same, then we do not need to reduce - // rhs, we only need to square the lhs. - if lhs == rhs { - return (&*lhs_reduced * &*lhs_reduced) - .expect("Both expressions are reduced to be degree <= 1"); - }; - - let rhs_reduced = if rhs_is_linear { - Cow::Borrowed(rhs) - } else { - Cow::Owned(self.get_or_create_witness(rhs).into()) - }; - - (&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree <= 1") - } - /// Adds an inversion brillig opcode. /// /// This code will invert `expr` without applying constraints diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index ee236df8eac..6c7d78acdea 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -3277,18 +3277,15 @@ mod test { // This check right now expects to only call one Brillig function. let mut num_normal_brillig_calls = 0; for (i, opcode) in opcodes.iter().enumerate() { - match opcode { - Opcode::BrilligCall { id, .. } => { - if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() { - // We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here - continue; - } - // We only generate one normal Brillig call so we should expect a function ID of `0` - let expected_id = 0u32; - assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); - num_normal_brillig_calls += 1; + if let Opcode::BrilligCall { id, .. } = opcode { + if brillig_stdlib_function_locations.get(&OpcodeLocation::Acir(i)).is_some() { + // We should have already checked Brillig stdlib functions and only want to check normal Brillig calls here + continue; } - _ => {} + // We only generate one normal Brillig call so we should expect a function ID of `0` + let expected_id = 0u32; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + num_normal_brillig_calls += 1; } } diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index e591a3d478c..41ee05982ac 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -11,7 +11,6 @@ use noirc_frontend::monomorphization::ast::{FuncId, Program}; use crate::errors::RuntimeError; use crate::ssa::function_builder::FunctionBuilder; use crate::ssa::ir::basic_block::BasicBlockId; -use crate::ssa::ir::dfg::DataFlowGraph; use crate::ssa::ir::function::{Function, RuntimeType}; use crate::ssa::ir::function::{FunctionId as IrFunctionId, InlineType}; use crate::ssa::ir::instruction::BinaryOp; @@ -1103,72 +1102,6 @@ fn operator_requires_swapped_operands(op: BinaryOpKind) -> bool { matches!(op, Greater | LessEqual) } -/// If the operation requires its result to be truncated because it is an integer, the maximum -/// number of bits that result may occupy is returned. -fn operator_result_max_bit_size_to_truncate( - op: BinaryOpKind, - lhs: ValueId, - rhs: ValueId, - dfg: &DataFlowGraph, -) -> Option { - let lhs_type = dfg.type_of_value(lhs); - let rhs_type = dfg.type_of_value(rhs); - - let get_bit_size = |typ| match typ { - Type::Numeric(NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size }) => { - Some(bit_size) - } - _ => None, - }; - - let lhs_bit_size = get_bit_size(lhs_type)?; - let rhs_bit_size = get_bit_size(rhs_type)?; - use BinaryOpKind::*; - match op { - Add => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), - Subtract => Some(std::cmp::max(lhs_bit_size, rhs_bit_size) + 1), - Multiply => { - if lhs_bit_size == 1 || rhs_bit_size == 1 { - // Truncation is unnecessary as multiplication by a boolean value cannot cause an overflow. - None - } else { - Some(lhs_bit_size + rhs_bit_size) - } - } - - ShiftLeft => { - if let Some(rhs_constant) = dfg.get_numeric_constant(rhs) { - // Happy case is that we know precisely by how many bits the the integer will - // increase: lhs_bit_size + rhs - return Some(lhs_bit_size + (rhs_constant.to_u128() as u32)); - } - // Unhappy case is that we don't yet know the rhs value, (even though it will - // eventually have to resolve to a constant). The best we can is assume the value of - // rhs to be the maximum value of it's numeric type. If that turns out to be larger - // than the native field's bit size, we full back to using that. - - // The formula for calculating the max bit size of a left shift is: - // lhs_bit_size + 2^{rhs_bit_size} - 1 - // Inferring the max bit size of left shift from its operands can result in huge - // number, that might not only be larger than the native field's max bit size, but - // furthermore might not be representable as a u32. Hence we use overflow checks and - // fallback to the native field's max bits. - let field_max_bits = FieldElement::max_num_bits(); - let (rhs_bit_size_pow_2, overflows) = 2_u32.overflowing_pow(rhs_bit_size); - if overflows { - return Some(field_max_bits); - } - let (max_bits_plus_1, overflows) = rhs_bit_size_pow_2.overflowing_add(lhs_bit_size); - if overflows { - return Some(field_max_bits); - } - let max_bit_size = std::cmp::min(max_bits_plus_1 - 1, field_max_bits); - Some(max_bit_size) - } - _ => None, - } -} - /// Converts the given operator to the appropriate BinaryOp. /// Take care when using this to insert a binary instruction: this requires /// checking operator_requires_not and operator_requires_swapped_operands