Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,11 @@ if.end:
}

; shared normal destination is not unreachable.
define void @t3_bad_shared_normal_dest() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t3_bad_shared_normal_dest(
define void @t3_shared_identical_normal_dest() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t3_shared_identical_normal_dest(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
Expand All @@ -167,10 +164,10 @@ define void @t3_bad_shared_normal_dest() personality i8* bitcast (i32 (...)* @__
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
Expand Down Expand Up @@ -203,7 +200,7 @@ if.end:
ret void
}

; normal destinations are not unreachable and not shared.
; normal destinations are not unreachable and not shared and can not be merged.
define void @t4_normal_dests() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t4_normal_dests(
; CHECK-NEXT: entry:
Expand Down Expand Up @@ -1570,12 +1567,9 @@ define void @t26_phi_in_normal_dest_compatible_incoming_values() personality i8*
; CHECK-LABEL: @t26_phi_in_normal_dest_compatible_incoming_values(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE0:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE0:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[IF_THEN0]] ], [ 0, [[IF_THEN1:%.*]] ], [ -1, [[IF_THEN2:%.*]] ]
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[IF_THEN2:%.*]] ], [ 0, [[IF_THEN1_INVOKE]] ]
; CHECK-NEXT: call void @consume(i32 [[PHI]])
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
Expand All @@ -1586,10 +1580,10 @@ define void @t26_phi_in_normal_dest_compatible_incoming_values() personality i8*
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else0:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1]], label [[IF_ELSE1:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_ELSE1:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.else1:
; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C2]], label [[IF_THEN2]], label [[IF_END:%.*]]
Expand Down Expand Up @@ -1642,10 +1636,7 @@ define void @t27_invoke_ret_value_is_used() personality i8* bitcast (i32 (...)*
; CHECK-LABEL: @t27_invoke_ret_value_is_used(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
Expand All @@ -1656,10 +1647,10 @@ define void @t27_invoke_ret_value_is_used() personality i8* bitcast (i32 (...)*
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: [[V1:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: [[TMP0:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
Expand Down Expand Up @@ -1697,13 +1688,9 @@ define void @t28_invoke_ret_value_is_used_in_phi_node() personality i8* bitcast
; CHECK-LABEL: @t28_invoke_ret_value_is_used_in_phi_node(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[V0]], [[IF_THEN0]] ], [ [[V1:%.*]], [[IF_THEN1:%.*]] ]
; CHECK-NEXT: call void @consume(i32 [[PHI]])
; CHECK-NEXT: call void @consume(i32 [[TMP0:%.*]])
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: lpad:
Expand All @@ -1713,10 +1700,10 @@ define void @t28_invoke_ret_value_is_used_in_phi_node() personality i8* bitcast
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: [[V1]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: [[TMP0]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
Expand Down Expand Up @@ -1756,10 +1743,7 @@ define void @t29_common_normal_destination_and_unreachable_normal_destination()
; CHECK-LABEL: @t29_common_normal_destination_and_unreachable_normal_destination(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE0:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE0:%.*]]
; CHECK: invoke.cont0:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
Expand All @@ -1770,10 +1754,10 @@ define void @t29_common_normal_destination_and_unreachable_normal_destination()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else0:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_ELSE1:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_ELSE1:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT0]] unwind label [[LPAD]]
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.else1:
; CHECK-NEXT: [[C2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C2]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]]
Expand Down Expand Up @@ -1824,6 +1808,308 @@ if.end:
ret void
}

; normal destinations are not unreachable and different but could be merged
define void @t30_completely_different_normal_dests() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t30_completely_different_normal_dests(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT0:%.*]] unwind label [[LPAD:%.*]]
; CHECK: invoke.cont0:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: lpad:
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: call void @destructor()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
; CHECK: invoke.cont2:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
;
entry:
%c0 = call i1 @cond()
br i1 %c0, label %if.then0, label %if.else

if.then0:
invoke void @maybe_throw() to label %invoke.cont0 unwind label %lpad

invoke.cont0:
call void @sideeffect()
unreachable

lpad:
%eh = landingpad { i8*, i32 } cleanup
call void @destructor()
resume { i8*, i32 } %eh

if.else:
%c1 = call i1 @cond()
br i1 %c1, label %if.then1, label %if.end

if.then1:
invoke void @maybe_throw() to label %invoke.cont2 unwind label %lpad

invoke.cont2:
call void @sideeffect()
unreachable

if.end:
call void @sideeffect()
ret void
}

; Even though the normal destinations are unreachable,
; they may have (dead) PHI nodes with incompatible incoming values,
; so we must cleanup them.
define void @t31_incompatible_dead_phi_in_normal_dest() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t31_incompatible_dead_phi_in_normal_dest(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
; CHECK: lpad:
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: call void @destructor()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: invoke void @maybe_throw()
; CHECK-NEXT: to label [[IF_THEN1_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.then1.cont:
; CHECK-NEXT: unreachable
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
;
entry:
%c0 = call i1 @cond()
br i1 %c0, label %if.then0, label %if.else

if.then0:
invoke void @maybe_throw() to label %invoke.cont unwind label %lpad

lpad:
%eh = landingpad { i8*, i32 } cleanup
call void @destructor()
resume { i8*, i32 } %eh

if.else:
%c1 = call i1 @cond()
br i1 %c1, label %if.then1, label %if.end

if.then1:
invoke void @maybe_throw() to label %invoke.cont unwind label %lpad

invoke.cont:
%deadphi0 = phi i32 [ 0, %if.then0 ], [ -1, %if.then1 ]
unreachable

if.end:
call void @sideeffect()
ret void
}

; Invokes return values, and they are used in a phi node, making the incoming values incompatible,
; second phi has compatible incoming values
define void @t32_invoke_ret_value_is_used_in_phi_node_other_phi_is_fine() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t32_invoke_ret_value_is_used_in_phi_node_other_phi_is_fine(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN1_INVOKE:%.*]], label [[IF_ELSE:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: call void @consume(i32 [[TMP0:%.*]])
; CHECK-NEXT: call void @consume(i32 0)
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: lpad:
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: call void @destructor()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1_INVOKE]], label [[IF_END:%.*]]
; CHECK: if.then1.invoke:
; CHECK-NEXT: [[TMP0]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
;
entry:
%c0 = call i1 @cond()
br i1 %c0, label %if.then0, label %if.else

if.then0:
%v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

invoke.cont:
%phi0 = phi i32 [ %v0, %if.then0 ], [ %v1, %if.then1 ]
%phi1 = phi i32 [ 0, %if.then0 ], [ 0, %if.then1 ]
call void @consume(i32 %phi0)
call void @consume(i32 %phi1)
call void @sideeffect()
unreachable

lpad:
%eh = landingpad { i8*, i32 } cleanup
call void @destructor()
resume { i8*, i32 } %eh

if.else:
%c1 = call i1 @cond()
br i1 %c1, label %if.then1, label %if.end

if.then1:
%v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

if.end:
call void @sideeffect()
ret void
}

; Invokes return values, and they are used in a phi node, making the incoming values incompatible,
; second phi has incompatible incoming values.
define void @t33_invoke_ret_value_is_used_in_phi_node_other_phi_is_bad() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t33_invoke_ret_value_is_used_in_phi_node_other_phi_is_bad(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: [[PHI0:%.*]] = phi i32 [ [[V0]], [[IF_THEN0]] ], [ [[V1:%.*]], [[IF_THEN1:%.*]] ]
; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 0, [[IF_THEN0]] ], [ -1, [[IF_THEN1]] ]
; CHECK-NEXT: call void @consume(i32 [[PHI0]])
; CHECK-NEXT: call void @consume(i32 [[PHI1]])
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: lpad:
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: call void @destructor()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: [[V1]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
;
entry:
%c0 = call i1 @cond()
br i1 %c0, label %if.then0, label %if.else

if.then0:
%v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

invoke.cont:
%phi0 = phi i32 [ %v0, %if.then0 ], [ %v1, %if.then1 ]
%phi1 = phi i32 [ 0, %if.then0 ], [ -1, %if.then1 ]
call void @consume(i32 %phi0)
call void @consume(i32 %phi1)
call void @sideeffect()
unreachable

lpad:
%eh = landingpad { i8*, i32 } cleanup
call void @destructor()
resume { i8*, i32 } %eh

if.else:
%c1 = call i1 @cond()
br i1 %c1, label %if.then1, label %if.end

if.then1:
%v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

if.end:
call void @sideeffect()
ret void
}

; Invokes return values, and they are used in a phi node, but when coming from different invokes,
; the incoming value isn't always the invoke, which is not okay.
define void @t34_invoke_ret_value_maybe_incompatibly_used_in_phi_node() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: @t34_invoke_ret_value_maybe_incompatibly_used_in_phi_node(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C0:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C0]], label [[IF_THEN0:%.*]], label [[IF_ELSE:%.*]]
; CHECK: if.then0:
; CHECK-NEXT: [[V0:%.*]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
; CHECK: invoke.cont:
; CHECK-NEXT: [[PHI0:%.*]] = phi i32 [ [[V0]], [[IF_THEN0]] ], [ 0, [[IF_THEN1:%.*]] ]
; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ 0, [[IF_THEN0]] ], [ [[V1:%.*]], [[IF_THEN1]] ]
; CHECK-NEXT: call void @consume(i32 [[PHI0]])
; CHECK-NEXT: call void @consume(i32 [[PHI1]])
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: unreachable
; CHECK: lpad:
; CHECK-NEXT: [[EH:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: call void @destructor()
; CHECK-NEXT: resume { i8*, i32 } [[EH]]
; CHECK: if.else:
; CHECK-NEXT: [[C1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C1]], label [[IF_THEN1]], label [[IF_END:%.*]]
; CHECK: if.then1:
; CHECK-NEXT: [[V1]] = invoke i32 @returning_maybe_throw()
; CHECK-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD]]
; CHECK: if.end:
; CHECK-NEXT: call void @sideeffect()
; CHECK-NEXT: ret void
;
entry:
%c0 = call i1 @cond()
br i1 %c0, label %if.then0, label %if.else

if.then0:
%v0 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

invoke.cont:
%phi0 = phi i32 [ %v0, %if.then0 ], [ 0, %if.then1 ]
%phi1 = phi i32 [ 0, %if.then0 ], [ %v1, %if.then1 ]
call void @consume(i32 %phi0)
call void @consume(i32 %phi1)
call void @sideeffect()
unreachable

lpad:
%eh = landingpad { i8*, i32 } cleanup
call void @destructor()
resume { i8*, i32 } %eh

if.else:
%c1 = call i1 @cond()
br i1 %c1, label %if.then1, label %if.end

if.then1:
%v1 = invoke i32 @returning_maybe_throw() to label %invoke.cont unwind label %lpad

if.end:
call void @sideeffect()
ret void
}

declare i1 @cond()

declare void @sideeffect()
Expand Down