Bug: duplication of basic-blocks for test conditions of the form e1 && e2 (control-flow reconstruction issue)
This:
fn h(x: &str) {}
fn main() {
{
if true && true {
h("foo")
} else {
h("bar")
}
}
}
gets pretty-printed as:
// Full name: test3::h
fn h<'_0>(@1: &'_0 (Str))
{
let @0: (); // return
let x@1: &'_ (Str); // arg #1
@0 := ()
@0 := ()
return
}
// Full name: test3::main
fn main()
{
let @0: (); // return
let @1: bool; // anonymous local
let @2: bool; // anonymous local
let @3: &'_ (Str); // anonymous local
let @4: &'_ (Str); // anonymous local
let @5: &'_ (Str); // anonymous local
let @6: &'_ (Str); // anonymous local
storage_live(@3)
storage_live(@4)
storage_live(@5)
storage_live(@6)
storage_live(@1)
@1 := const (true)
if move (@1) {
storage_live(@2)
@2 := const (true)
if move (@2) {
storage_live(@3)
storage_live(@4)
@4 := const ("foo")
@3 := &*(@4)
@0 := h<'_>(move (@3))
storage_dead(@4)
storage_dead(@3)
}
else {
storage_live(@5)
storage_live(@6)
@6 := const ("bar")
@5 := &*(@6)
@0 := h<'_>(move (@5))
storage_dead(@6)
storage_dead(@5)
}
}
else {
storage_live(@5)
storage_live(@6)
@6 := const ("bar")
@5 := &*(@6)
@0 := h<'_>(move (@5))
storage_dead(@6)
storage_dead(@5)
}
storage_dead(@2)
storage_dead(@1)
@0 := ()
return
}
Notice how the const("bar") appears twice, meaning that the else-branch is duplicated. The desired outcome is for no such duplication to occur.
This is throwing Eurydice off the rails in a non-recoverable way. I'll elaborate once I file an issue on the Eurydice side.
Oh interesting, it seems the boolean condition just isn't computed and it's all done via control flow instead. That's not easy to reconstruct 🤔
Standard desugaring of lazy boolean operators to make sure the right hand side isn't eagerly evaluated?
if (e1 && e2) {
e3
} else {
e4
becomes
if (e1) {
if (e2) {
e3
} else {
e4
}
} else {
e4
}
I guess there could be a "peephole" optimization pattern for this that recognizes exactly this desugaring?
Yeah, I want to emit something like:
if e1 {
b = e2;
} else {
b = false;
}
if b {
e3
} else {
e4
}
We can probably recognize cases like this during control-flow reconstruction.
That would be perfect and I think would solve my use-case.