Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ssa): fix the compile-time check for equality in acir-gen #904

Merged
merged 1 commit into from
Feb 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions crates/noirc_evaluator/src/ssa/acir_gen/operations/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ pub(crate) fn evaluate_neq(
ctx: &SsaContext,
evaluator: &mut Evaluator,
) -> Expression {
// Check whether the `lhs` and `rhs` are trivially equal
if lhs == rhs {
return Expression::zero();
}

// Check whether the `lhs` and `rhs` are Arrays
if let (Some(a), Some(b)) = (Memory::deref(ctx, lhs), Memory::deref(ctx, rhs)) {
let array_a = &ctx.mem[a];
Expand Down Expand Up @@ -64,28 +69,30 @@ pub(crate) fn evaluate_neq(

return Expression::from(&constraints::evaluate_zero_equality(x_witness, evaluator));
}

// Arriving here means that `lhs` and `rhs` are not Arrays
let l_c = l_c.expect("ICE: unexpected array pointer");
let r_c = r_c.expect("ICE: unexpected array pointer");
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
// Arriving here means that `lhs` and `rhs` are not Arrays
//
// Check if `lhs` and `rhs` are constants. If so, we can evaluate whether
// they are equal at compile time.
if let (Some(l), Some(r)) = (l_c.to_const(), r_c.to_const()) {
if l == r {
return Expression::default();
} else {
return Expression::one();
}
}
let mut x = InternalVar::from(constraints::subtract(
l_c.expression(),
FieldElement::one(),
r_c.expression(),
));
//todo we need a witness because of the directive, but we should use an expression
let x_witness =
x.get_or_compute_witness(evaluator, false).expect("unexpected constant expression");
Expression::from(&constraints::evaluate_zero_equality(x_witness, evaluator))

// Check if `x` is constant. If so, we can evaluate whether
// it is zero at compile time.
if let Some(x_const) = x.to_const() {
if x_const.is_zero() {
Expression::zero()
} else {
Expression::one()
}
} else {
//todo we need a witness because of the directive, but we should use an expression
let x_witness =
x.get_or_compute_witness(evaluator, false).expect("unexpected constant expression");
Expression::from(&constraints::evaluate_zero_equality(x_witness, evaluator))
}
}

pub(crate) fn evaluate_eq(
Expand Down