|  | ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | 
|  | ; RUN: opt -passes=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 ptr @__gxx_personality_v0 { | 
|  | ; 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 { ptr, i32 } | 
|  | ; CHECK-NEXT:    cleanup | 
|  | ; CHECK-NEXT:    call void @foo() | 
|  | ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[RESUME0:%.*]], label [[RESUME1:%.*]] | 
|  | ; CHECK:       lpad2: | 
|  | ; CHECK-NEXT:    [[LP2:%.*]] = landingpad { ptr, i32 } | 
|  | ; CHECK-NEXT:    cleanup | 
|  | ; CHECK-NEXT:    call void @bar() | 
|  | ; CHECK-NEXT:    br label [[RESUME2:%.*]] | 
|  | ; CHECK:       lpad3: | 
|  | ; CHECK-NEXT:    [[LP3:%.*]] = landingpad { ptr, i32 } | 
|  | ; CHECK-NEXT:    cleanup | 
|  | ; CHECK-NEXT:    call void @baz() | 
|  | ; CHECK-NEXT:    br label [[RESUME2]] | 
|  | ; CHECK:       common.resume: | 
|  | ; CHECK-NEXT:    [[COMMON_RESUME_OP:%.*]] = phi { ptr, i32 } [ [[LP]], [[RESUME0]] ], [ [[LP]], [[RESUME1]] ], [ [[SEMICOMMON_LP:%.*]], [[RESUME2]] ] | 
|  | ; CHECK-NEXT:    call void @common() | 
|  | ; CHECK-NEXT:    resume { ptr, 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 { ptr, 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 { ptr, i32 } cleanup | 
|  | call void @foo() | 
|  | br i1 %cond, label %resume0, label %resume1 | 
|  |  | 
|  | lpad2: | 
|  | %lp2 = landingpad { ptr, i32 } cleanup | 
|  | call void @bar() | 
|  | br label %resume2 | 
|  |  | 
|  | lpad3: | 
|  | %lp3 = landingpad { ptr, i32 } cleanup | 
|  | call void @baz() | 
|  | br label %resume2 | 
|  |  | 
|  | resume0: | 
|  | call void @qux() | 
|  | call void @common() | 
|  | resume { ptr, i32 } %lp | 
|  |  | 
|  | resume1: | 
|  | call void @quux() | 
|  | call void @common() | 
|  | resume { ptr, i32 } %lp | 
|  |  | 
|  | resume2: | 
|  | %semicommon.lp = phi { ptr, i32 } [ %lp2, %lpad2 ], [ %lp3, %lpad3 ] | 
|  | call void @quuz() | 
|  | call void @common() | 
|  | resume { ptr, i32 } %semicommon.lp | 
|  | } | 
|  |  | 
|  | declare dso_local i32 @__gxx_personality_v0(...) |