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: update noir for acir simplify feature #1333

Closed
wants to merge 9 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
37 changes: 33 additions & 4 deletions crates/noirc_evaluator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use acvm::{
acir::native_types::{Expression, Witness},
compiler::optimizers::simplify::CircuitSimplifier,
Language,
//compiler::optimizers::simplify,
};
use errors::{RuntimeError, RuntimeErrorKind};
use iter_extended::btree_map;
Expand All @@ -23,7 +24,9 @@ use noirc_frontend::monomorphization::ast::*;
use ssa::{node::ObjectType, ssa_gen::IrGenerator};
use std::collections::{BTreeMap, BTreeSet};

#[derive(Default)]
static _UNSASTISFIED_CONSTRAIN_ERR: &str = "Cannot satisfy constraint";

//#[derive(Default)]
pub struct Evaluator {
// Why is this not u64?
//
Expand Down Expand Up @@ -56,8 +59,23 @@ pub struct Evaluator {
return_is_distinct: bool,

opcodes: Vec<AcirOpcode>,
simplifier: CircuitSimplifier,
}

impl Default for Evaluator {
fn default() -> Self {
Evaluator {
current_witness_index: u32::default(),
num_witnesses_abi_len: usize::default(),
param_witnesses: BTreeMap::default(),
public_parameters: BTreeSet::default(),
return_values: Vec::default(),
return_is_distinct: bool::default(),
opcodes: Vec::default(),
simplifier: CircuitSimplifier::new(0),
}
}
}
/// Compiles the Program into ACIR and applies optimizations to the arithmetic gates
// XXX: We return the num_witnesses, but this is the max number of witnesses
// Some of these could have been removed due to optimizations. We need this number because the
Expand All @@ -83,7 +101,7 @@ pub fn create_circuit(
opcodes,
..
} = evaluator;
let simplifier = CircuitSimplifier::new(current_witness_index);

let optimized_circuit = acvm::compiler::compile(
Circuit {
current_witness_index,
Expand All @@ -93,7 +111,7 @@ pub fn create_circuit(
},
np_language,
is_opcode_supported,
&simplifier,
&evaluator.simplifier,
)
.map_err(|_| RuntimeErrorKind::Spanless(String::from("produced an acvm compile error")))?;

Expand Down Expand Up @@ -141,8 +159,18 @@ impl Evaluator {
self.current_witness_index
}

pub fn push_opcode(&mut self, gate: AcirOpcode) {
pub fn push_opcode(&mut self, gate: AcirOpcode) -> Result<(), RuntimeErrorKind> {
self.opcodes.push(gate);
// TODO uncomment to activate the simplification
// if let simplify::SimplifyResult::UnsatisfiedConstrain(_g) =
// self.simplifier.simplify(&mut self.opcodes)
// {
// //TODO add location
// return Err(RuntimeErrorKind::UnstructuredError {
// message: UNSASTISFIED_CONSTRAIN_ERR.to_string(),
// });
// }
Ok(())
}

/// Compiles the AST into the intermediate format by evaluating the main function
Expand All @@ -161,6 +189,7 @@ impl Evaluator {
ir_gen.ssa_gen_main()?;

//Generates ACIR representation:
self.simplifier = CircuitSimplifier::new(self.num_witnesses_abi_len as u32);
ir_gen.context.ir_to_acir(self, enable_logging, show_output)?;
Ok(())
}
Expand Down
22 changes: 12 additions & 10 deletions crates/noirc_evaluator/src/ssa/acir_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Acir {
//TODO we should rather follow the jumps
current_block = block.left.map(|block_id| &ctx[block_id]);
}
self.memory.acir_gen(evaluator, ctx);
self.memory.acir_gen(evaluator, ctx)?;
Ok(())
}

Expand All @@ -72,9 +72,11 @@ impl Acir {
Operation::Constrain(value, ..) => {
constrain::evaluate(value, var_cache, evaluator, ctx)
}
Operation::Not(value) => not::evaluate(value, ins.res_type, var_cache, evaluator, ctx),
Operation::Not(value) => {
Ok(not::evaluate(value, ins.res_type, var_cache, evaluator, ctx))
}
Operation::Cast(value) => {
self.var_cache.get_or_compute_internal_var(*value, evaluator, ctx)
Ok(self.var_cache.get_or_compute_internal_var(*value, evaluator, ctx))
}
Operation::Truncate { value, bit_size, max_bit_size } => {
truncate::evaluate(value, *bit_size, *max_bit_size, var_cache, evaluator, ctx)
Expand All @@ -92,18 +94,18 @@ impl Acir {
intrinsics::evaluate(args, ins, opcode, self, ctx, evaluator)
}
Operation::Return(node_ids) => {
r#return::evaluate(node_ids, acir_mem, var_cache, evaluator, ctx)?
Ok(r#return::evaluate(node_ids, acir_mem, var_cache, evaluator, ctx)?)
}
Operation::Cond { condition, val_true: lhs, val_false: rhs } => {
condition::evaluate(*condition, *lhs, *rhs, var_cache, evaluator, ctx)
Ok(condition::evaluate(*condition, *lhs, *rhs, var_cache, evaluator, ctx))
}
Operation::Load { array_id, index, location } => Some(load::evaluate(
Operation::Load { array_id, index, location } => Ok(Some(load::evaluate(
*array_id, *index, acir_mem, var_cache, *location, evaluator, ctx,
)?),
)?)),
Operation::Store { .. } => {
store::evaluate(&ins.operation, acir_mem, var_cache, evaluator, ctx)?
store::evaluate(&ins.operation, acir_mem, var_cache, evaluator, ctx)
}
Operation::Nop => None,
Operation::Nop => Ok(None),
i @ Operation::Jne(..)
| i @ Operation::Jeq(..)
| i @ Operation::Jmp(_)
Expand All @@ -112,7 +114,7 @@ impl Acir {
| i @ Operation::Result { .. } => {
unreachable!("Invalid instruction: {:?}", i);
}
};
}?;

// If the operation returned an `InternalVar`
// then we add it to the `InternalVar` cache
Expand Down
36 changes: 24 additions & 12 deletions crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{
errors::RuntimeError,
ssa::{
acir_gen::InternalVar,
context::SsaContext,
Expand Down Expand Up @@ -121,25 +122,30 @@ impl ArrayHeap {
inputs: Vec<Expression>,
bits: &mut Vec<Witness>,
evaluator: &mut Evaluator,
) -> Vec<Expression> {
) -> Result<Vec<Expression>, RuntimeError> {
let outputs = vecmap(0..inputs.len(), |_| evaluator.add_witness_to_cs().into());
if bits.is_empty() {
*bits = operations::sort::evaluate_permutation(&inputs, &outputs, evaluator);
*bits = operations::sort::evaluate_permutation(&inputs, &outputs, evaluator)?;
} else {
operations::sort::evaluate_permutation_with_witness(&inputs, &outputs, bits, evaluator);
}
outputs
Ok(outputs)
}

pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, array_id: ArrayId, array_len: u32) {
pub(crate) fn acir_gen(
&self,
evaluator: &mut Evaluator,
array_id: ArrayId,
array_len: u32,
) -> Result<(), RuntimeError> {
let (len, read_write) = match self.typ {
ArrayType::Init(_, _) | ArrayType::WriteOnly => (0, true),
ArrayType::ReadOnly(last) => (last.unwrap_or(self.trace.len()), false),
ArrayType::ReadWrite(last) => (last.unwrap_or(self.trace.len()), true),
};

if len == 0 {
return;
return Ok(());
}
evaluator.opcodes.push(AcirOpcode::Block(MemoryBlock {
id: AcirBlockId(array_id.as_u32()),
Expand All @@ -165,11 +171,11 @@ impl ArrayHeap {
tuple_expressions.push(vec![item.index.clone(), counter_expr.clone()]);
}
let mut bit_counter = Vec::new();
let out_counter = Self::generate_outputs(in_counter, &mut bit_counter, evaluator);
let out_index = Self::generate_outputs(in_index, &mut bit_counter, evaluator);
let out_value = Self::generate_outputs(in_value, &mut bit_counter, evaluator);
let out_counter = Self::generate_outputs(in_counter, &mut bit_counter, evaluator)?;
let out_index = Self::generate_outputs(in_index, &mut bit_counter, evaluator)?;
let out_value = Self::generate_outputs(in_value, &mut bit_counter, evaluator)?;
let out_op = if read_write {
Self::generate_outputs(in_op, &mut bit_counter, evaluator)
Self::generate_outputs(in_op, &mut bit_counter, evaluator)?
} else {
Vec::new()
};
Expand All @@ -196,7 +202,7 @@ impl ArrayHeap {
len_bits,
false,
evaluator,
);
)?;
let sub_cmp = subtract(&cmp, FieldElement::one(), &Expression::one());
let secondary_order = subtract(
&mul_with_witness(evaluator, &index_sub, &sub_cmp),
Expand All @@ -220,6 +226,7 @@ impl ArrayHeap {
};
evaluator.opcodes.push(AcirOpcode::Arithmetic(load_on_same_adr));
}
Ok(())
}
}

Expand Down Expand Up @@ -317,10 +324,15 @@ impl AcirMem {
let item = MemOp { operation: op, value, index };
self.array_heap_mut(*array_id).push(item);
}
pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, ctx: &SsaContext) {
pub(crate) fn acir_gen(
&self,
evaluator: &mut Evaluator,
ctx: &SsaContext,
) -> Result<(), RuntimeError> {
for mem in &self.virtual_memory {
let array = &ctx.mem[*mem.0];
mem.1.acir_gen(evaluator, array.id, array.len);
mem.1.acir_gen(evaluator, array.id, array.len)?;
}
Ok(())
}
}
Loading