diff options
Diffstat (limited to 'llvm/test/CodeGen/WinEH')
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-cloning.ll | 398 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-coreclr.ll | 277 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-demotion.ll | 121 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll | 28 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-intrinsics.ll | 14 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll | 1548 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-no-demotion.ll | 78 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll | 68 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WinEH/wineh-statenumbering.ll | 31 |
9 files changed, 226 insertions, 2337 deletions
diff --git a/llvm/test/CodeGen/WinEH/wineh-cloning.ll b/llvm/test/CodeGen/WinEH/wineh-cloning.ll index 7d6529d6009..66a9132980f 100644 --- a/llvm/test/CodeGen/WinEH/wineh-cloning.ll +++ b/llvm/test/CodeGen/WinEH/wineh-cloning.ll @@ -1,6 +1,7 @@ -; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s +; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s declare i32 @__CxxFrameHandler3(...) +declare i32 @__C_specific_handler(...) declare void @f() declare i32 @g() @@ -13,16 +14,16 @@ entry: ; %x def colors: {entry} subset of use colors; must spill %x = call i32 @g() invoke void @f() - to label %noreturn unwind label %catch + to label %noreturn unwind label %catch.switch +catch.switch: + %cs = catchswitch within none [label %catch] unwind to caller catch: - catchpad [] - to label %noreturn unwind label %endcatch + catchpad within %cs [] + br label %noreturn noreturn: ; %x use colors: {entry, cleanup} call void @h(i32 %x) unreachable -endcatch: - catchendpad unwind to caller } ; Need two copies of the call to @h, one under entry and one under catch. ; Currently we generate a load for each, though we shouldn't need one @@ -32,11 +33,11 @@ endcatch: ; CHECK: %x = call i32 @g() ; CHECK: invoke void @f() ; CHECK: to label %[[EntryCopy:[^ ]+]] unwind label %catch +; CHECK: catch.switch: +; CHECK: %cs = catchswitch within none [label %catch] unwind to caller ; CHECK: catch: -; CHECK: catchpad [] -; CHECK-NEXT: to label %[[CatchCopy:[^ ]+]] unwind -; CHECK: [[CatchCopy]]: -; CHECK: call void @h(i32 %x) +; CHECK: catchpad within %cs [] +; CHECK-NEXT: call void @h(i32 %x) ; CHECK: [[EntryCopy]]: ; CHECK: call void @h(i32 %x) @@ -46,7 +47,7 @@ entry: invoke void @f() to label %exit unwind label %cleanup cleanup: - cleanuppad [] + cleanuppad within none [] br label %exit exit: call void @f() @@ -60,7 +61,7 @@ exit: ; CHECK: invoke void @f() ; CHECK: to label %[[exit:[^ ]+]] unwind label %cleanup ; CHECK: cleanup: -; CHECK: cleanuppad [] +; CHECK: cleanuppad within none [] ; CHECK: call void @f() ; CHECK-NEXT: unreachable ; CHECK: [[exit]]: @@ -71,16 +72,17 @@ exit: define void @test3() personality i32 (...)* @__CxxFrameHandler3 { entry: invoke void @f() - to label %invoke.cont unwind label %catch + to label %invoke.cont unwind label %catch.switch invoke.cont: invoke void @f() to label %exit unwind label %cleanup +catch.switch: + %cs = catchswitch within none [label %catch] unwind to caller catch: - catchpad [] to label %shared unwind label %endcatch -endcatch: - catchendpad unwind to caller + catchpad within %cs [] + br label %shared cleanup: - cleanuppad [] + cleanuppad within none [] br label %shared shared: call void @f() @@ -95,13 +97,11 @@ exit: ; CHECK: invoke void @f() ; CHECK: to label %[[exit:[^ ]+]] unwind ; CHECK: catch: -; CHECK: catchpad [] -; CHECK-NEXT: to label %[[shared:[^ ]+]] unwind -; CHECK: cleanup: -; CHECK: cleanuppad [] -; CHECK: call void @f() +; CHECK: catchpad within %cs [] +; CHECK-NEXT: call void @f() ; CHECK-NEXT: unreachable -; CHECK: [[shared]]: +; CHECK: cleanup: +; CHECK: cleanuppad within none [] ; CHECK: call void @f() ; CHECK-NEXT: unreachable ; CHECK: [[exit]]: @@ -111,12 +111,12 @@ exit: define void @test4() personality i32 (...)* @__CxxFrameHandler3 { entry: invoke void @f() - to label %shared unwind label %catch + to label %shared unwind label %catch.switch +catch.switch: + %cs = catchswitch within none [label %catch] unwind to caller catch: - catchpad [] - to label %shared unwind label %endcatch -endcatch: - catchendpad unwind to caller + catchpad within %cs [] + br label %shared shared: %x = call i32 @g() %i = call i32 @g() @@ -145,10 +145,9 @@ exit: ; from %shared to %exit. ; CHECK-LABEL: define void @test4( ; CHECK: entry: -; CHECK: to label %[[shared_E:[^ ]+]] unwind label %catch +; CHECK: to label %[[shared_E:[^ ]+]] unwind label %catch.switch ; CHECK: catch: -; CHECK: to label %[[shared_C:[^ ]+]] unwind label %endcatch -; CHECK: [[shared_C]]: +; CHECK: catchpad within %cs [] ; CHECK: [[x_C:%[^ ]+]] = call i32 @g() ; CHECK: [[i_C:%[^ ]+]] = call i32 @g() ; CHECK: [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0 @@ -159,7 +158,7 @@ exit: ; CHECK: [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0 ; CHECK: br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]] ; CHECK: [[loop_C]]: -; CHECK: [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %[[shared_C]] ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ] +; CHECK: [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ] ; CHECK: [[b_C:%[^ ]+]] = call i1 @b() ; CHECK: br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]] ; CHECK: [[loop_E]]: @@ -194,27 +193,25 @@ exit: ; CHECK: unreachable -define void @test5() personality i32 (...)* @__CxxFrameHandler3 { +define void @test5() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %exit unwind label %outer outer: - %o = cleanuppad [] + %o = cleanuppad within none [] %x = call i32 @g() invoke void @f() - to label %outer.ret unwind label %inner + to label %outer.ret unwind label %catch.switch +catch.switch: + %cs = catchswitch within %o [label %inner] unwind to caller inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.endcatch -inner.catch: - catchret %i to label %outer.post-inner -inner.endcatch: - catchendpad unwind to caller + %i = catchpad within %cs [] + catchret from %i to label %outer.post-inner outer.post-inner: call void @h(i32 %x) br label %outer.ret outer.ret: - cleanupret %o unwind to caller + cleanupret from %o unwind to caller exit: ret void } @@ -225,17 +222,16 @@ exit: ; CHECK: outer: ; CHECK: %x = call i32 @g() ; CHECK-NEXT: invoke void @f() -; CHECK-NEXT: to label %outer.ret unwind label %inner +; CHECK-NEXT: to label %outer.ret unwind label %catch.switch ; CHECK: inner: -; CHECK: to label %inner.catch unwind label %inner.endcatch -; CHECK: inner.catch: -; CHECK-NEXT: catchret %i to label %outer.post-inner +; CHECK-NEXT: %i = catchpad within %cs [] +; CHECK-NEXT: catchret from %i to label %outer.post-inner ; CHECK: outer.post-inner: ; CHECK-NEXT: call void @h(i32 %x) ; CHECK-NEXT: br label %outer.ret -define void @test6() personality i32 (...)* @__CxxFrameHandler3 { +define void @test6() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %invoke.cont unwind label %left @@ -243,15 +239,13 @@ invoke.cont: invoke void @f() to label %exit unwind label %right left: - cleanuppad [] + cleanuppad within none [] br label %shared right: - catchpad [] - to label %right.catch unwind label %right.end + %cs = catchswitch within none [label %right.catch] unwind to caller right.catch: + catchpad within %cs [] br label %shared -right.end: - catchendpad unwind to caller shared: %x = call i32 @g() invoke void @f() @@ -259,109 +253,32 @@ shared: shared.cont: unreachable inner: - %i = cleanuppad [] + %i = cleanuppad within none [] call void @h(i32 %x) - cleanupret %i unwind label %right.end + cleanupret from %i unwind to caller exit: ret void } -; %inner is a cleanup which appears both as a child of -; %left and as a child of %right. Since statically we -; need each funclet to have a single parent, we need to -; clone the entire %inner funclet so we can have one -; copy under each parent. The cleanupret in %inner -; unwinds to the catchendpad for %right, so the copy -; of %inner under %right should include it; the copy -; of %inner under %left should instead have an -; `unreachable` inserted there, but the copy under -; %left still needs to be created because it's possible -; the dynamic path enters %left, then enters %inner, -; then calls @h, and that the call to @h doesn't return. ; CHECK-LABEL: define void @test6( ; CHECK: left: ; CHECK: %x.for.left = call i32 @g() ; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: catchpad -; CHECK: to label %right.catch unwind label %right.end +; CHECK: to label %shared.cont.for.left unwind label %inner ; CHECK: right.catch: +; CHECK: catchpad ; CHECK: %x = call i32 @g() -; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller +; CHECK: to label %shared.cont unwind label %inner ; CHECK: shared.cont: ; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 %x) -; CHECK: cleanupret [[I_R]] unwind label %right.end -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable - - -define void @test7() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %unreachable unwind label %right -left: - cleanuppad [] - invoke void @f() to label %unreachable unwind label %inner -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - invoke void @f() to label %unreachable unwind label %inner -right.end: - catchendpad unwind to caller -inner: - %i = cleanuppad [] - %x = call i32 @g() - call void @h(i32 %x) - cleanupret %i unwind label %right.end -unreachable: - unreachable -} -; Another case of a two-parent child (like @test6), this time -; with the join at the entry itself instead of following a -; non-pad join. -; CHECK-LABEL: define void @test7( -; CHECK: invoke.cont: -; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right -; CHECK: left: -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: to label %unreachable unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: [[X_R:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X_R]]) -; CHECK: cleanupret [[I_R]] unwind label %right.end -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: [[X_L:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X_L]]) -; CHECK: unreachable -; CHECK: unreachable: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_ENTRY]]: +; CHECK: shared.cont.for.left: ; CHECK: unreachable +; CHECK: inner: +; CHECK: %i = cleanuppad within none [] +; CHECK: call void @h(i32 %x1.wineh.reload) +; CHECK: cleanupret from %i unwind to caller -define void @test8() personality i32 (...)* @__CxxFrameHandler3 { +define void @test9() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %invoke.cont unwind label %left @@ -369,119 +286,32 @@ invoke.cont: invoke void @f() to label %unreachable unwind label %right left: - cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -inner: - cleanuppad [] - invoke void @f() - to label %unreachable unwind label %inner.child -inner.child: - cleanuppad [] - %x = call i32 @g() - call void @h(i32 %x) - unreachable -unreachable: - unreachable -} -; %inner is a two-parent child which itself has a child; need -; to make two copies of both the %inner and %inner.child. -; CHECK-LABEL: define void @test8( -; CHECK: invoke.cont: -; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right -; CHECK: left: -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_RIGHT]]: -; CHECK: to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]] -; CHECK: [[INNER_CHILD_RIGHT]]: -; CHECK: [[TMP:\%.+]] = cleanuppad [] -; CHECK: [[X:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X]]) -; CHECK: unreachable -; CHECK: [[INNER_CHILD_LEFT]]: -; CHECK: [[TMP:\%.+]] = cleanuppad [] -; CHECK: [[X:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X]]) -; CHECK: unreachable -; CHECK: [[UNREACHABLE_INNER_RIGHT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_INNER_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_RIGHT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_ENTRY]]: -; CHECK: unreachable - - -define void @test9() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %unreachable unwind label %right -left: - cleanuppad [] + cleanuppad within none [] call void @h(i32 1) invoke void @f() to label %unreachable unwind label %right right: - cleanuppad [] + cleanuppad within none [] call void @h(i32 2) invoke void @f() to label %unreachable unwind label %left unreachable: unreachable } -; This is an irreducible loop with two funclets that enter each other; -; need to make two copies of each funclet (one a child of root, the -; other a child of the opposite funclet), but also make sure not to -; clone self-descendants (if we tried to do that we'd need to make an -; infinite number of them). Presumably if optimizations ever generated -; such a thing it would mean that one of the two cleanups was originally -; the parent of the other, but that we'd somehow lost track in the CFG -; of which was which along the way; generating each possibility lets -; whichever case was correct execute correctly. +; This is an irreducible loop with two funclets that enter each other. ; CHECK-LABEL: define void @test9( ; CHECK: entry: ; CHECK: to label %invoke.cont unwind label %[[LEFT:.+]] ; CHECK: invoke.cont: ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]] -; CHECK: [[LEFT_FROM_RIGHT:.+]]: -; CHECK: call void @h(i32 1) -; CHECK: call void @f() -; CHECK: unreachable ; CHECK: [[LEFT]]: ; CHECK: call void @h(i32 1) ; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]] +; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]] ; CHECK: [[RIGHT]]: ; CHECK: call void @h(i32 2) ; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]] -; CHECK: [[RIGHT_FROM_LEFT]]: -; CHECK: call void @h(i32 2) -; CHECK: call void @f() -; CHECK: unreachable +; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]] ; CHECK: [[UNREACHABLE_RIGHT]]: ; CHECK: unreachable ; CHECK: [[UNREACHABLE_LEFT]]: @@ -495,16 +325,16 @@ entry: invoke void @f() to label %unreachable unwind label %inner inner: - %cleanup = cleanuppad [] + %cleanup = cleanuppad within none [] ; make sure we don't overlook this cleanupret and try to process ; successor %outer as a child of inner. - cleanupret %cleanup unwind label %outer + cleanupret from %cleanup unwind label %outer outer: - %catch = catchpad [] to label %catch.body unwind label %endpad + %cs = catchswitch within none [label %catch.body] unwind to caller + catch.body: - catchret %catch to label %exit -endpad: - catchendpad unwind to caller + %catch = catchpad within %cs [] + catchret from %catch to label %exit exit: ret void unreachable: @@ -515,46 +345,40 @@ unreachable: ; CHECK-NEXT: invoke ; CHECK-NEXT: to label %unreachable unwind label %inner ; CHECK: inner: -; CHECK-NEXT: %cleanup = cleanuppad -; CHECK-NEXT: cleanupret %cleanup unwind label %outer +; CHECK-NEXT: %cleanup = cleanuppad within none [] +; CHECK-NEXT: cleanupret from %cleanup unwind label %outer ; CHECK: outer: -; CHECK-NEXT: %catch = catchpad [] -; CHECK-NEXT: to label %catch.body unwind label %endpad +; CHECK-NEXT: %cs = catchswitch within none [label %catch.body] unwind to caller ; CHECK: catch.body: -; CHECK-NEXT: catchret %catch to label %exit -; CHECK: endpad: -; CHECK-NEXT: catchendpad unwind to caller +; CHECK-NEXT: %catch = catchpad within %cs [] +; CHECK-NEXT: catchret from %catch to label %exit ; CHECK: exit: ; CHECK-NEXT: ret void -define void @test11() personality i32 (...)* @__CxxFrameHandler3 { +define void @test11() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %exit unwind label %cleanup.outer cleanup.outer: - %outer = cleanuppad [] + %outer = cleanuppad within none [] invoke void @f() to label %outer.cont unwind label %cleanup.inner outer.cont: br label %merge cleanup.inner: - %inner = cleanuppad [] + %inner = cleanuppad within %outer [] br label %merge merge: - invoke void @f() - to label %unreachable unwind label %merge.end -unreachable: + call void @f() unreachable -merge.end: - cleanupendpad %outer unwind to caller exit: ret void } ; merge.end will get cloned for outer and inner, but is implausible -; from inner, so the invoke @f() in inner's copy of merge should be +; from inner, so the call @f() in inner's copy of merge should be ; rewritten to call @f() ; CHECK-LABEL: define void @test11() -; CHECK: %inner = cleanuppad [] +; CHECK: %inner = cleanuppad within %outer [] ; CHECK-NEXT: call void @f() ; CHECK-NEXT: unreachable @@ -566,10 +390,10 @@ cont: invoke void @f() to label %exit unwind label %right left: - cleanuppad [] + cleanuppad within none [] br label %join right: - cleanuppad [] + cleanuppad within none [] br label %join join: ; This call will get cloned; make sure we can handle cloning @@ -587,68 +411,10 @@ entry: ret void unreachable: - cleanuppad [] + cleanuppad within none [] unreachable } -define void @test14() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %catch1.pad -catch1.pad: - %catch1 = catchpad [i32 1] - to label %catch1.body unwind label %catch2.pad -catch1.body: - invoke void @h(i32 1) - to label %catch1.body2 unwind label %catch.end -catch1.body2: - invoke void @f() - to label %catch1.ret unwind label %cleanup1.pad -cleanup1.pad: - %cleanup1 = cleanuppad [] - call void @f() - cleanupret %cleanup1 unwind label %catch.end -catch1.ret: - catchret %catch1 to label %exit -catch2.pad: - %catch2 = catchpad [i32 2] - to label %catch2.body unwind label %catch.end -catch2.body: - invoke void @h(i32 2) - to label %catch2.body2 unwind label %catch.end -catch2.body2: - invoke void @f() - to label %catch2.ret unwind label %cleanup2.pad -cleanup2.pad: - %cleanup2 = cleanuppad [] - call void @f() - cleanupret %cleanup2 unwind label %catch.end -catch2.ret: - catchret %catch2 to label %exit -catch.end: - catchendpad unwind to caller -exit: - ret void -} -; Make sure we don't clone the catchendpad even though the -; cleanupendpads targeting it would naively imply that it -; should get their respective parent colors (catch1 and catch2), -; as well as its properly getting the root function color. The -; references from the invokes ensure that if we did make clones -; for each catch, they'd be reachable, as those invokes would get -; rewritten -; CHECK-LABEL: define void @test14() -; CHECK-NOT: catchendpad -; CHECK: invoke void @h(i32 1) -; CHECK-NEXT: unwind label %catch.end -; CHECK-NOT: catchendpad -; CHECK: invoke void @h(i32 2) -; CHECK-NEXT: unwind label %catch.end -; CHECK-NOT: catchendpad -; CHECK: catch.end: -; CHECK-NEXT: catchendpad -; CHECK-NOT: catchendpad - ;; Debug info (from test12) ; Make sure the DISubprogram doesn't get cloned diff --git a/llvm/test/CodeGen/WinEH/wineh-coreclr.ll b/llvm/test/CodeGen/WinEH/wineh-coreclr.ll deleted file mode 100644 index 079993f74db..00000000000 --- a/llvm/test/CodeGen/WinEH/wineh-coreclr.ll +++ /dev/null @@ -1,277 +0,0 @@ -; RUN: llc -mtriple=x86_64-pc-windows-coreclr -verify-machineinstrs < %s | FileCheck %s - -declare void @ProcessCLRException() -declare void @f(i32) -declare void @g(i8 addrspace(1)*) -declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token) - -; Simplified IR for pseudo-C# like the following: -; void test1() { -; try { -; f(1); -; try { -; f(2); -; } catch (type1) { -; f(3); -; } catch (type2) [ -; f(4); -; try { -; f(5); -; } fault { -; f(6); -; } -; } -; } finally { -; f(7); -; } -; f(8); -; } - -; CHECK-LABEL: test1: # @test1 -; CHECK-NEXT: [[L_begin:.*func_begin.*]]: -define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) { -entry: -; CHECK: # %entry -; CHECK: leaq [[FPOffset:[0-9]+]](%rsp), %rbp -; CHECK: .seh_endprologue -; CHECK: movq %rsp, [[PSPSymOffset:[0-9]+]](%rsp) -; CHECK: [[L_before_f1:.+]]: -; CHECK-NEXT: movl $1, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f1:.+]]: - invoke void @f(i32 1) - to label %inner_try unwind label %finally.pad -inner_try: -; CHECK: # %inner_try -; CHECK: [[L_before_f2:.+]]: -; CHECK-NEXT: movl $2, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f2:.+]]: - invoke void @f(i32 2) - to label %finally.clone unwind label %catch1.pad -catch1.pad: -; CHECK: .seh_proc [[L_catch1:[^ ]+]] - %catch1 = catchpad [i32 1] - to label %catch1.body unwind label %catch2.pad -catch1.body: -; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]] -; ^ all funclets use the same frame size -; CHECK: movq [[PSPSymOffset]](%rcx), %rcx -; ^ establisher frame pointer passed in rcx -; CHECK: movq %rcx, [[PSPSymOffset]](%rsp) -; CHECK: leaq [[FPOffset]](%rcx), %rbp -; CHECK: .seh_endprologue -; CHECK: movq %rdx, %rcx -; ^ exception pointer passed in rdx -; CHECK-NEXT: callq g - %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1) - call void @g(i8 addrspace(1)* %exn1) -; CHECK: [[L_before_f3:.+]]: -; CHECK-NEXT: movl $3, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f3:.+]]: - invoke void @f(i32 3) - to label %catch1.ret unwind label %catch.end -catch1.ret: - catchret %catch1 to label %finally.clone -catch2.pad: -; CHECK: .seh_proc [[L_catch2:[^ ]+]] - %catch2 = catchpad [i32 2] - to label %catch2.body unwind label %catch.end -catch2.body: -; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]] -; ^ all funclets use the same frame size -; CHECK: movq [[PSPSymOffset]](%rcx), %rcx -; ^ establisher frame pointer passed in rcx -; CHECK: movq %rcx, [[PSPSymOffset]](%rsp) -; CHECK: leaq [[FPOffset]](%rcx), %rbp -; CHECK: .seh_endprologue -; CHECK: movq %rdx, %rcx -; ^ exception pointer passed in rdx -; CHECK-NEXT: callq g - %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2) - call void @g(i8 addrspace(1)* %exn2) -; CHECK: [[L_before_f4:.+]]: -; CHECK-NEXT: movl $4, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f4:.+]]: - invoke void @f(i32 4) - to label %try_in_catch unwind label %catch.end -try_in_catch: -; CHECK: # %try_in_catch -; CHECK: [[L_before_f5:.+]]: -; CHECK-NEXT: movl $5, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f5:.+]]: - invoke void @f(i32 5) - to label %catch2.ret unwind label %fault.pad -fault.pad: -; CHECK: .seh_proc [[L_fault:[^ ]+]] - %fault = cleanuppad [i32 undef] -; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]] -; ^ all funclets use the same frame size -; CHECK: movq [[PSPSymOffset]](%rcx), %rcx -; ^ establisher frame pointer passed in rcx -; CHECK: movq %rcx, [[PSPSymOffset]](%rsp) -; CHECK: leaq [[FPOffset]](%rcx), %rbp -; CHECK: .seh_endprologue -; CHECK: [[L_before_f6:.+]]: -; CHECK-NEXT: movl $6, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f6:.+]]: - invoke void @f(i32 6) - to label %fault.ret unwind label %fault.end -fault.ret: - cleanupret %fault unwind label %catch.end -fault.end: - cleanupendpad %fault unwind label %catch.end -catch2.ret: - catchret %catch2 to label %finally.clone -catch.end: - catchendpad unwind label %finally.pad -finally.clone: - call void @f(i32 7) - br label %tail -finally.pad: -; CHECK: .seh_proc [[L_finally:[^ ]+]] - %finally = cleanuppad [] -; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]] -; ^ all funclets use the same frame size -; CHECK: movq [[PSPSymOffset]](%rcx), %rcx -; ^ establisher frame pointer passed in rcx -; CHECK: movq %rcx, [[PSPSymOffset]](%rsp) -; CHECK: leaq [[FPOffset]](%rcx), %rbp -; CHECK: .seh_endprologue -; CHECK: [[L_before_f7:.+]]: -; CHECK-NEXT: movl $7, %ecx -; CHECK-NEXT: callq f -; CHECK-NEXT: [[L_after_f7:.+]]: - invoke void @f(i32 7) - to label %finally.ret unwind label %finally.end -finally.ret: - cleanupret %finally unwind to caller -finally.end: - cleanupendpad %finally unwind to caller -tail: - call void @f(i32 8) - ret void -; CHECK: [[L_end:.*func_end.*]]: -} - -; Now check for EH table in xdata (following standard xdata) -; CHECK-LABEL: .section .xdata -; standard xdata comes here -; CHECK: .long 4{{$}} -; ^ number of funclets -; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]] -; ^ offset from L_begin to start of 1st funclet -; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]] -; ^ offset from L_begin to start of 2nd funclet -; CHECK-NEXT: .long [[L_fault]]-[[L_begin]] -; ^ offset from L_begin to start of 3rd funclet -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset from L_begin to start of 4th funclet -; CHECK-NEXT: .long [[L_end]]-[[L_begin]] -; ^ offset from L_begin to end of last funclet -; CHECK-NEXT: .long 7 -; ^ number of EH clauses -; Clause 1: call f(2) is guarded by catch1 -; CHECK-NEXT: .long 0 -; ^ flags (0 => catch handler) -; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 1 -; ^ type token of catch (from catchpad) -; Clause 2: call f(2) is also guarded by catch2 -; CHECK-NEXT: .long 0 -; ^ flags (0 => catch handler) -; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_fault]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 2 -; ^ type token of catch (from catchpad) -; Clause 3: calls f(1) and f(2) are guarded by finally -; CHECK-NEXT: .long 2 -; ^ flags (2 => finally handler) -; CHECK-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_end]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 0 -; ^ type token slot (null for finally) -; Clause 4: call f(3) is guarded by finally -; This is a "duplicate" because the protected range (f(3)) -; is in funclet catch1 but the finally's immediate parent -; is the main function, not that funclet. -; CHECK-NEXT: .long 10 -; ^ flags (2 => finally handler | 8 => duplicate) -; CHECK-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_end]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 0 -; ^ type token slot (null for finally) -; Clause 5: call f(5) is guarded by fault -; CHECK-NEXT: .long 4 -; ^ flags (4 => fault handler) -; CHECK-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_fault]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 0 -; ^ type token slot (null for fault) -; Clause 6: calls f(4) and f(5) are guarded by finally -; This is a "duplicate" because the protected range (f(4)-f(5)) -; is in funclet catch2 but the finally's immediate parent -; is the main function, not that funclet. -; CHECK-NEXT: .long 10 -; ^ flags (2 => finally handler | 8 => duplicate) -; CHECK-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_end]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 0 -; ^ type token slot (null for finally) -; Clause 7: call f(6) is guarded by finally -; This is a "duplicate" because the protected range (f(3)) -; is in funclet catch1 but the finally's immediate parent -; is the main function, not that funclet. -; CHECK-NEXT: .long 10 -; ^ flags (2 => finally handler | 8 => duplicate) -; CHECK-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1 -; ^ offset of start of clause -; CHECK-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1 -; ^ offset of end of clause -; CHECK-NEXT: .long [[L_finally]]-[[L_begin]] -; ^ offset of start of handler -; CHECK-NEXT: .long [[L_end]]-[[L_begin]] -; ^ offset of end of handler -; CHECK-NEXT: .long 0 -; ^ type token slot (null for finally) diff --git a/llvm/test/CodeGen/WinEH/wineh-demotion.ll b/llvm/test/CodeGen/WinEH/wineh-demotion.ll index 96f33b0ed1a..bd239133ea8 100644 --- a/llvm/test/CodeGen/WinEH/wineh-demotion.ll +++ b/llvm/test/CodeGen/WinEH/wineh-demotion.ll @@ -1,4 +1,4 @@ -; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s +; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s declare i32 @__CxxFrameHandler3(...) @@ -36,17 +36,15 @@ merge: ; CHECK: merge: ; CHECK-NOT: = phi %phi = phi i32 [ %x, %left ], [ %y, %right ] - %cp = catchpad [] to label %catch unwind label %catchend + %cs1 = catchswitch within none [label %catch] unwind to caller catch: + %cp = catchpad within %cs1 [] ; CHECK: catch: ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]] ; CHECK-NEXT: call void @h(i32 [[Reload]]) call void @h(i32 %phi) - catchret %cp to label %exit - -catchend: - catchendpad unwind to caller + catchret from %cp to label %exit exit: ret void @@ -75,44 +73,42 @@ right: merge.inner: ; CHECK: merge.inner: ; CHECK-NOT: = phi - ; CHECK: catchpad [] + ; CHECK: catchswitch within none %x = phi i32 [ 1, %left ], [ 2, %right ] - %cpinner = catchpad [] to label %catch.inner unwind label %catchend.inner + %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer catch.inner: + %cpinner = catchpad within %cs1 [] ; Need just one store here because only %y is affected ; CHECK: catch.inner: %z = call i32 @g() ; CHECK: store i32 %z ; CHECK-NEXT: invoke void @f invoke void @f() - to label %catchret.inner unwind label %catchend.inner + to label %catchret.inner unwind label %merge.outer catchret.inner: - catchret %cpinner to label %exit -catchend.inner: - ; CHECK-NOT: = phi - %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ] - catchendpad unwind label %merge.outer + catchret from %cpinner to label %exit merge.outer: + %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ] ; CHECK: merge.outer: - ; CHECK: [[CatchPad:%[^ ]+]] = catchpad [] - %cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer - -catchend.outer: - catchendpad unwind to caller + ; CHECK-NOT: = phi + ; CHECK: catchswitch within none + %cs2 = catchswitch within none [label %catch.outer] unwind to caller catch.outer: + %cpouter = catchpad within %cs2 [] + ; CHECK: catch.outer: + ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 [] ; Need to load x and y from two different slots since they're both live ; and can have different values (if we came from catch.inner) - ; CHECK: catch.outer: ; CHECK-DAG: load i32, i32* [[Slot1]] ; CHECK-DAG: load i32, i32* [[Slot2]] - ; CHECK: catchret [[CatchPad]] to label + ; CHECK: catchret from [[CatchPad]] to label call void @h(i32 %x) call void @h(i32 %y) - catchret %cpouter to label %exit + catchret from %cpouter to label %exit exit: ret void @@ -145,13 +141,12 @@ right: to label %join unwind label %catchpad.inner catchpad.inner: ; CHECK: catchpad.inner: - ; CHECK-NEXT: catchpad [] + ; CHECK-NEXT: catchswitch within none %phi.inner = phi i32 [ %l, %left ], [ %r, %right ] - %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner + %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer catch.inner: - catchret %cp1 to label %join -catchend.inner: - catchendpad unwind label %catchpad.outer + %cp1 = catchpad within %cs1 [] + catchret from %cp1 to label %join join: ; CHECK: join: ; CHECK-NOT: store @@ -160,19 +155,19 @@ join: %j = call i32 @g() invoke void @f() to label %exit unwind label %catchpad.outer + catchpad.outer: ; CHECK: catchpad.outer: - ; CHECK-NEXT: catchpad [] - %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ] - %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer + ; CHECK-NEXT: catchswitch within none + %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ] + %cs2 = catchswitch within none [label %catch.outer] unwind to caller catch.outer: ; CHECK: catch.outer: ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]] ; CHECK: call void @h(i32 [[Reload]]) + %cp2 = catchpad within %cs2 [] call void @h(i32 %phi.outer) - catchret %cp2 to label %exit -catchend.outer: - catchendpad unwind to caller + catchret from %cp2 to label %exit exit: ret void } @@ -198,10 +193,10 @@ invoke.cont: cleanup: ; cleanup phi can be loaded at cleanup entry ; CHECK: cleanup: - ; CHECK-NEXT: cleanuppad [] + ; CHECK-NEXT: cleanuppad within none [] ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]] %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ] - %cp = cleanuppad [] + %cp = cleanuppad within none [] %b = call i1 @i() br i1 %b, label %left, label %right @@ -222,7 +217,7 @@ merge: ; CHECK: merge: ; CHECK-NEXT: store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]] ; CHECK-NEXT: cleanupret - cleanupret %cp unwind label %catchpad + cleanupret from %cp unwind label %catchswitch invoke.cont2: ; need store for %phi.catch @@ -230,23 +225,22 @@ invoke.cont2: ; CHECK-NEXT: store i32 3, i32* [[CatchSlot]] ; CHECK-NEXT: invoke void @f invoke void @f() - to label %exit unwind label %catchpad + to label %exit unwind label %catchswitch -catchpad: - ; CHECK: catchpad: - ; CHECK-NEXT: catchpad [] +catchswitch: + ; CHECK: catchswitch: + ; CHECK-NEXT: catchswitch within none %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ] - %cp2 = catchpad [] to label %catch unwind label %catchend + %cs1 = catchswitch within none [label %catch] unwind to caller catch: ; CHECK: catch: + ; CHECK: catchpad within %cs1 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]] ; CHECK: call void @h(i32 [[CatchReload]] + %cp2 = catchpad within %cs1 [] call void @h(i32 %phi.catch) - catchret %cp2 to label %exit - -catchend: - catchendpad unwind to caller + catchret from %cp2 to label %exit exit: ret void @@ -262,17 +256,17 @@ entry: %x = invoke i32 @g() to label %loop unwind label %to_caller to_caller: - %cp1 = cleanuppad [] - cleanupret %cp1 unwind to caller + %cp1 = cleanuppad within none [] + cleanupret from %cp1 unwind to caller loop: invoke void @f() to label %loop unwind label %cleanup cleanup: ; CHECK: cleanup: ; CHECK: call void @h(i32 %x) - %cp2 = cleanuppad [] + %cp2 = cleanuppad within none [] call void @h(i32 %x) - cleanupret %cp2 unwind to caller + cleanupret from %cp2 unwind to caller } ; CHECK-LABEL: @test7( @@ -294,18 +288,21 @@ invoke.cont: catchpad: ; %x phi should be eliminated ; CHECK: catchpad: - ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad [] + ; CHECK-NEXT: catchswitch within none %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ] - %cp = catchpad [] to label %catch unwind label %catchend + %cs1 = catchswitch within none [label %catch] unwind to caller catch: + ; CHECK: catch: + ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 [] + %cp = catchpad within %cs1 [] %b = call i1 @i() br i1 %b, label %left, label %right left: ; Edge from %left to %join needs to be split so that ; the load of %x can be inserted *after* the catchret ; CHECK: left: - ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]] - catchret %cp to label %join + ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]] + catchret from %cp to label %join ; CHECK: [[SplitLeft]]: ; CHECK: [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]] ; CHECK: br label %join @@ -314,11 +311,9 @@ right: ; the load of %y can be inserted *after* the catchret ; CHECK: right: ; CHECK: %y = call i32 @g() - ; CHECK: catchret %[[CatchPad]] to label %join + ; CHECK: catchret from %[[CatchPad]] to label %join %y = call i32 @g() - catchret %cp to label %join -catchend: - catchendpad unwind to caller + catchret from %cp to label %join join: ; CHECK: join: ; CHECK: %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ] @@ -340,20 +335,20 @@ done: ret void cleanup1: - ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad [] + ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none [] ; CHECK-NEXT: call void @f() - ; CHECK-NEXT: cleanupret [[CleanupPad1]] - %cp0 = cleanuppad [] + ; CHECK-NEXT: cleanupret from [[CleanupPad1]] + %cp0 = cleanuppad within none [] br label %cleanupexit cleanup2: - ; CHECK: cleanuppad [] + ; CHECK: cleanuppad within none [] ; CHECK-NEXT: call void @f() ; CHECK-NEXT: unreachable - %cp1 = cleanuppad [] + %cp1 = cleanuppad within none [] br label %cleanupexit cleanupexit: call void @f() - cleanupret %cp0 unwind label %cleanup2 + cleanupret from %cp0 unwind label %cleanup2 } diff --git a/llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll b/llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll deleted file mode 100644 index 47ffc35acac..00000000000 --- a/llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll +++ /dev/null @@ -1,28 +0,0 @@ -; RUN: llc -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s - -declare void @ProcessCLRException() -declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token) -declare void @f() -declare void @g(i32 addrspace(1)*) - -; CHECK-LABEL: test1: # @test1 -define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) { -entry: - invoke void @f() - to label %exit unwind label %catch.pad -catch.pad: -; CHECK: {{^[^: ]+}}: # %catch.pad - %catch = catchpad [i32 5] - to label %catch.body unwind label %catch.end -catch.body: - %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch) - %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)* - ; CHECK: movq %rdx, %rcx - ; CHECK-NEXT: callq g - call void @g(i32 addrspace(1)* %cast_exn) - catchret %catch to label %exit -catch.end: - catchendpad unwind to caller -exit: - ret void -} diff --git a/llvm/test/CodeGen/WinEH/wineh-intrinsics.ll b/llvm/test/CodeGen/WinEH/wineh-intrinsics.ll index acdeb796ac1..3658792a384 100644 --- a/llvm/test/CodeGen/WinEH/wineh-intrinsics.ll +++ b/llvm/test/CodeGen/WinEH/wineh-intrinsics.ll @@ -15,13 +15,12 @@ entry: invoke void (...) @f(i32 1) to label %exit unwind label %catchpad catchpad: - %catch = catchpad [i32 1] to label %do_catch unwind label %catchend + %cs1 = catchswitch within none [label %do_catch] unwind to caller do_catch: + %catch = catchpad within %cs1 [i32 1] %exn = call i8* @llvm.eh.exceptionpointer.p0i8(token %catch) call void (...) @f(i8* %exn) - catchret %catch to label %exit -catchend: - catchendpad unwind to caller + catchret from %catch to label %exit exit: ret void } @@ -31,13 +30,12 @@ entry: invoke void (...) @f(i32 1) to label %exit unwind label %catchpad catchpad: - %catch = catchpad [i32 1] to label %do_catch unwind label %catchend + %cs1 = catchswitch within none [label %do_catch] unwind to caller do_catch: + %catch = catchpad within %cs1 [i32 1] %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch) call void (...) @f(i8 addrspace(1)* %exn) - catchret %catch to label %exit -catchend: - catchendpad unwind to caller + catchret from %catch to label %exit exit: ret void } diff --git a/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll b/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll deleted file mode 100644 index 1e9342d17cb..00000000000 --- a/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll +++ /dev/null @@ -1,1548 +0,0 @@ -; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s - -declare i32 @__CxxFrameHandler3(...) - -declare void @f() -declare i32 @g() -declare void @h(i32) -declare i1 @b() - -define void @test1() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - %i = cleanuppad [] - call void @h(i32 %x) - cleanupret %i unwind label %right.end -exit: - ret void -} -; %inner is a cleanup which appears both as a child of -; %left and as a child of %right. Since statically we -; need each funclet to have a single parent, we need to -; clone the entire %inner funclet so we can have one -; copy under each parent. The cleanupret in %inner -; unwinds to the catchendpad for %right, so the copy -; of %inner under %right should include it; the copy -; of %inner under %left should instead have an -; `unreachable` inserted there, but the copy under -; %left still needs to be created because it's possible -; the dynamic path enters %left, then enters %inner, -; then calls @h, and that the call to @h doesn't return. -; CHECK-LABEL: define void @test1( -; CHECK: left: -; CHECK: cleanuppad -; CHECK: %x.for.left = call i32 @g() -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: %x = call i32 @g() -; CHECK: to label %shared.cont unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: shared.cont: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 %x) -; CHECK: cleanupret [[I_R]] unwind label %right.end -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable - - -define void @test2() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %right.end -exit: - ret void -} -; In this case left and right are both parents of inner. This differs from -; @test1 in that inner is a catchpad rather than a cleanuppad, which makes -; inner.end a block that gets cloned so that left and right each contain a -; copy (catchendpad blocks are considered to be part of the parent funclet -; of the associated catchpad). The catchendpad in %inner.end unwinds to -; %right.end (which belongs to the entry funclet). -; CHECK-LABEL: define void @test2( -; CHECK: left: -; CHECK: cleanuppad -; CHECK: %x.for.left = call i32 @g() -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] -; CHECK: right.catch: -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind label %[[RIGHT_END]] - -define void @test3() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - %l = cleanuppad [] - br label %shared -left.end: - cleanupendpad %l unwind label %right -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; In this case, %left and %right are siblings with %entry as the parent of both, -; while %left and %right are both parents of %inner. The catchendpad in -; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end -; will be made for both %left and %right, but because %left.end is a cleanup pad -; and %right is a catch pad the unwind edge from the copy of %inner.end for -; %right must be removed. -; CHECK-LABEL: define void @test3( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: %x.for.left = call i32 @g() -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_END:left.end.*]]: -; CHECK: cleanupendpad %l unwind label %right -; CHECK: right: -; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] -; CHECK: right.catch: -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller - - -define void @test4() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %left.end -left.catch: - br label %shared -left.end: - catchendpad unwind label %right -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This is a variation of @test3 in which both %left and %right are catch pads. -; In this case, %left and %right are siblings with %entry as the parent of both, -; while %left and %right are both parents of %inner. The catchendpad in -; %inner.end unwinds to %left.end. When %inner is cloned a copy of %inner.end -; will be made for both %left and %right, but because the catchpad in %right -; does not unwind to %left.end the unwind edge from the copy of %inner.end for -; %right must be removed. -; CHECK-LABEL: define void @test4( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] -; CHECK: left.catch: -; CHECK: %x.for.left = call i32 @g() -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind label %right -; CHECK: right: -; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] -; CHECK: right.catch: -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] - - -define void @test5() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %left.end -left.catch: - br label %shared -left.end: - catchendpad unwind label %right -right: - %r = cleanuppad [] - br label %shared -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; Like @test3, %left and %right are siblings with %entry as the parent of both, -; while %left and %right are both parents of %inner. This case makes %left a -; catch and %right a cleanup so that %inner unwinds to %left.end, which is a -; block in %entry. The %inner funclet is cloned for %left and %right, but the -; copy of %inner.end for %right must have its unwind edge removed because the -; catchendpad at %left.end is not compatible with %right. -; CHECK-LABEL: define void @test5( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] -; CHECK: left.catch: -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind label %right -; CHECK: right: -; CHECK: %r = cleanuppad [] -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] - -define void @test6() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %left.end -left.catch: - br label %shared -left.end: - catchendpad unwind label %middle -middle: - %m = catchpad [] - to label %middle.catch unwind label %middle.end -middle.catch: - catchret %m to label %exit -middle.end: - catchendpad unwind label %right -right: - %r = cleanuppad [] - br label %shared -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This is like @test5 but it inserts another sibling between %left and %right. -; In this case %left, %middle and %right are all siblings, while %left and -; %right are both parents of %inner. This checks the proper handling of the -; catchendpad in %inner.end (which will be cloned so that %left and %right both -; have copies) unwinding to a catchendpad that unwinds to a sibling. -; CHECK-LABEL: define void @test6( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] -; CHECK: left.catch: -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind label %middle -; CHECK: middle: -; CHECK: catchpad [] -; CHECK: to label %middle.catch unwind label %middle.end -; CHECK: middle.catch: -; CHECK: catchret %m to label %exit -; CHECK: middle.end: -; CHECK: catchendpad unwind label %right -; CHECK: right: -; CHECK: %r = cleanuppad [] -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] - - -define void @test7() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %left.end -left.catch: - br label %shared -left.end: - catchendpad unwind label %right -right: - %r = cleanuppad [] - br label %shared -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %inner.sibling -inner.sibling: - %is = cleanuppad [] - call void @h(i32 0) - cleanupret %is unwind label %left.end -exit: - ret void -} -; This is like @test5 but instead of unwinding to %left.end, the catchendpad -; in %inner.end unwinds to a sibling cleanup pad. Both %inner (along with its -; associated blocks) and %inner.sibling must be cloned for %left and %right. -; The clones of %inner will be identical, but the copy of %inner.sibling for -; %right must end with an unreachable instruction, because it cannot unwind to -; %left.end. -; CHECK-LABEL: define void @test7( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] -; CHECK: left.catch: -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind label %[[RIGHT:.+]] -; CHECK: [[RIGHT]]: -; CHECK: [[R:\%.+]] = cleanuppad [] -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[INNER_SIBLING_LEFT:.+]] -; CHECK: [[INNER_SIBLING_RIGHT]] -; CHECK: [[IS_R:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_SIBLING_LEFT]] -; CHECK: [[IS_L:\%.+]] = cleanuppad [] -; CHECK: call void @h(i32 0) -; CHECK: cleanupret [[IS_L]] unwind label %[[LEFT_END]] - - -define void @test8() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %unreachable unwind label %right -left: - cleanuppad [] - invoke void @f() to label %unreachable unwind label %inner -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - invoke void @f() to label %unreachable unwind label %inner -right.end: - catchendpad unwind to caller -inner: - %i = cleanuppad [] - %x = call i32 @g() - call void @h(i32 %x) - cleanupret %i unwind label %right.end -unreachable: - unreachable -} -; Another case of a two-parent child (like @test1), this time -; with the join at the entry itself instead of following a -; non-pad join. -; CHECK-LABEL: define void @test8( -; CHECK: invoke.cont: -; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right -; CHECK: left: -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: to label %unreachable unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_R:\%.+]] = cleanuppad [] -; CHECK: [[X_R:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X_R]]) -; CHECK: cleanupret [[I_R]] unwind label %right.end -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_L:\%.+]] = cleanuppad [] -; CHECK: [[X_L:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X_L]]) -; CHECK: unreachable -; CHECK: unreachable: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_ENTRY]]: -; CHECK: unreachable - - -define void @test9() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %unreachable unwind label %right -left: - cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -inner: - cleanuppad [] - invoke void @f() - to label %unreachable unwind label %inner.child -inner.child: - cleanuppad [] - %x = call i32 @g() - call void @h(i32 %x) - unreachable -unreachable: - unreachable -} -; %inner is a two-parent child which itself has a child; need -; to make two copies of both the %inner and %inner.child. -; CHECK-LABEL: define void @test9( -; CHECK: invoke.cont: -; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right -; CHECK: left: -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_RIGHT]]: -; CHECK: to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]] -; CHECK: [[INNER_CHILD_RIGHT]]: -; CHECK: [[TMP:\%.+]] = cleanuppad [] -; CHECK: [[X:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X]]) -; CHECK: unreachable -; CHECK: [[INNER_CHILD_LEFT]]: -; CHECK: [[TMP:\%.+]] = cleanuppad [] -; CHECK: [[X:\%.+]] = call i32 @g() -; CHECK: call void @h(i32 [[X]]) -; CHECK: unreachable -; CHECK: [[UNREACHABLE_INNER_RIGHT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_INNER_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_RIGHT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_ENTRY]]: -; CHECK: unreachable - - -define void @test10() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %unreachable unwind label %right -left: - cleanuppad [] - call void @h(i32 1) - invoke void @f() - to label %unreachable unwind label %right -right: - cleanuppad [] - call void @h(i32 2) - invoke void @f() - to label %unreachable unwind label %left -unreachable: - unreachable -} -; This is an irreducible loop with two funclets that enter each other; -; need to make two copies of each funclet (one a child of root, the -; other a child of the opposite funclet), but also make sure not to -; clone self-descendants (if we tried to do that we'd need to make an -; infinite number of them). Presumably if optimizations ever generated -; such a thing it would mean that one of the two cleanups was originally -; the parent of the other, but that we'd somehow lost track in the CFG -; of which was which along the way; generating each possibility lets -; whichever case was correct execute correctly. -; CHECK-LABEL: define void @test10( -; CHECK: entry: -; CHECK: to label %invoke.cont unwind label %[[LEFT:.+]] -; CHECK: invoke.cont: -; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]] -; CHECK: [[LEFT_FROM_RIGHT:.+]]: -; CHECK: call void @h(i32 1) -; CHECK: call void @f() -; CHECK: unreachable -; CHECK: [[LEFT]]: -; CHECK: call void @h(i32 1) -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]] -; CHECK: [[RIGHT]]: -; CHECK: call void @h(i32 2) -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]] -; CHECK: [[RIGHT_FROM_LEFT]]: -; CHECK: call void @h(i32 2) -; CHECK: call void @f() -; CHECK: unreachable -; CHECK: [[UNREACHABLE_RIGHT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_LEFT]]: -; CHECK: unreachable -; CHECK: [[UNREACHABLE_ENTRY]]: -; CHECK: unreachable - - -define void @test11() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %left.sibling -left.catch: - br label %shared -left.sibling: - %ls = catchpad [] - to label %left.sibling.catch unwind label %left.end -left.sibling.catch: - catchret %ls to label %exit -left.end: - catchendpad unwind label %right -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This is a variation of @test4 in which the shared child funclet unwinds to a -; catchend pad that is the unwind destination of %left.sibling rather than %left -; but is still a valid destination for %inner as reach from %left. -; When %inner is cloned a copy of %inner.end will be made for both %left and -; %right, but because the catchpad in %right does not unwind to %left.end the -; unwind edge from the copy of %inner.end for %right must be removed. -; CHECK-LABEL: define void @test11( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %left.sibling -; CHECK: left.catch: -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: left.sibling: -; CHECK: catchpad [] -; CHECK: to label %left.sibling.catch unwind label %[[LEFT_END:.+]] -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind label %right -; CHECK: right: -; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] -; CHECK: right.catch: -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] - - -define void @test12() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - catchpad [] - to label %left.catch unwind label %right -left.catch: - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - %x = call i32 @g() - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 %x) - unreachable -inner.end: - catchendpad unwind label %right.end -exit: - ret void -} -; In this case %left and %right are both parents of %inner, so %inner must be -; cloned but the catchendpad unwind target in %inner.end is valid for both -; parents, so the unwind edge should not be removed in either case. -; CHECK-LABEL: define void @test12( -; CHECK: left: -; CHECK: catchpad [] -; CHECK: to label %left.catch unwind label %right -; CHECK: left.catch: -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: to label %right.catch unwind label %[[RIGHT_END:.+]] -; CHECK: right.catch: -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 %x) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 %x.for.left) -; CHECK: unreachable -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind label %[[RIGHT_END]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[RIGHT_END]] - -define void @test13() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - %l = catchpad [] - to label %left.cont unwind label %left.end -left.cont: - invoke void @f() - to label %left.ret unwind label %inner -left.ret: - catchret %l to label %invoke.cont -left.end: - catchendpad unwind to caller -right: - %r = catchpad [] - to label %right.catch unwind label %right.end -right.catch: - invoke void @f() - to label %right.ret unwind label %inner -right.ret: - catchret %r to label %exit -right.end: - catchendpad unwind to caller -shared: - call void @h(i32 0) - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 1) - catchret %i to label %shared -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This case tests the scenario where a funclet with multiple parents uses a -; catchret to return to a block that may exist in either parent funclets. -; Both %left and %right are parents of %inner. During common block cloning -; a clone of %shared will be made so that both %left and %right have a copy, -; but the copy of %shared for one of the parent funclets will be unreachable -; until the %inner funclet is cloned. When the %inner.catch block is cloned -; during the %inner funclet cloning, the catchret instruction should be updated -; so that the catchret in the copy %inner.catch for %left returns to the copy of -; %shared in %left and the catchret in the copy of %inner.catch for %right -; returns to the copy of %shared for %right. -; CHECK-LABEL: define void @test13( -; CHECK: left: -; CHECK: %l = catchpad [] -; CHECK: to label %left.cont unwind label %left.end -; CHECK: left.cont: -; CHECK: invoke void @f() -; CHECK: to label %left.ret unwind label %[[INNER_LEFT:.+]] -; CHECK: left.ret: -; CHECK: catchret %l to label %invoke.cont -; CHECK: left.end: -; CHECK: catchendpad unwind to caller -; CHECK: right: -; CHECK: %r = catchpad [] -; CHECK: to label %right.catch unwind label %right.end -; CHECK: right.catch: -; CHECK: invoke void @f() -; CHECK: to label %right.ret unwind label %[[INNER_RIGHT:.+]] -; CHECK: right.ret: -; CHECK: catchret %r to label %exit -; CHECK: right.end: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_RIGHT:.+]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[SHARED_LEFT:.+]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: %[[I_RIGHT:.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: %[[I_LEFT:.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 1) -; CHECK: catchret %[[I_RIGHT]] to label %[[SHARED_RIGHT]] -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 1) -; CHECK: catchret %[[I_LEFT]] to label %[[SHARED_LEFT]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller - - -define void @test14() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - %l = catchpad [] - to label %shared unwind label %left.end -left.cont: - invoke void @f() - to label %left.ret unwind label %right -left.ret: - catchret %l to label %exit -left.end: - catchendpad unwind to caller -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind label %left.end -shared: - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 0) - catchret %i to label %left.cont -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This case tests another scenario where a funclet with multiple parents uses a -; catchret to return to a block in one of the parent funclets. Here %right and -; %left are both parents of %inner and %left is a parent of %right. The -; catchret in %inner.catch will cause %left.cont and %left.ret to be cloned for -; both %left and %right, but the catchret in %left.ret is invalid for %right -; but the catchret instruction in the copy of %left.ret for %right will be -; removed as an implausible terminator. -; CHECK-LABEL: define void @test14( -; CHECK: left: -; CHECK: %l = catchpad [] -; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[LEFT_END:.+]] -; CHECK: [[LEFT_CONT:left.cont.*]]: -; CHECK: invoke void @f() -; CHECK: to label %[[LEFT_RET:.+]] unwind label %[[RIGHT:.+]] -; CHECK: [[LEFT_RET]]: -; CHECK: catchret %l to label %exit -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] -; CHECK: [[SHARED_LEFT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 0) -; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller - -define void @test15() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - %l = catchpad [] - to label %left.catch unwind label %left.end -left.catch: - invoke void @f() - to label %shared unwind label %right -left.ret: - catchret %l to label %exit -left.end: - catchendpad unwind to caller -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind label %left.end -shared: - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 0) - catchret %i to label %left.ret -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This case is a variation of test14 but instead of returning to an invoke the -; catchret in %inner.catch returns to a catchret instruction. -; CHECK-LABEL: define void @test15( -; CHECK: left: -; CHECK: %l = catchpad [] -; CHECK: to label %left.catch unwind label %[[LEFT_END:.+]] -; CHECK: left.catch: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_LEFT:.+]] unwind label %[[RIGHT:.+]] -; CHECK: [[LEFT_RET_RIGHT:.+]]: -; CHECK: unreachable -; CHECK: [[LEFT_RET_LEFT:.+]]: -; CHECK: catchret %l to label %exit -; CHECK: [[LEFT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] -; CHECK: [[SHARED_LEFT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 0) -; CHECK: catchret [[I_LEFT]] to label %[[LEFT_RET_LEFT]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 0) -; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_RET_RIGHT]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END]] - - -define void @test16() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %exit unwind label %left -left: - %l = cleanuppad [] - br label %shared -left.cont: - cleanupret %l unwind label %right -left.end: - cleanupendpad %l unwind label %right -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %shared.cont unwind label %inner -shared.cont: - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.end -inner.catch: - call void @h(i32 0) - catchret %i to label %left.cont -inner.end: - catchendpad unwind label %left.end -exit: - ret void -} -; This case is another variation of test14 but here the catchret in %inner.catch -; returns to a cleanupret instruction. -; CHECK-LABEL: define void @test16( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: [[LEFT_CONT_RIGHT:.+]]: -; CHECK: unreachable -; CHECK: [[LEFT_CONT_LEFT:.+]]: -; CHECK: cleanupret %l unwind label %[[RIGHT:.+]] -; CHECK: [[LEFT_END_LEFT:.+]]: -; CHECK: cleanupendpad %l unwind label %[[RIGHT]] -; CHECK: [[RIGHT]]: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 0) -; CHECK: catchret [[I_RIGHT]] to label %[[LEFT_CONT_RIGHT]] -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 0) -; CHECK: catchret [[I_LEFT]] to label %[[LEFT_CONT_LEFT]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind label %[[LEFT_END_LEFT]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind to caller - - -define void @test17() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - %l = cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -unreachable: - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.sibling -inner.catch: - call void @h(i32 0) - unreachable -inner.sibling: - %is = catchpad [] - to label %inner.sibling.catch unwind label %inner.end -inner.sibling.catch: - invoke void @f() - to label %unreachable unwind label %inner.end -inner.end: - catchendpad unwind label %right.end -exit: - ret void -} -; This case tests the scenario where two catchpads with the same catchendpad -; have multiple parents. Both %left and %right are parents of %inner and -; %inner.sibling so both of the inner funclets must be cloned. Because -; the catchendpad in %inner.end unwinds to the catchendpad for %right, the -; unwind edge should be removed for the copy of %inner.end that is reached -; from %left. In addition, the %inner.siblin.catch block contains an invoke -; that unwinds to the shared inner catchendpad. The unwind destination for -; this invoke should be updated to unwind to the correct cloned %inner.end -; for each path to the funclet. -; CHECK-LABEL: define void @test17( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_SIBLING_RIGHT]]: -; CHECK: [[IS_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_SIBLING_LEFT]]: -; CHECK: [[IS_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]] -; CHECK: [[INNER_SIBLING_CATCH_LEFT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind label %[[RIGHT_END]] - - -define void @test18() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - %l = cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -unreachable: - unreachable -inner: - %i = catchpad [] - to label %inner.catch unwind label %inner.sibling -inner.catch: - invoke void @f() - to label %unreachable unwind label %inner.end -inner.sibling: - %is = catchpad [] - to label %inner.sibling.catch unwind label %inner.end -inner.sibling.catch: - call void @h(i32 0) - unreachable -inner.end: - catchendpad unwind label %right.end -exit: - ret void -} -; This is like test17 except that the inner invoke is moved from the -; %inner.sibling funclet to %inner so that it is unwinding to a -; catchendpad block that has not yet been cloned. The unwind destination -; of the invoke should still be updated to reach the correct copy of -; %inner.end for the path by which it is reached. -; CHECK-LABEL: define void @test18( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]] -; CHECK: [[INNER_CATCH_RIGHT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_CATCH_LEFT]]: -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_SIBLING_RIGHT]]: -; CHECK: [[IS_RIGHT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]] -; CHECK: [[INNER_SIBLING_LEFT]]: -; CHECK: [[IS_LEFT:\%.+]] = catchpad [] -; CHECK: to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT]] -; CHECK: [[INNER_SIBLING_CATCH_RIGHT]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_SIBLING_CATCH_LEFT]]: -; CHECK: call void @h(i32 0) -; CHECK: unreachable -; CHECK: [[INNER_END_LEFT]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: catchendpad unwind label %[[RIGHT_END]] - - -define void @test19() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - %l = cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -unreachable: - unreachable -inner: - %i = cleanuppad [] - invoke void @f() - to label %unreachable unwind label %inner.end -inner.end: - cleanupendpad %i unwind label %right.end -exit: - ret void -} -; This case tests the scenario where an invoke in a funclet with multiple -; parents unwinds to a cleanup end pad for the funclet. The unwind destination -; for the invoke should map to the correct copy of the cleanup end pad block. -; CHECK-LABEL: define void @test19( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]] -; CHECK: [[INNER_END_RIGHT]]: -; CHECK: cleanupendpad [[I_RIGHT]] unwind label %[[RIGHT_END]] -; CHECK: [[INNER_END_LEFT]]: -; CHECK: cleanupendpad [[I_LEFT]] unwind to caller - -define void @test20() personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @f() - to label %invoke.cont unwind label %left -invoke.cont: - invoke void @f() - to label %exit unwind label %right -left: - %l = cleanuppad [] - br label %shared -right: - catchpad [] - to label %right.catch unwind label %right.end -right.catch: - br label %shared -right.end: - catchendpad unwind to caller -shared: - invoke void @f() - to label %unreachable unwind label %inner -unreachable: - unreachable -inner: - %i = cleanuppad [] - invoke void @f() - to label %unreachable unwind label %inner.cleanup -inner.cleanup: - cleanuppad [] - call void @f() - unreachable -exit: - ret void -} -; This tests the case where a funclet with multiple parents contains an invoke -; instruction that unwinds to a child funclet. Here %left and %right are both -; parents of %inner. Initially %inner is the only parent of %inner.cleanup but -; after %inner is cloned, %inner.cleanup has multiple parents and so it must -; also be cloned. -; CHECK-LABEL: define void @test20( -; CHECK: left: -; CHECK: %l = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]] -; CHECK: right: -; CHECK: catchpad [] -; CHECK: to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]] -; CHECK: [[RIGHT_CATCH]]: -; CHECK: invoke void @f() -; CHECK: to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]] -; CHECK: [[RIGHT_END]]: -; CHECK: catchendpad unwind to caller -; CHECK: [[SHARED_CONT_RIGHT]]: -; CHECK: unreachable -; CHECK: [[SHARED_CONT_LEFT]]: -; CHECK: unreachable -; CHECK: [[INNER_RIGHT]]: -; CHECK: [[I_RIGHT:\%.+]] = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_CLEANUP_RIGHT:.+]] -; CHECK: [[INNER_LEFT]]: -; CHECK: [[I_LEFT:\%.+]] = cleanuppad [] -; CHECK: invoke void @f() -; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_CLEANUP_LEFT:.+]] -; CHECK: [[INNER_CLEANUP_RIGHT]]: -; CHECK: cleanuppad [] -; CHECK: call void @f() -; CHECK: unreachable -; CHECK: [[INNER_CLEANUP_LEFT]]: -; CHECK: cleanuppad [] -; CHECK: call void @f() -; CHECK: unreachable - - diff --git a/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll b/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll index 4f023947caa..7d18238c003 100644 --- a/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll +++ b/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll @@ -2,6 +2,8 @@ declare i32 @__CxxFrameHandler3(...) +declare i32 @__C_specific_handler(...) + declare void @f() declare i32 @g() @@ -9,7 +11,7 @@ declare i32 @g() declare void @h(i32) ; CHECK-LABEL: @test1( -define void @test1() personality i32 (...)* @__CxxFrameHandler3 { +define void @test1() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %invoke.cont1 unwind label %left @@ -23,11 +25,11 @@ invoke.cont2: to label %exit unwind label %inner left: - %0 = cleanuppad [] + %0 = cleanuppad within none [] br label %shared right: - %1 = cleanuppad [] + %1 = cleanuppad within none [] br label %shared shared: @@ -40,25 +42,20 @@ shared.cont: inner: %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ] - %i = cleanuppad [] + %i = cleanuppad within none [] call void @h(i32 %phi) unreachable -; CHECK [[INNER_INVOKE_CONT2:inner.*]]: - ; CHECK: call void @h(i32 0) - -; CHECK [[INNER_RIGHT:inner.*]]: - ; CHECK: call void @h(i32 %x) - -; CHECK [[INNER_LEFT:inner.*]]: - ; CHECK: call void @h(i32 %x.for.left) +; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ] +; CHECK: %i = cleanuppad within none [] +; CHECK: call void @h(i32 %phi) exit: unreachable } ; CHECK-LABEL: @test2( -define void @test2() personality i32 (...)* @__CxxFrameHandler3 { +define void @test2() personality i32 (...)* @__C_specific_handler { entry: invoke void @f() to label %invoke.cont unwind label %left @@ -68,11 +65,11 @@ invoke.cont: to label %exit unwind label %right left: - cleanuppad [] + cleanuppad within none [] br label %shared right: - cleanuppad [] + cleanuppad within none [] br label %shared shared: @@ -84,15 +81,13 @@ shared.cont: unreachable inner: - %i = cleanuppad [] + %i = cleanuppad within none [] call void @h(i32 %x) unreachable -; CHECK [[INNER_RIGHT:inner.*]]: - ; CHECK: call void @h(i32 %x) - -; CHECK [[INNER_LEFT:inner.*]]: - ; CHECK: call void @h(i32 %x.for.left) +; CHECK: %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ] +; CHECK: %i = cleanuppad within none [] +; CHECK: call void @h(i32 %x1) exit: unreachable @@ -108,10 +103,47 @@ invoke.cont: ret void terminate: -; CHECK: cleanuppad [] +; CHECK: cleanuppad within none [] ; CHECK: call void @__std_terminate() ; CHECK: unreachable - terminatepad [void ()* @__std_terminate] unwind to caller + terminatepad within none [void ()* @__std_terminate] unwind to caller +} + +; CHECK-LABEL: @test4( +define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 { +entry: + invoke void @f() + to label %invoke.cont1 unwind label %left + +invoke.cont1: + invoke void @f() + to label %exit unwind label %right + +left: + %0 = cleanuppad within none [] + br label %shared + +right: + %1 = cleanuppad within none [] + br i1 %x, label %shared, label %right.other + +right.other: + br label %shared + +shared: + %phi = phi i32 [ 1, %left ], [ 0, %right ], [ -1, %right.other ] + call void @h(i32 %phi) + unreachable + +; CHECK: %0 = cleanuppad within none [] +; CHECK: call void @h(i32 1) + +; CHECK: %1 = cleanuppad within none [] +; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ] +; CHECK: call void @h(i32 %phi) + +exit: + unreachable } declare void @__std_terminate() diff --git a/llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll b/llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll index bd1f2322878..f5889f03965 100644 --- a/llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll +++ b/llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll @@ -7,38 +7,6 @@ declare void @dummy_filter() declare void @f(i32) -; CHECK-LABEL: define void @test1( -;Cxx: define void @test1() personality i32 (...)* @__CxxFrameHandler3 { -;SEH: define void @test1() personality i32 (...)* @_except_handler3 { -entry: - ; CHECK: entry: - ; CHECK: store i32 0 - ; CHECK: invoke void @f(i32 0) - invoke void @f(i32 0) - to label %exit unwind label %cleanup.pad -cleanup.pad: - ; CHECK: cleanup.pad: - ; CHECK: store i32 1 - ; CHECK: invoke void @f(i32 1) - %cleanup = cleanuppad [] - invoke void @f(i32 1) - to label %cleanup.ret unwind label %catch.pad -catch.pad: -;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null] -;SEH: %catch = catchpad [void ()* @dummy_filter] - to label %catch.body unwind label %catch.end -catch.body: - catchret %catch to label %cleanup.ret -catch.end: - catchendpad unwind label %cleanup.end -cleanup.ret: - cleanupret %cleanup unwind to caller -cleanup.end: - cleanupendpad %cleanup unwind to caller -exit: - ret void -} - ; CHECK-LABEL: define void @test2( ;Cxx: define void @test2(i1 %b) personality i32 (...)* @__CxxFrameHandler3 { ;SEH: define void @test2(i1 %b) personality i32 (...)* @_except_handler3 { @@ -49,20 +17,18 @@ entry: invoke void @f(i32 1) to label %exit unwind label %cleanup.pad cleanup.pad: - %cleanup = cleanuppad [] + %cleanup = cleanuppad within none [] br i1 %b, label %left, label %right left: - cleanupret %cleanup unwind label %catch.pad + cleanupret from %cleanup unwind label %catch.pad right: - cleanupret %cleanup unwind label %catch.pad + cleanupret from %cleanup unwind label %catch.pad catch.pad: -;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null] -;SEH: %catch = catchpad [void ()* @dummy_filter] - to label %catch.body unwind label %catch.end + %cs1 = catchswitch within none [label %catch.body] unwind to caller catch.body: - catchret %catch to label %exit -catch.end: - catchendpad unwind to caller +;Cxx: %catch = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] +;SEH: %catch = catchpad within %cs1 [void ()* @dummy_filter] + catchret from %catch to label %exit exit: ret void } @@ -72,29 +38,25 @@ exit: ;SEH: define void @test3() personality i32 (...)* @_except_handler3 { entry: ; CHECK: entry: - ; CHECK: store i32 1 + ; CHECK: store i32 0 ; CHECK: invoke void @f(i32 1) invoke void @f(i32 1) to label %exit unwind label %cleanup.pad cleanup.pad: ; CHECK: cleanup.pad: - ; CHECK: store i32 0 + ; CHECK: store i32 1 ; CHECK: invoke void @f(i32 0) - %cleanup = cleanuppad [] + %cleanup = cleanuppad within none [] invoke void @f(i32 0) - to label %unreachable unwind label %cleanup.end + to label %unreachable unwind label %catch.pad unreachable: unreachable -cleanup.end: - cleanupendpad %cleanup unwind label %catch.pad catch.pad: -;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null] -;SEH: %catch = catchpad [void ()* @dummy_filter] - to label %catch.body unwind label %catch.end + %cs1 = catchswitch within none [label %catch.body] unwind to caller catch.body: - catchret %catch to label %exit -catch.end: - catchendpad unwind to caller +;Cxx: %catch = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] +;SEH: %catch = catchpad within %cs1 [void ()* @dummy_filter] + catchret from %catch to label %exit exit: ret void } diff --git a/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll b/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll index 2d5f7ca0c0e..b7ec843aa39 100644 --- a/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll +++ b/llvm/test/CodeGen/WinEH/wineh-statenumbering.ll @@ -37,9 +37,10 @@ entry: to label %unreachable.for.entry unwind label %catch.dispatch catch.dispatch: ; preds = %entry - %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock + %cs1 = catchswitch within none [label %catch] unwind to caller catch: ; preds = %catch.dispatch + %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] ; CHECK: catch: ; CHECK: store i32 2 ; CHECK: invoke void @_CxxThrowException( @@ -47,34 +48,22 @@ catch: ; preds = %catch.dispatch to label %unreachable unwind label %catch.dispatch.1 catch.dispatch.1: ; preds = %catch - %2 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch.3 unwind label %catchendblock.2 - + %cs2 = catchswitch within %1 [label %catch.3] unwind to caller catch.3: ; preds = %catch.dispatch.1 + %2 = catchpad within %cs2 [i8* null, i32 u0x40, i8* null] ; CHECK: catch.3: ; CHECK: store i32 3 - ; CHECK: invoke void @g(i32 1) - invoke void @g(i32 1) - to label %invoke.cont unwind label %catchendblock.2 - -invoke.cont: ; preds = %catch.3 - catchret %2 to label %try.cont + ; CHECK: call void @g(i32 1) + call void @g(i32 1) + catchret from %2 to label %try.cont -try.cont: ; preds = %invoke.cont +try.cont: ; preds = %catch.3 ; CHECK: try.cont: ; CHECK: store i32 1 - ; CHECK: invoke void @g(i32 2) - invoke void @g(i32 2) - to label %invoke.cont.4 unwind label %catchendblock - -invoke.cont.4: ; preds = %try.cont + ; CHECK: call void @g(i32 2) + call void @g(i32 2) unreachable -catchendblock.2: ; preds = %catch.3, %catch.dispatch.1 - catchendpad unwind label %catchendblock - -catchendblock: ; preds = %catchendblock.2, %try.cont, %catch.dispatch - catchendpad unwind to caller - unreachable: ; preds = %catch unreachable |

