Skip to content

Commit

Permalink
feat: remove truncation from brillig casts
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Jan 10, 2024
1 parent 5be049e commit 6577625
Showing 1 changed file with 2 additions and 48 deletions.
50 changes: 2 additions & 48 deletions compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ impl<'block> BrilligBlock<'block> {
let source_register = self.convert_ssa_register_value(*value, dfg);
self.brillig_context.truncate_instruction(destination_register, source_register);
}
Instruction::Cast(value, target_type) => {
Instruction::Cast(value, _) => {
let result_ids = dfg.instruction_results(instruction_id);
let destination_register = self.variables.define_register_variable(
self.function_context,
Expand All @@ -541,12 +541,7 @@ impl<'block> BrilligBlock<'block> {
dfg,
);
let source_register = self.convert_ssa_register_value(*value, dfg);
self.convert_cast(
destination_register,
source_register,
target_type,
&dfg.type_of_value(*value),
);
self.brillig_context.mov_instruction(destination_register, source_register);
}
Instruction::ArrayGet { array, index } => {
let result_ids = dfg.instruction_results(instruction_id);
Expand Down Expand Up @@ -1090,47 +1085,6 @@ impl<'block> BrilligBlock<'block> {
self.brillig_context.usize_op(source_len, target_len, binary_op, 1);
}

/// Converts an SSA cast to a sequence of Brillig opcodes.
/// Casting is only necessary when shrinking the bit size of a numeric value.
fn convert_cast(
&mut self,
destination: RegisterIndex,
source: RegisterIndex,
target_type: &Type,
source_type: &Type,
) {
fn numeric_to_bit_size(typ: &NumericType) -> u32 {
match typ {
NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => *bit_size,
NumericType::NativeField => FieldElement::max_num_bits(),
}
}
// Casting is only valid for numeric types
// This should be checked by the frontend, so we panic if this is the case
let (source_numeric_type, target_numeric_type) = match (source_type, target_type) {
(Type::Numeric(source_numeric_type), Type::Numeric(target_numeric_type)) => {
(source_numeric_type, target_numeric_type)
}
_ => unimplemented!("The cast operation is only valid for integers."),
};
let source_bit_size = numeric_to_bit_size(source_numeric_type);
let target_bit_size = numeric_to_bit_size(target_numeric_type);
// Casting from a larger bit size to a smaller bit size (narrowing cast)
// requires a cast instruction.
// If its a widening cast, ie casting from a smaller bit size to a larger bit size
// we simply put a mov instruction as a no-op
//
// Field elements by construction always have the largest bit size
// This means that casting to a Field element, will always be a widening cast
// and therefore a no-op. Conversely, casting from a Field element
// will always be a narrowing cast and therefore a cast instruction
if source_bit_size > target_bit_size {
self.brillig_context.cast_instruction(destination, source, target_bit_size);
} else {
self.brillig_context.mov_instruction(destination, source);
}
}

/// Converts the Binary instruction into a sequence of Brillig opcodes.
fn convert_ssa_binary(
&mut self,
Expand Down

0 comments on commit 6577625

Please sign in to comment.