@@ -451,6 +451,31 @@ impl<'brillig> Context<'brillig> {
451
451
}
452
452
}
453
453
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
+
454
479
// If the instruction doesn't have side-effects and if it won't interact with enable_side_effects during acir_gen,
455
480
// we cache the results so we can reuse them if the same instruction appears again later in the block.
456
481
// Others have side effects representing failure, which are implicit in the ACIR code and can also be deduplicated.
@@ -1521,4 +1546,49 @@ mod test {
1521
1546
let ssa = ssa. fold_constants_using_constraints ( ) ;
1522
1547
assert_normalized_ssa_equals ( ssa, expected) ;
1523
1548
}
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
+ }
1524
1594
}
0 commit comments