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

chore(ssa refactor): array eq ACIR gen #1701

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
a = [77,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102]
b = [44,75,108,209,54,16,50,202,155,210,174,185,217,0,170,77,69,217,234,216,10,201,66,51,116,196,81,167,37,77,7,102]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Simple example of checking where two arrays are different
fn main(a: [Field; 32], b: [Field; 32]) {
assert(a != b);
}
64 changes: 58 additions & 6 deletions crates/noirc_evaluator/src/ssa_refactor/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use super::{
};
use crate::brillig::{artifact::BrilligArtifact, Brillig};
use acvm::FieldElement;
use iter_extended::vecmap;
use iter_extended::{try_vecmap, vecmap};

pub(crate) use acir_ir::generated_acir::GeneratedAcir;

Expand Down Expand Up @@ -342,7 +342,7 @@ impl Context {
Value::Intrinsic(..) => todo!(),
Value::Function(..) => unreachable!("ICE: All functions should have been inlined"),
Value::Instruction { .. } | Value::Param { .. } => {
unreachable!("ICE: Should have been in cache {value:?}")
unreachable!("ICE: Value {value_id:?} should have been in cache {value:?}")
}
};
self.ssa_values.insert(value_id, acir_value.clone());
Expand All @@ -355,15 +355,19 @@ impl Context {
dfg: &DataFlowGraph,
) -> im::Vector<AcirValue> {
match self.convert_value(value_id, dfg) {
AcirValue::Var(acir_var, _) => panic!("Expected an array value, found: {acir_var:?}"),
AcirValue::Var(acir_var, _) => {
panic!("Expected an array value at {value_id:?}, found: {acir_var:?}")
}
AcirValue::Array(array) => array,
}
}

fn convert_numeric_value(&mut self, value_id: ValueId, dfg: &DataFlowGraph) -> AcirVar {
match self.convert_value(value_id, dfg) {
AcirValue::Var(acir_var, _) => acir_var,
AcirValue::Array(array) => panic!("Expected a numeric value, found: {array:?}"),
AcirValue::Array(array) => {
panic!("Expected a numeric value at {value_id:?}, found: {array:?}")
}
}
}

Expand All @@ -373,8 +377,16 @@ impl Context {
binary: &Binary,
dfg: &DataFlowGraph,
) -> Result<AcirVar, AcirGenError> {
let lhs = self.convert_numeric_value(binary.lhs, dfg);
let rhs = self.convert_numeric_value(binary.rhs, dfg);
let lhs = self.convert_value(binary.lhs, dfg);
let rhs = self.convert_value(binary.rhs, dfg);

let (lhs, rhs) = match (lhs, rhs) {
(AcirValue::Array(lhs), AcirValue::Array(rhs)) => {
return self.convert_ssa_array_binary(binary.operator, lhs, rhs);
}
(AcirValue::Var(lhs, _), AcirValue::Var(rhs, _)) => (lhs, rhs),
_ => unreachable!("Binary operands must both be vars or both be arrays"),
};

let binary_type = self.type_of_binary_operation(binary, dfg);
match &binary_type {
Expand Down Expand Up @@ -420,6 +432,46 @@ impl Context {
}
}

fn convert_ssa_array_binary(
&mut self,
operator: BinaryOp,
lhs: im::Vector<AcirValue>,
rhs: im::Vector<AcirValue>,
) -> Result<AcirVar, AcirGenError> {
assert_eq!(operator, BinaryOp::Eq, "Only array equality is supported");
assert_eq!(
lhs.len(),
rhs.len(),
"Arrays of different lengths cannot be checked for equality"
);
let unwrap_values = |values: im::Vector<AcirValue>| {
vecmap(values, |elem| match elem {
AcirValue::Var(var, _) => var,
_ => unreachable!("Nested array equality is not supported"),
})
};
let lhs_vars = unwrap_values(lhs);
let rhs_vars = unwrap_values(rhs);

let mut elem_equalities =
try_vecmap(lhs_vars.into_iter().zip(rhs_vars.into_iter()), |(lhs_elem, rhs_elem)| {
self.acir_context.eq_var(lhs_elem, rhs_elem)
})?;

if let Some(last_elem) = elem_equalities.pop() {
let mut coalesced_eq_var = last_elem;
for elem_eq in elem_equalities {
coalesced_eq_var =
self.acir_context.and_var(coalesced_eq_var, elem_eq, Type::bool().into())?;
}
Ok(coalesced_eq_var)
} else {
// Arrays are empty, therefore the equality is always true
let true_var = self.acir_context.add_constant(FieldElement::one());
Ok(true_var)
}
}

/// Operands in a binary operation are checked to have the same type.
///
/// In Noir, binary operands should have the same type due to the language
Expand Down