tryWidenCondBranchToCondBranch is supposed to perform guard widening,
redirecting a deopting exit of successor block into a deopting exit of the
widenable predecessor block. But the check that the latter is actually deoptimizing
was never done. As result, the transform was turning
define i32 @test(float %arg) gc "statepoint-example" personality i32* ()* @blam { bb: %tmp = call i1 @llvm.experimental.widenable.condition() br i1 %tmp, label %bb2, label %bb1 bb1: ; preds = %bb br i1 undef, label %bb7, label %bb5 bb2: ; preds = %bb %tmp3 = getelementptr inbounds i8, i8 addrspace(1)* undef, i64 16 br i1 undef, label %bb7, label %bb4 bb4: ; preds = %bb2 call void @snork() [ "deopt"() ] unreachable bb5: ; preds = %bb1 ret i32 0 bb7: ; preds = %bb2, %bb1 %tmp8 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 10) [ "deopt"() ] ret i32 %tmp8 }
into
define i32 @test(float %arg) gc "statepoint-example" personality i32* ()* @blam { bb: %tmp = call i1 @llvm.experimental.widenable.condition() br i1 %tmp, label %bb2, label %bb1 bb1: ; preds = %bb2, %bb br i1 undef, label %bb7, label %bb5 bb2: ; preds = %bb %tmp3 = getelementptr inbounds i8, i8 addrspace(1)* undef, i64 16 br i1 undef, label %bb1, label %bb4 bb4: ; preds = %bb2 call void @snork() [ "deopt"() ] unreachable bb5: ; preds = %bb1 ret i32 0 bb7: ; preds = %bb1 %tmp8 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 10) [ "deopt"() ] ret i32 %tmp8 }
Note that this is just wrong: previously taking branch bb2->bb7 was always a deopt,
but then it was replaced with bb2->bb1 and then it could go to bb5 which was not
even reachable from bb2 before the transform. (In this test conditions are undef, but
in fact they are never analyzed so it doesn't matter; condition in bb2 could as well be
a regular value).
So in fact, this transform may replace a deopting edge with some random edge which
never deopts. It's a miscompile by itself, and in case of SimplifyCFG, it has weird interactions
with other transforms of SimplifyCondBranchToCondBranch, which create a .pr Phi, then
thread through it, and then the described buggy transform repeats and brings the code into
its initial state. So we end up stuck in an infinite loop.
This patch fixes this situation by ensuring that widenable condition branch actually goes to
deopt if the condition is false.