From 59c33e5de1304e63772247f06675d6f3aa8c87d8 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 14 Jan 2025 17:18:42 +0000 Subject: [PATCH] feat: remove `max_bit_size` from `Instruction::truncate` --- compiler/noirc_evaluator/src/acir/acir_variable.rs | 3 +-- compiler/noirc_evaluator/src/acir/mod.rs | 7 +++---- .../noirc_evaluator/src/ssa/function_builder/mod.rs | 3 +-- compiler/noirc_evaluator/src/ssa/ir/instruction.rs | 13 ++++++------- .../src/ssa/ir/instruction/binary.rs | 2 -- compiler/noirc_evaluator/src/ssa/ir/printer.rs | 4 ++-- .../src/ssa/opt/remove_bit_shifts.rs | 9 ++++----- compiler/noirc_evaluator/src/ssa/parser/ast.rs | 1 - compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs | 4 ++-- compiler/noirc_evaluator/src/ssa/parser/mod.rs | 8 ++------ compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs | 8 ++++---- 11 files changed, 25 insertions(+), 37 deletions(-) diff --git a/compiler/noirc_evaluator/src/acir/acir_variable.rs b/compiler/noirc_evaluator/src/acir/acir_variable.rs index cf6b1fcc7f7..d403fc8231b 100644 --- a/compiler/noirc_evaluator/src/acir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/acir/acir_variable.rs @@ -1141,14 +1141,13 @@ impl> AcirContext { &mut self, lhs: AcirVar, rhs: u32, - max_bit_size: u32, ) -> Result { // 2^{rhs} let divisor = self.add_constant(F::from(2_u128).pow(&F::from(rhs as u128))); let one = self.add_constant(F::one()); // Computes lhs = 2^{rhs} * q + r - let (_, remainder) = self.euclidean_division_var(lhs, divisor, max_bit_size, one)?; + let (_, remainder) = self.euclidean_division_var(lhs, divisor, F::max_num_bits(), one)?; Ok(remainder) } diff --git a/compiler/noirc_evaluator/src/acir/mod.rs b/compiler/noirc_evaluator/src/acir/mod.rs index a250189d3f1..48b0c3b6814 100644 --- a/compiler/noirc_evaluator/src/acir/mod.rs +++ b/compiler/noirc_evaluator/src/acir/mod.rs @@ -745,9 +745,9 @@ impl<'a> Context<'a> { let result_acir_var = self.acir_context.not_var(acir_var, typ)?; self.define_result_var(dfg, instruction_id, result_acir_var); } - Instruction::Truncate { value, bit_size, max_bit_size } => { + Instruction::Truncate { value, bit_size } => { let result_acir_var = - self.convert_ssa_truncate(*value, *bit_size, *max_bit_size, dfg)?; + self.convert_ssa_truncate(*value, *bit_size, dfg)?; self.define_result_var(dfg, instruction_id, result_acir_var); } Instruction::EnableSideEffectsIf { condition } => { @@ -2065,7 +2065,6 @@ impl<'a> Context<'a> { &mut self, value_id: ValueId, bit_size: u32, - max_bit_size: u32, dfg: &DataFlowGraph, ) -> Result { let mut var = self.convert_numeric_value(value_id, dfg)?; @@ -2090,7 +2089,7 @@ impl<'a> Context<'a> { ), }; - self.acir_context.truncate_var(var, bit_size, max_bit_size) + self.acir_context.truncate_var(var, bit_size) } /// Returns a vector of `AcirVar`s constrained to be result of the function call. diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 3d7e0b06d5b..d9df915e8a7 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -273,9 +273,8 @@ impl FunctionBuilder { &mut self, value: ValueId, bit_size: u32, - max_bit_size: u32, ) -> ValueId { - self.insert_instruction(Instruction::Truncate { value, bit_size, max_bit_size }, None) + self.insert_instruction(Instruction::Truncate { value, bit_size }, None) .first() } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 786c3671d38..6d093e709b2 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -251,7 +251,7 @@ pub(crate) enum Instruction { Not(ValueId), /// Truncates `value` to `bit_size` - Truncate { value: ValueId, bit_size: u32, max_bit_size: u32 }, + Truncate { value: ValueId, bit_size: u32 }, /// Constrains two values to be equal to one another. Constrain(ValueId, ValueId, Option), @@ -635,10 +635,9 @@ impl Instruction { }), Instruction::Cast(value, typ) => Instruction::Cast(f(*value), *typ), Instruction::Not(value) => Instruction::Not(f(*value)), - Instruction::Truncate { value, bit_size, max_bit_size } => Instruction::Truncate { + Instruction::Truncate { value, bit_size } => Instruction::Truncate { value: f(*value), bit_size: *bit_size, - max_bit_size: *max_bit_size, }, Instruction::Constrain(lhs, rhs, assert_message) => { // Must map the `lhs` and `rhs` first as the value `f` is moved with the closure @@ -711,7 +710,7 @@ impl Instruction { } Instruction::Cast(value, _) => *value = f(*value), Instruction::Not(value) => *value = f(*value), - Instruction::Truncate { value, bit_size: _, max_bit_size: _ } => { + Instruction::Truncate { value, bit_size: _, } => { *value = f(*value); } Instruction::Constrain(lhs, rhs, assert_message) => { @@ -908,8 +907,8 @@ impl Instruction { try_optimize_array_set_from_previous_get(dfg, *array_id, *index_id, *value) } - Instruction::Truncate { value, bit_size, max_bit_size } => { - if bit_size == max_bit_size { + Instruction::Truncate { value, bit_size } => { + if *bit_size == FieldElement::max_num_bits() { return SimplifiedTo(*value); } if let Some((numeric_constant, typ)) = dfg.get_numeric_constant_with_type(*value) { @@ -920,7 +919,7 @@ impl Instruction { match &dfg[*instruction] { Instruction::Truncate { bit_size: src_bit_size, .. } => { // If we're truncating the value to fit into the same or larger bit size then this is a noop. - if src_bit_size <= bit_size && src_bit_size <= max_bit_size { + if src_bit_size <= bit_size { SimplifiedTo(*value) } else { None diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs index df1e8f537da..7623f918470 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs @@ -223,7 +223,6 @@ impl Binary { Instruction::Truncate { value: self.lhs, bit_size, - max_bit_size: lhs_type.bit_size(), }, ); } @@ -305,7 +304,6 @@ impl Binary { Instruction::Truncate { value, bit_size: num_bits, - max_bit_size: lhs_type.bit_size(), }, ); } diff --git a/compiler/noirc_evaluator/src/ssa/ir/printer.rs b/compiler/noirc_evaluator/src/ssa/ir/printer.rs index 7fe12b83ea9..05a10f86948 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -180,9 +180,9 @@ fn display_instruction_inner( } Instruction::Cast(lhs, typ) => writeln!(f, "cast {} as {typ}", show(*lhs)), Instruction::Not(rhs) => writeln!(f, "not {}", show(*rhs)), - Instruction::Truncate { value, bit_size, max_bit_size } => { + Instruction::Truncate { value, bit_size } => { let value = show(*value); - writeln!(f, "truncate {value} to {bit_size} bits, max_bit_size: {max_bit_size}",) + writeln!(f, "truncate {value} to {bit_size} bits",) } Instruction::Constrain(lhs, rhs, error) => { write!(f, "constrain {} == {}", show(*lhs), show(*rhs))?; diff --git a/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs b/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs index e36be71aeea..316b7f89290 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs @@ -150,7 +150,7 @@ impl Context<'_> { // Unchecked mul as this is a wrapping operation that we later truncate let result = self.insert_binary(lhs_field, BinaryOp::Mul { unchecked: true }, pow_field); - let result = self.insert_truncate(result, bit_size, max_bit); + let result = self.insert_truncate(result, bit_size); self.insert_cast(result, typ) } } @@ -184,7 +184,7 @@ impl Context<'_> { BinaryOp::Add { unchecked: true }, lhs_as_field, ); - let one_complement = self.insert_truncate(one_complement, bit_size, bit_size + 1); + let one_complement = self.insert_truncate(one_complement, bit_size); let one_complement = self.insert_cast(one_complement, NumericType::signed(bit_size)); // Performs the division on the 1-complement (or the operand if positive) let shifted_complement = self.insert_binary(one_complement, BinaryOp::Div, pow); @@ -201,7 +201,7 @@ impl Context<'_> { BinaryOp::Sub { unchecked: true }, lhs_sign_as_int, ); - self.insert_truncate(shifted, bit_size, bit_size + 1) + self.insert_truncate(shifted, bit_size) } } @@ -280,9 +280,8 @@ impl Context<'_> { &mut self, value: ValueId, bit_size: u32, - max_bit_size: u32, ) -> ValueId { - self.insert_instruction(Instruction::Truncate { value, bit_size, max_bit_size }, None) + self.insert_instruction(Instruction::Truncate { value, bit_size }, None) .first() } diff --git a/compiler/noirc_evaluator/src/ssa/parser/ast.rs b/compiler/noirc_evaluator/src/ssa/parser/ast.rs index 6c7608a2f16..6539de018b8 100644 --- a/compiler/noirc_evaluator/src/ssa/parser/ast.rs +++ b/compiler/noirc_evaluator/src/ssa/parser/ast.rs @@ -126,7 +126,6 @@ pub(crate) enum ParsedInstruction { target: Identifier, value: ParsedValue, bit_size: u32, - max_bit_size: u32, }, } diff --git a/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs b/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs index fcaaf74f533..8a300fa1e3b 100644 --- a/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs +++ b/compiler/noirc_evaluator/src/ssa/parser/into_ssa.rs @@ -270,9 +270,9 @@ impl Translator { let address = self.translate_value(address)?; self.builder.insert_store(address, value); } - ParsedInstruction::Truncate { target, value, bit_size, max_bit_size } => { + ParsedInstruction::Truncate { target, value, bit_size} => { let value = self.translate_value(value)?; - let value_id = self.builder.insert_truncate(value, bit_size, max_bit_size); + let value_id = self.builder.insert_truncate(value, bit_size); self.define_variable(target, value_id)?; } } diff --git a/compiler/noirc_evaluator/src/ssa/parser/mod.rs b/compiler/noirc_evaluator/src/ssa/parser/mod.rs index 143ba511879..45a59a68a0f 100644 --- a/compiler/noirc_evaluator/src/ssa/parser/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/parser/mod.rs @@ -506,12 +506,8 @@ impl<'a> Parser<'a> { let value = self.parse_value_or_error()?; self.eat_or_error(Token::Keyword(Keyword::To))?; let bit_size = self.eat_int_or_error()?.to_u128() as u32; - self.eat_or_error(Token::Keyword(Keyword::Bits))?; - self.eat_or_error(Token::Comma)?; - self.eat_or_error(Token::Keyword(Keyword::MaxBitSize))?; - self.eat_or_error(Token::Colon)?; - let max_bit_size = self.eat_int_or_error()?.to_u128() as u32; - return Ok(ParsedInstruction::Truncate { target, value, bit_size, max_bit_size }); + self.eat_or_error(Token::Keyword(Keyword::Bits))?;`` + return Ok(ParsedInstruction::Truncate { target, value, bit_size }); } if let Some(op) = self.eat_binary_op()? { diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 1e7a9b7e8b1..0dc25a868ca 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -382,7 +382,7 @@ impl<'a> FunctionContext<'a> { match operator { BinaryOpKind::Add | BinaryOpKind::Subtract => { // Result is computed modulo the bit size - let result = self.builder.insert_truncate(result, bit_size, bit_size + 1); + let result = self.builder.insert_truncate(result, bit_size); let result = self.insert_safe_cast( result, NumericType::unsigned(bit_size), @@ -396,7 +396,7 @@ impl<'a> FunctionContext<'a> { // Result is computed modulo the bit size let mut result = self.builder.insert_cast(result, NumericType::unsigned(2 * bit_size)); - result = self.builder.insert_truncate(result, bit_size, 2 * bit_size); + result = self.builder.insert_truncate(result, bit_size); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); self.insert_safe_cast(result, result_type, location) @@ -461,7 +461,7 @@ impl<'a> FunctionContext<'a> { one, Some("attempt to bit-shift with overflow".to_owned().into()), ); - self.builder.insert_truncate(result, bit_size, bit_size + 1) + self.builder.insert_truncate(result, bit_size) } /// Insert constraints ensuring that the operation does not overflow the bit size of the result @@ -641,7 +641,7 @@ impl<'a> FunctionContext<'a> { let incoming_type_size = self.builder.type_of_value(value).bit_size(); let target_type_size = typ.bit_size(); if target_type_size < incoming_type_size { - value = self.builder.insert_truncate(value, target_type_size, incoming_type_size); + value = self.builder.insert_truncate(value, target_type_size); } self.builder.insert_cast(value, typ)