Skip to content
Merged
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
72 changes: 71 additions & 1 deletion compiler/noirc_evaluator/src/ssa/opt/die.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ impl RcTracker {
RcInstruction { id: instruction_id, array: *value, possibly_mutated: false };
self.rcs_with_possible_pairs.entry(typ).or_default().push(dec_rc);
}
Instruction::ArraySet { array, .. } => {
Instruction::ArraySet { array, value, .. } => {
let typ = function.dfg.type_of_value(*array);
// We mark all RCs that refer to arrays with a matching type as the one being set, as possibly mutated.
if let Some(dec_rcs) = self.rcs_with_possible_pairs.get_mut(&typ) {
Expand All @@ -768,6 +768,11 @@ impl RcTracker {
}
}
self.mutated_array_types.insert(typ);

let value_typ = function.dfg.type_of_value(*value);
if value_typ.is_array() {
self.mutated_array_types.insert(value_typ);
}
}
Instruction::Store { value, .. } => {
// We are very conservative and say that any store of an array type means it has the potential to be mutated.
Expand Down Expand Up @@ -1649,4 +1654,69 @@ mod test {
}
"#);
}

#[test]
fn do_not_remove_inc_rc_on_nested_constant_array() {
let src = "
brillig(inline) fn func_1 f0 {
b0(v0: [[Field; 1]; 1]):
v1 = allocate -> &mut [[Field; 1]; 1]
store v0 at v1
v3 = make_array [Field 2] : [Field; 1]
v4 = allocate -> &mut Field
store Field 0 at v4
jmp b1()
b1():
v6 = load v4 -> Field
v7 = eq v6, Field 2
jmpif v7 then: b2, else: b3
b2():
jmp b4()
b3():
v8 = load v4 -> Field
v10 = add v8, Field 1
store v10 at v4
v11 = allocate -> &mut Field
store Field 0 at v11
jmp b5()
b4():
v23 = load v1 -> [[Field; 1]; 1]
v24 = array_get v23, index u32 0 -> [Field; 1]
v25 = array_get v24, index u32 0 -> Field
return v25
b5():
v12 = load v11 -> Field
v13 = eq v12, Field 1
jmpif v13 then: b6, else: b7
b6():
jmp b8()
b7():
v14 = load v11 -> Field
v15 = add v14, Field 1
store v15 at v11
v16 = load v1 -> [[Field; 1]; 1]
v18 = array_get v16, index u32 0 -> [Field; 1]
v19 = array_set v18, index u32 0, value Field 1
v20 = array_set v16, index u32 0, value v19
store v20 at v1
jmp b9()
b8():
inc_rc v3
v21 = load v1 -> [[Field; 1]; 1]
v22 = array_set v21, index u32 0, value v3
store v22 at v1
jmp b10()
b9():
jmp b5()
b10():
jmp b1()
}
";
let ssa = Ssa::from_str(src).unwrap();
let ssa = ssa.dead_instruction_elimination();

// If `inc_rc v3` were removed, we risk it later being mutated in `v19 = array_set v18, index u32 0, value Field 1`.
// Thus, when we later go to do `v22 = array_set v21, index u32 0, value v3` once more, we will be writing [1] rather than [2].
assert_normalized_ssa_equals(ssa, src);
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading