Skip to content

Commit

Permalink
chore: make eval_constants a pure function (noir-lang#3027)
Browse files Browse the repository at this point in the history
Co-authored-by: kevaundray <kevtheappdev@gmail.com>
  • Loading branch information
2 people authored and Sakapoi committed Oct 19, 2023
1 parent ab359f4 commit 81c40af
Showing 1 changed file with 42 additions and 42 deletions.
84 changes: 42 additions & 42 deletions compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,15 +646,11 @@ impl Binary {
let operand_type = dfg.type_of_value(self.lhs);

if let (Some(lhs), Some(rhs)) = (lhs, rhs) {
// If the rhs of a division is zero, attempting to evaluate the divison will cause a compiler panic.
// Thus, we do not evaluate this divison as we want to avoid triggering a panic,
// and division by zero should be handled by laying down constraints during ACIR generation.
if matches!(self.operator, BinaryOp::Div | BinaryOp::Mod) && rhs == FieldElement::zero()
{
return SimplifyResult::None;
}
return match self.eval_constants(dfg, lhs, rhs, operand_type) {
Some(value) => SimplifyResult::SimplifiedTo(value),
return match eval_constant_binary_op(lhs, rhs, self.operator, operand_type) {
Some((result, result_type)) => {
let value = dfg.make_constant(result, result_type);
SimplifyResult::SimplifiedTo(value)
}
None => SimplifyResult::None,
};
}
Expand Down Expand Up @@ -775,47 +771,51 @@ impl Binary {
}
SimplifyResult::None
}
}

/// Evaluate the two constants with the operation specified by self.operator.
/// Pushes the resulting value to the given DataFlowGraph's constants and returns it.
fn eval_constants(
&self,
dfg: &mut DataFlowGraph,
lhs: FieldElement,
rhs: FieldElement,
mut operand_type: Type,
) -> Option<Id<Value>> {
let value = match &operand_type {
Type::Numeric(NumericType::NativeField) => {
self.operator.get_field_function()?(lhs, rhs)
}
Type::Numeric(NumericType::Unsigned { bit_size }) => {
let function = self.operator.get_u128_function();

let lhs = truncate(lhs.try_into_u128()?, *bit_size);
let rhs = truncate(rhs.try_into_u128()?, *bit_size);
/// Evaluate a binary operation with constant arguments.
fn eval_constant_binary_op(
lhs: FieldElement,
rhs: FieldElement,
operator: BinaryOp,
mut operand_type: Type,
) -> Option<(FieldElement, Type)> {
let value = match &operand_type {
Type::Numeric(NumericType::NativeField) => {
// If the rhs of a division is zero, attempting to evaluate the division will cause a compiler panic.
// Thus, we do not evaluate the division in this method, as we want to avoid triggering a panic,
// and the operation should be handled by ACIR generation.
if matches!(operator, BinaryOp::Div | BinaryOp::Mod) && rhs == FieldElement::zero() {
return None;
}
operator.get_field_function()?(lhs, rhs)
}
Type::Numeric(NumericType::Unsigned { bit_size }) => {
let function = operator.get_u128_function();

// The divisor is being truncated into the type of the operand, which can potentially
// lead to the rhs being zero.
// If the rhs of a division is zero, attempting to evaluate the divison will cause a compiler panic.
// Thus, we do not evaluate the division in this method, as we want to avoid triggering a panic,
// and the operation should be handled by ACIR generation.
if matches!(self.operator, BinaryOp::Div) && rhs == 0 {
return None;
}
let lhs = truncate(lhs.try_into_u128()?, *bit_size);
let rhs = truncate(rhs.try_into_u128()?, *bit_size);

let result = function(lhs, rhs);
truncate(result, *bit_size).into()
// The divisor is being truncated into the type of the operand, which can potentially
// lead to the rhs being zero.
// If the rhs of a division is zero, attempting to evaluate the division will cause a compiler panic.
// Thus, we do not evaluate the division in this method, as we want to avoid triggering a panic,
// and the operation should be handled by ACIR generation.
if matches!(operator, BinaryOp::Div | BinaryOp::Mod) && rhs == 0 {
return None;
}
_ => return None,
};

if matches!(self.operator, BinaryOp::Eq | BinaryOp::Lt) {
operand_type = Type::bool();
let result = function(lhs, rhs);
truncate(result, *bit_size).into()
}
_ => return None,
};

Some(dfg.make_constant(value, operand_type))
if matches!(operator, BinaryOp::Eq | BinaryOp::Lt) {
operand_type = Type::bool();
}

Some((value, operand_type))
}

fn truncate(int: u128, bit_size: u32) -> u128 {
Expand Down

0 comments on commit 81c40af

Please sign in to comment.