The following code:
unconstrained fn foo(cond: bool) -> bool {
let mut b = false;
let c = if cond { &mut b } else { &mut false };
b = !b;
b = *c;
b
}
fn main() -> pub bool {
let expected = comptime { unsafe { foo(true) } };
let result = unsafe { foo(true) };
assert(result == expected);
unsafe { foo(true) }
}
fails with the assertion: comptime correctly returns true while Brillig returns false.
The issue seems to be within mem2reg_simple. It sees the following SSA:
b3(v1: &mut u1): // v1 = c (either v2 or a fresh alloc)
v5 = load v2 -> u1 // load b
v6 = not v5 // !b
store v6 at v2 // b = !b (store 1)
v7 = load v1 -> u1 // *c
store v7 at v2 // b = *c (store 2)
return v7
and removes store 1 thinking it's dead, because the load in between them mentions v1 not v2. But v1 and v2 are actually the same pointer here when cond is true.
Seems to have been introduced in #11935
The following code:
fails with the assertion: comptime correctly returns
truewhile Brillig returnsfalse.The issue seems to be within mem2reg_simple. It sees the following SSA:
and removes store 1 thinking it's dead, because the load in between them mentions v1 not v2. But v1 and v2 are actually the same pointer here when cond is true.
Seems to have been introduced in #11935