Skip to content

Commit b5e7a7a

Browse files
authored
Merge 7d14952 into 6196d05
2 parents 6196d05 + 7d14952 commit b5e7a7a

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs

+70
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,31 @@ impl<'brillig> Context<'brillig> {
451451
}
452452
}
453453

454+
// If we have an array get whose value is from an array set on the same array at the same index,
455+
// we can simplify that array get to the value of the previous array set.
456+
//
457+
// For example:
458+
// v3 = array_set v0, index v1, value v2
459+
// v4 = array_get v3, index v1 -> Field
460+
//
461+
// We know that `v4` can be simplified to `v2`.
462+
// Thus, even if the index is dynamic (meaning the array get would have side effects),
463+
// we can simplify the operation when we take into account the predicate.
464+
if let Instruction::ArraySet { index, value, .. } = &instruction {
465+
let use_predicate =
466+
self.use_constraint_info && instruction.requires_acir_gen_predicate(dfg);
467+
let predicate = use_predicate.then_some(side_effects_enabled_var);
468+
469+
let array_get = Instruction::ArrayGet { array: instruction_results[0], index: *index };
470+
471+
self.cached_instruction_results
472+
.entry(array_get)
473+
.or_default()
474+
.entry(predicate)
475+
.or_default()
476+
.cache(block, vec![*value]);
477+
}
478+
454479
// If the instruction doesn't have side-effects and if it won't interact with enable_side_effects during acir_gen,
455480
// we cache the results so we can reuse them if the same instruction appears again later in the block.
456481
// Others have side effects representing failure, which are implicit in the ACIR code and can also be deduplicated.
@@ -1521,4 +1546,49 @@ mod test {
15211546
let ssa = ssa.fold_constants_using_constraints();
15221547
assert_normalized_ssa_equals(ssa, expected);
15231548
}
1549+
1550+
#[test]
1551+
fn array_get_from_array_set_with_different_predicates() {
1552+
let src = "
1553+
acir(inline) fn main f0 {
1554+
b0(v0: [Field; 3], v1: u32, v2: Field):
1555+
enable_side_effects u1 0
1556+
v4 = array_set v0, index v1, value v2
1557+
enable_side_effects u1 1
1558+
v6 = array_get v4, index v1 -> Field
1559+
return v6
1560+
}
1561+
";
1562+
1563+
let ssa = Ssa::from_str(src).unwrap();
1564+
1565+
let ssa = ssa.fold_constants_using_constraints();
1566+
// We expect the code to be unchanged
1567+
assert_normalized_ssa_equals(ssa, src);
1568+
}
1569+
1570+
#[test]
1571+
fn array_get_from_array_set_same_predicates() {
1572+
let src = "
1573+
acir(inline) fn main f0 {
1574+
b0(v0: [Field; 3], v1: u32, v2: Field):
1575+
enable_side_effects u1 1
1576+
v4 = array_set v0, index v1, value v2
1577+
v6 = array_get v4, index v1 -> Field
1578+
return v6
1579+
}
1580+
";
1581+
let ssa = Ssa::from_str(src).unwrap();
1582+
1583+
let expected = "
1584+
acir(inline) fn main f0 {
1585+
b0(v0: [Field; 3], v1: u32, v2: Field):
1586+
enable_side_effects u1 1
1587+
v4 = array_set v0, index v1, value v2
1588+
return v2
1589+
}
1590+
";
1591+
let ssa = ssa.fold_constants_using_constraints();
1592+
assert_normalized_ssa_equals(ssa, expected);
1593+
}
15241594
}

0 commit comments

Comments
 (0)