Skip to content

Commit

Permalink
feat(optimization): Follow past array_sets when optimizing `array_g…
Browse files Browse the repository at this point in the history
…et`s (noir-lang/noir#5772)

feat: user `super::` in LSP autocompletion if possible (noir-lang/noir#5751)
fix: unconstrained fn mismatch is now a warning (noir-lang/noir#5764)
feat(perf): mem2reg function state for value loads to optimize across blocks (noir-lang/noir#5757)
feat: add `Expr::as_array`, `Expr::as_repeated_element_array` and same for slice (noir-lang/noir#5750)
chore: Add Brillig loop bytecode size regression and update noir-gates-diff report (noir-lang/noir#5747)
feat: fault-tolerant parsing of `fn` and `impl` (noir-lang/noir#5753)
fix: add missing trait impls for integer types to stdlib (noir-lang/noir#5738)
chore: refactor ACIR function IDs from raw integers to struct (noir-lang/noir#5748)
feat: (LSP) suggest names that match any part of the current prefix (noir-lang/noir#5752)
feat: LSP auto-import completion (noir-lang/noir#5741)
fix: Allow comptime code to use break without also being `unconstrained` (noir-lang/noir#5744)
feat: add `Expr::as_any_integer` and `Expr::as_member_access` (noir-lang/noir#5742)
chore: clarify Field use (noir-lang/noir#5740)
feat: add `Expr::as_binary_op` (noir-lang/noir#5734)
chore(docs): expanding solidity verifier chain list (noir-lang/noir#5587)
chore: apply some new lints across workspace (noir-lang/noir#5736)
feat: suggest trait methods in LSP completion (noir-lang/noir#5735)
feat: LSP autocomplete constructor fields (noir-lang/noir#5732)
feat: add `Expr::as_unary` (noir-lang/noir#5731)
chore: count brillig opcodes in nargo info (noir-lang/noir#5189)
feat: suggest tuple fields in LSP completion (noir-lang/noir#5730)
feat: add `Expr::as_bool` (noir-lang/noir#5729)
feat: add `Expr` methods: `as_tuple`, `as_parenthesized`, `as_index`, `as_if` (noir-lang/noir#5726)
feat: LSP signature help (noir-lang/noir#5725)
chore: split LSP completion.rs into several files (noir-lang/noir#5723)
feat: add `TraitImpl::trait_generic_args` and `TraitImpl::methods` (noir-lang/noir#5722)
fix: let LSP autocompletion work in more contexts (noir-lang/noir#5719)
fix(frontend): Continue type check if we are missing an unsafe block (noir-lang/noir#5720)
feat: add `unsafe` blocks for calling unconstrained code from constrained functions (noir-lang/noir#4429)
  • Loading branch information
AztecBot committed Aug 20, 2024
2 parents 7e37bfd + dfbd8b1 commit 8e40f4a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .noir-sync-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5192e537708fc9ec51f53bb6a6629c9d682532d5
090501dfaf7c569b1aa944856bf68ad663572ae4
72 changes: 63 additions & 9 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,16 +608,11 @@ impl Instruction {
}
}
Instruction::ArrayGet { array, index } => {
let array = dfg.get_array_constant(*array);
let index = dfg.get_numeric_constant(*index);
if let (Some((array, _)), Some(index)) = (array, index) {
let index =
index.try_to_u32().expect("Expected array index to fit in u32") as usize;
if index < array.len() {
return SimplifiedTo(array[index]);
}
if let Some(index) = dfg.get_numeric_constant(*index) {
try_optimize_array_get_from_previous_set(dfg, *array, index)
} else {
None
}
None
}
Instruction::ArraySet { array, index, value, .. } => {
let array = dfg.get_array_constant(*array);
Expand Down Expand Up @@ -744,6 +739,65 @@ impl Instruction {
}
}

/// Given a chain of operations like:
/// v1 = array_set [10, 11, 12], index 1, value: 5
/// v2 = array_set v1, index 2, value: 6
/// v3 = array_set v2, index 2, value: 7
/// v4 = array_get v3, index 1
///
/// We want to optimize `v4` to `10`. To do this we need to follow the array value
/// through several array sets. For each array set:
/// - If the index is non-constant we fail the optimization since any index may be changed
/// - If the index is constant and is our target index, we conservatively fail the optimization
/// in case the array_set is disabled from a previous `enable_side_effects_if` and the array get
/// was not.
/// - Otherwise, we check the array value of the array set.
/// - If the array value is constant, we use that array.
/// - If the array value is from a previous array-set, we recur.
fn try_optimize_array_get_from_previous_set(
dfg: &DataFlowGraph,
mut array_id: Id<Value>,
target_index: FieldElement,
) -> SimplifyResult {
let mut elements = None;

// Arbitrary number of maximum tries just to prevent this optimization from taking too long.
let max_tries = 5;
for _ in 0..max_tries {
match &dfg[array_id] {
Value::Instruction { instruction, .. } => {
match &dfg[*instruction] {
Instruction::ArraySet { array, index, value, .. } => {
if let Some(constant) = dfg.get_numeric_constant(*index) {
if constant == target_index {
return SimplifyResult::SimplifiedTo(*value);
}

array_id = *array; // recur
} else {
return SimplifyResult::None;
}
}
_ => return SimplifyResult::None,
}
}
Value::Array { array, typ: _ } => {
elements = Some(array.clone());
break;
}
_ => return SimplifyResult::None,
}
}

if let (Some(array), Some(index)) = (elements, target_index.try_to_u64()) {
let index = index as usize;
if index < array.len() {
return SimplifyResult::SimplifiedTo(array[index]);
}
}
SimplifyResult::None
}

pub(crate) type ErrorType = HirType;

pub(crate) fn error_selector_from_type(typ: &ErrorType) -> ErrorSelector {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ fn main(
// I believe we want to eventually make it public too though.
key_hash: Field
) {
std::verify_proof(verification_key, proof, public_inputs, key_hash);
std::verify_proof(
verification_key,
proof,
public_inputs,
key_hash
);
}

0 comments on commit 8e40f4a

Please sign in to comment.