; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S < %s | FileCheck %s ; Test that we tail merge resume blocks and phi operands properly. declare void @maybe_throws() declare void @foo() declare void @bar() declare void @baz() declare void @qux() declare void @quux() declare void @quuz() declare void @common() define void @merge_simple(i1 %cond) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; CHECK-LABEL: @merge_simple( ; CHECK-NEXT: invoke void @maybe_throws() ; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] ; CHECK: invoke.cont: ; CHECK-NEXT: invoke void @maybe_throws() ; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD2:%.*]] ; CHECK: invoke.cont2: ; CHECK-NEXT: invoke void @maybe_throws() ; CHECK-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD3:%.*]] ; CHECK: invoke.cont3: ; CHECK-NEXT: ret void ; CHECK: lpad: ; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup ; CHECK-NEXT: call void @foo() ; CHECK-NEXT: br i1 [[COND:%.*]], label [[RESUME0:%.*]], label [[RESUME1:%.*]] ; CHECK: lpad2: ; CHECK-NEXT: [[LP2:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup ; CHECK-NEXT: call void @bar() ; CHECK-NEXT: br label [[RESUME2:%.*]] ; CHECK: lpad3: ; CHECK-NEXT: [[LP3:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: cleanup ; CHECK-NEXT: call void @baz() ; CHECK-NEXT: br label [[RESUME2]] ; CHECK: common.resume: ; CHECK-NEXT: [[COMMON_RESUME_OP:%.*]] = phi { i8*, i32 } [ [[LP]], [[RESUME0]] ], [ [[LP]], [[RESUME1]] ], [ [[SEMICOMMON_LP:%.*]], [[RESUME2]] ] ; CHECK-NEXT: call void @common() ; CHECK-NEXT: resume { i8*, i32 } [[COMMON_RESUME_OP]] ; CHECK: resume0: ; CHECK-NEXT: call void @qux() ; CHECK-NEXT: br label [[COMMON_RESUME:%.*]] ; CHECK: resume1: ; CHECK-NEXT: call void @quux() ; CHECK-NEXT: br label [[COMMON_RESUME]] ; CHECK: resume2: ; CHECK-NEXT: [[SEMICOMMON_LP]] = phi { i8*, i32 } [ [[LP2]], [[LPAD2]] ], [ [[LP3]], [[LPAD3]] ] ; CHECK-NEXT: call void @quuz() ; CHECK-NEXT: br label [[COMMON_RESUME]] ; invoke void @maybe_throws() to label %invoke.cont unwind label %lpad invoke.cont: invoke void @maybe_throws() to label %invoke.cont2 unwind label %lpad2 invoke.cont2: invoke void @maybe_throws() to label %invoke.cont3 unwind label %lpad3 invoke.cont3: ret void lpad: %lp = landingpad { i8*, i32 } cleanup call void @foo() br i1 %cond, label %resume0, label %resume1 lpad2: %lp2 = landingpad { i8*, i32 } cleanup call void @bar() br label %resume2 lpad3: %lp3 = landingpad { i8*, i32 } cleanup call void @baz() br label %resume2 resume0: call void @qux() call void @common() resume { i8*, i32 } %lp resume1: call void @quux() call void @common() resume { i8*, i32 } %lp resume2: %semicommon.lp = phi { i8*, i32 } [ %lp2, %lpad2 ], [ %lp3, %lpad3 ] call void @quuz() call void @common() resume { i8*, i32 } %semicommon.lp } declare dso_local i32 @__gxx_personality_v0(...)