summaryrefslogtreecommitdiffstats
path: root/llvm/test/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/CodeGen')
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-cloning.ll398
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-demotion.ll121
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-intrinsics.ll14
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll1548
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-no-demotion.ll78
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll68
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-statenumbering.ll31
-rw-r--r--llvm/test/CodeGen/X86/branchfolding-catchpads.ll45
-rw-r--r--llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll14
-rw-r--r--llvm/test/CodeGen/X86/catchpad-regmask.ll18
-rw-r--r--llvm/test/CodeGen/X86/catchpad-weight.ll27
-rw-r--r--llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll9
-rw-r--r--llvm/test/CodeGen/X86/catchret-fallthrough.ll9
-rw-r--r--llvm/test/CodeGen/X86/cleanuppad-inalloca.ll4
-rw-r--r--llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll4
-rw-r--r--llvm/test/CodeGen/X86/cleanuppad-realign.ll4
-rw-r--r--llvm/test/CodeGen/X86/funclet-layout.ll69
-rw-r--r--llvm/test/CodeGen/X86/late-address-taken.ll10
-rw-r--r--llvm/test/CodeGen/X86/seh-catch-all-win32.ll11
-rw-r--r--llvm/test/CodeGen/X86/seh-catch-all.ll11
-rw-r--r--llvm/test/CodeGen/X86/seh-catchpad.ll61
-rw-r--r--llvm/test/CodeGen/X86/seh-except-finally.ll25
-rw-r--r--llvm/test/CodeGen/X86/seh-exception-code.ll11
-rw-r--r--llvm/test/CodeGen/X86/seh-finally.ll12
-rw-r--r--llvm/test/CodeGen/X86/seh-safe-div-win32.ll26
-rw-r--r--llvm/test/CodeGen/X86/seh-safe-div.ll26
-rw-r--r--llvm/test/CodeGen/X86/seh-stack-realign.ll11
-rw-r--r--llvm/test/CodeGen/X86/tail-dup-catchret.ll9
-rw-r--r--llvm/test/CodeGen/X86/tail-merge-wineh.ll29
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad-csrs.ll62
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll105
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad-nested.ll35
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad-varargs.ll9
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad.ll105
-rw-r--r--llvm/test/CodeGen/X86/win-cleanuppad.ll12
-rw-r--r--llvm/test/CodeGen/X86/win-funclet-cfi.ll15
-rw-r--r--llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll10
-rw-r--r--llvm/test/CodeGen/X86/win32-eh-states.ll183
-rw-r--r--llvm/test/CodeGen/X86/win32-eh.ll30
-rw-r--r--llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll11
-rw-r--r--llvm/test/CodeGen/X86/win32-seh-catchpad.ll76
-rw-r--r--llvm/test/CodeGen/X86/win32-seh-nested-finally.ll (renamed from llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll)21
-rw-r--r--llvm/test/CodeGen/X86/wineh-coreclr.ll (renamed from llvm/test/CodeGen/WinEH/wineh-coreclr.ll)146
-rw-r--r--llvm/test/CodeGen/X86/wineh-exceptionpointer.ll (renamed from llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll)14
44 files changed, 880 insertions, 2657 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-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-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
diff --git a/llvm/test/CodeGen/X86/branchfolding-catchpads.ll b/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
index 21c7818e519..0468b3c314f 100644
--- a/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
+++ b/llvm/test/CodeGen/X86/branchfolding-catchpads.ll
@@ -19,24 +19,18 @@ if.else:
to label %cleanup unwind label %catch.dispatch
catch.dispatch:
- catchpad [i8* null, i32 8, i8* null]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [ label %catch, label %catch.2 ] unwind to caller
catch:
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
- catchpad [i8* null, i32 64, i8* null]
- to label %catch.2 unwind label %catchendblock
+ catchpad within %cs [i8* null, i32 8, i8* null]
+ call void @throw() noreturn
+ br label %unreachable
catch.2:
+ catchpad within %cs [i8* null, i32 64, i8* null]
store i8 1, i8* %b
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catchendblock:
- catchendpad unwind to caller
+ call void @throw() noreturn
+ br label %unreachable
cleanup:
%retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ]
@@ -67,31 +61,22 @@ if.else:
to label %cleanup unwind label %catch.dispatch
catch.dispatch:
- catchpad [i8* null, i32 8, i8* null]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [ label %catch, label %catch.2, label %catch.3 ] unwind to caller
catch:
- invoke void @throw() noreturn
- to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
- %c2 = catchpad [i8* null, i32 32, i8* null]
- to label %catch.2 unwind label %catch.dispatch.3
+ catchpad within %cs [i8* null, i32 8, i8* null]
+ call void @throw() noreturn
+ br label %unreachable
catch.2:
+ %c2 = catchpad within %cs [i8* null, i32 32, i8* null]
store i8 1, i8* %b
- catchret %c2 to label %cleanup
-
-catch.dispatch.3:
- %c3 = catchpad [i8* null, i32 64, i8* null]
- to label %catch.3 unwind label %catchendblock
+ catchret from %c2 to label %cleanup
catch.3:
+ %c3 = catchpad within %cs [i8* null, i32 64, i8* null]
store i8 2, i8* %b
- catchret %c3 to label %cleanup
-
-catchendblock:
- catchendpad unwind to caller
+ catchret from %c3 to label %cleanup
cleanup:
%retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ], [ -1, %catch.2 ], [ -1, %catch.3 ]
diff --git a/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll b/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
index 267c69332c3..1160101792f 100644
--- a/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
+++ b/llvm/test/CodeGen/X86/catchpad-realign-savexmm.ll
@@ -14,19 +14,17 @@ define void @f() personality i32 (...)* @__CxxFrameHandler3 {
%v1 = fadd double %v, 1.0
store double %v1, double* @fp_global
invoke void @g()
- to label %return unwind label %catch
+ to label %return unwind label %catch.dispatch
return:
ret void
-catch:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catchit unwind label %endpad
+catch.dispatch:
+ %cs1 = catchswitch within none [label %catch] unwind to caller
-catchit:
- catchret %p to label %return
-endpad:
- catchendpad unwind to caller
+catch:
+ %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %p to label %return
}
; CHECK: f: # @f
diff --git a/llvm/test/CodeGen/X86/catchpad-regmask.ll b/llvm/test/CodeGen/X86/catchpad-regmask.ll
index fe3a238e173..0d436f6eb59 100644
--- a/llvm/test/CodeGen/X86/catchpad-regmask.ll
+++ b/llvm/test/CodeGen/X86/catchpad-regmask.ll
@@ -41,14 +41,14 @@ entry:
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
%idxprom1 = sext i32 %idx2 to i64
%arrayidx2 = getelementptr inbounds [4 x i32], [4 x i32]* @array, i64 0, i64 %idxprom1
store i32 222, i32* %arrayidx2, align 4, !tbaa !2
- catchret %0 to label %try.cont
+ catchret from %0 to label %try.cont
try.cont: ; preds = %catch
%idxprom3 = sext i32 %idx3 to i64
@@ -56,9 +56,6 @@ try.cont: ; preds = %catch
store i32 333, i32* %arrayidx4, align 4, !tbaa !2
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %entry
unreachable
}
@@ -98,20 +95,17 @@ entry:
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
store i32 222, i32* @imported, align 4, !tbaa !2
- catchret %0 to label %try.cont
+ catchret from %0 to label %try.cont
try.cont: ; preds = %catch
store i32 333, i32* @imported, align 4, !tbaa !2
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %entry
unreachable
}
diff --git a/llvm/test/CodeGen/X86/catchpad-weight.ll b/llvm/test/CodeGen/X86/catchpad-weight.ll
index e8b416845ec..1abcd03ac64 100644
--- a/llvm/test/CodeGen/X86/catchpad-weight.ll
+++ b/llvm/test/CodeGen/X86/catchpad-weight.ll
@@ -2,7 +2,7 @@
; Check if the edge weight to the catchpad is calculated correctly.
-; CHECK: Successors according to CFG: BB#3(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#4(0x00000400 / 0x80000000 = 0.00%) BB#6(0x00000200 / 0x80000000 = 0.00%) BB#8(0x00000100 / 0x80000000 = 0.00%)
+; CHECK: Successors according to CFG: BB#2(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#3(0x00000400 / 0x80000000 = 0.00%) BB#4(0x00000200 / 0x80000000 = 0.00%) BB#5(0x00000100 / 0x80000000 = 0.00%)
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--windows-msvc18.0.0"
@@ -31,11 +31,11 @@ entry:
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %1 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
- to label %catch.5 unwind label %catch.dispatch.1
+ %cs1 = catchswitch within none [label %catch.5] unwind label %catch.dispatch.1
catch.5: ; preds = %catch.dispatch
- catchret %1 to label %try.cont
+ %1 = catchpad within %cs1 [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
+ catchret from %1 to label %try.cont
try.cont: ; preds = %entry, %catch, %catch.3, %catch.5
call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
@@ -43,26 +43,23 @@ try.cont: ; preds = %entry, %catch, %cat
ret i32 0
catch.dispatch.1: ; preds = %catch.dispatch
- %2 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
- to label %catch.3 unwind label %catch.dispatch.2
+ %cs2 = catchswitch within none [label %catch.3] unwind label %catch.dispatch.2
catch.3: ; preds = %catch.dispatch.1
- catchret %2 to label %try.cont
+ %2 = catchpad within %cs2 [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
+ catchret from %2 to label %try.cont
catch.dispatch.2: ; preds = %catch.dispatch.1
- %3 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+ %cs3 = catchswitch within none [label %catch] unwind label %ehcleanup
catch: ; preds = %catch.dispatch.2
- catchret %3 to label %try.cont
-
-catchendblock: ; preds = %catch.dispatch.2
- catchendpad unwind label %ehcleanup
+ %3 = catchpad within %cs3 [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
+ catchret from %3 to label %try.cont
ehcleanup: ; preds = %catchendblock
- %4 = cleanuppad []
+ %4 = cleanuppad within none []
call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
- cleanupret %4 unwind to caller
+ cleanupret from %4 unwind to caller
}
; Function Attrs: nounwind argmemonly
diff --git a/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll b/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
index 3b3b3f5d091..585f7bc33e3 100644
--- a/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
+++ b/llvm/test/CodeGen/X86/catchret-empty-fallthrough.ll
@@ -19,14 +19,11 @@ try: ; preds = %entry
to label %fallthrough unwind label %dispatch
dispatch: ; preds = %try
- %0 = catchpad [i8* null]
- to label %catch unwind label %catchendblock.i.i
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %dispatch
- catchret %0 to label %return
-
-catchendblock.i.i: ; preds = %dispatch
- catchendpad unwind to caller
+ %0 = catchpad within %cs1 [i8* null]
+ catchret from %0 to label %return
fallthrough: ; preds = %try
unreachable
diff --git a/llvm/test/CodeGen/X86/catchret-fallthrough.ll b/llvm/test/CodeGen/X86/catchret-fallthrough.ll
index f732566d0cb..6a94b290e82 100644
--- a/llvm/test/CodeGen/X86/catchret-fallthrough.ll
+++ b/llvm/test/CodeGen/X86/catchret-fallthrough.ll
@@ -18,14 +18,11 @@ entry:
to label %invoke.cont.3 unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
- catchret %0 to label %nrvo.skipdtor
-
-catchendblock: ; preds = %catch, %catch.dispatch
- catchendpad unwind to caller
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %0 to label %nrvo.skipdtor
invoke.cont.3: ; preds = %entry
store i32 123, i32* @some_global
diff --git a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
index 8858f3704a1..294ef3abc46 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
@@ -29,9 +29,9 @@ invoke.cont: ; preds = %entry
ret void
ehcleanup: ; preds = %entry
- %2 = cleanuppad []
+ %2 = cleanuppad within none []
call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0)
- cleanupret %2 unwind to caller
+ cleanupret from %2 unwind to caller
}
; CHECK: _passes_two:
diff --git a/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll b/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
index df866f9598a..e32cdbed73f 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-large-codemodel.ll
@@ -9,9 +9,9 @@ entry:
invoke void @bar()
to label %exit unwind label %cleanup
cleanup:
- %c = cleanuppad []
+ %c = cleanuppad within none []
call void @bar()
- cleanupret %c unwind to caller
+ cleanupret from %c unwind to caller
exit:
ret void
}
diff --git a/llvm/test/CodeGen/X86/cleanuppad-realign.ll b/llvm/test/CodeGen/X86/cleanuppad-realign.ll
index a19cf261307..d322932da4c 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-realign.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-realign.ll
@@ -17,9 +17,9 @@ invoke.cont: ; preds = %entry
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call void @Dtor(i64* %o)
- cleanupret %0 unwind to caller
+ cleanupret from %0 unwind to caller
}
; X86-LABEL: _realigned_cleanup: # @realigned_cleanup
diff --git a/llvm/test/CodeGen/X86/funclet-layout.ll b/llvm/test/CodeGen/X86/funclet-layout.ll
index 053d484889b..b5972df43cc 100644
--- a/llvm/test/CodeGen/X86/funclet-layout.ll
+++ b/llvm/test/CodeGen/X86/funclet-layout.ll
@@ -15,21 +15,21 @@ entry:
to label %unreachable unwind label %catch.dispatch
catch.dispatch:
- %cp = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
- br i1 %B, label %catchret, label %catch
+ %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ br label %catch.loop
+
+catch.loop:
+ br i1 %B, label %catchret, label %catch.loop
catchret:
- catchret %cp to label %try.cont
+ catchret from %cp to label %try.cont
try.cont:
ret void
-catchendblock:
- catchendpad unwind to caller
-
unreachable:
unreachable
}
@@ -55,54 +55,50 @@ entry:
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
to label %unreachable unwind label %catch.dispatch.1
catch.dispatch.1: ; preds = %catch
- %1 = catchpad [i8* null, i32 64, i8* null]
- to label %catch.3 unwind label %catchendblock.2
+ %cs2 = catchswitch within %0 [label %catch.3] unwind to caller
catch.3: ; preds = %catch.dispatch.1
- catchret %1 to label %try.cont
+ %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+ catchret from %1 to label %try.cont
try.cont: ; preds = %catch.3
- catchret %0 to label %try.cont.5
+ catchret from %0 to label %try.cont.5
try.cont.5: ; preds = %try.cont
ret i32 0
-catchendblock.2: ; preds = %catch.dispatch.1
- catchendpad unwind label %catchendblock
-
-catchendblock: ; preds = %catchendblock.2, %catch.dispatch
- catchendpad unwind to caller
-
unreachable: ; preds = %catch, %entry
unreachable
-
}
; CHECK-LABEL: test2:
-; The entry funclet contains %entry and %try.cont.5
+; The parent function contains %entry and %try.cont.5
+; CHECK: .seh_proc
; CHECK: # %entry
; CHECK: # %try.cont.5
; CHECK: retq
-; The outer catch funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The inner catch funclet contains %catch.3
+; CHECK: .seh_proc
+; CHECK: # %catch.3{{$}}
+; CHECK: retq
+
+; The outer catch funclet contains %catch
+; CHECK: .seh_proc
+; CHECK: # %catch{{$}}
; CHECK: callq _CxxThrowException
; CHECK: # %unreachable
; CHECK: ud2
-; The inner catch funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
-; CHECK: retq
-
define void @test3(i1 %V) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
@@ -110,24 +106,21 @@ entry:
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.2 unwind label %catch.dispatch.1
+ %cs1 = catchswitch within none [label %catch.2] unwind label %catch.dispatch.1
catch.2: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
tail call void @exit(i32 0) #2
unreachable
catch.dispatch.1: ; preds = %catch.dispatch
- %1 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs2 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch.1
+ %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
tail call void @exit(i32 0) #2
unreachable
-catchendblock: ; preds = %catch.dispatch.1
- catchendpad unwind to caller
-
try.cont: ; preds = %entry
br i1 %V, label %exit_one, label %exit_two
@@ -150,13 +143,13 @@ exit_two:
; CHECK-NOT: # exit_two
; CHECK: ud2
-; The catch(...) funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The catch(...) funclet contains %catch.2
+; CHECK: # %catch.2{{$}}
; CHECK: callq exit
; CHECK: ud2
-; The catch(int) funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
+; The catch(int) funclet contains %catch
+; CHECK: # %catch{{$}}
; CHECK: callq exit
; CHECK: ud2
diff --git a/llvm/test/CodeGen/X86/late-address-taken.ll b/llvm/test/CodeGen/X86/late-address-taken.ll
index 8f85393b67c..f98c53595ab 100644
--- a/llvm/test/CodeGen/X86/late-address-taken.ll
+++ b/llvm/test/CodeGen/X86/late-address-taken.ll
@@ -22,19 +22,17 @@ body:
invoke void @f()
to label %exit unwind label %catch.pad
catch.pad:
- %catch = catchpad [i32 33554467]
- 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
+ %catch = catchpad within %cs1 [i32 33554467]
+ catchret from %catch to label %exit
exit:
ret void
}
; CHECK-LABEL: catchret: # @catchret
; CHECK: [[Exit:^[^ :]+]]: # Block address taken
; CHECK-NEXT: # %exit
-; CHECK: # %catch.pad
+; CHECK: # %catch.body
; CHECK: .seh_endprolog
; CHECK: leaq [[Exit]](%rip), %rax
; CHECK: retq # CATCHRET
diff --git a/llvm/test/CodeGen/X86/seh-catch-all-win32.ll b/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
index 5d9d5038385..69afb1b9d9c 100644
--- a/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
+++ b/llvm/test/CodeGen/X86/seh-catch-all-win32.ll
@@ -22,16 +22,13 @@ entry:
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
- to label %__except unwind label %endpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %lpad
+ %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
%code = load i32, i32* %__exceptioncode, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
- catchret %p to label %__try.cont
-
-endpad: ; preds = %lpad
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
__try.cont: ; preds = %entry, %__except
ret i32 0
@@ -73,7 +70,7 @@ entry:
; CHECK: popl %edi
; CHECK: popl %ebx
; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad{{$}}
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except{{$}}
; stackrestore
; CHECK: movl -24(%ebp), %esp
; EH state -1
diff --git a/llvm/test/CodeGen/X86/seh-catch-all.ll b/llvm/test/CodeGen/X86/seh-catch-all.ll
index aa1b6e040ff..4463485f209 100644
--- a/llvm/test/CodeGen/X86/seh-catch-all.ll
+++ b/llvm/test/CodeGen/X86/seh-catch-all.ll
@@ -16,16 +16,13 @@ __try.cont:
ret i32 0
lpad:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catchall unwind label %endpad
+ %cs1 = catchswitch within none [label %catchall] unwind to caller
catchall:
+ %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
%code = call i32 @llvm.eh.exceptioncode(token %p)
call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
- catchret %p to label %__try.cont
-
-endpad:
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
}
; Check that we can get the exception code from eax to the printf.
@@ -33,7 +30,7 @@ endpad:
; CHECK-LABEL: main:
; CHECK: callq crash
; CHECK: retq
-; CHECK: .LBB0_2: # %lpad
+; CHECK: .LBB0_2: # %catchall
; CHECK: leaq str(%rip), %rcx
; CHECK: movl %eax, %edx
; CHECK: callq printf
diff --git a/llvm/test/CodeGen/X86/seh-catchpad.ll b/llvm/test/CodeGen/X86/seh-catchpad.ll
index 895dba883ae..a8be4ec1450 100644
--- a/llvm/test/CodeGen/X86/seh-catchpad.ll
+++ b/llvm/test/CodeGen/X86/seh-catchpad.ll
@@ -45,13 +45,6 @@ entry:
%call = invoke i32 @do_div(i32 1, i32 0) #4
to label %__try.cont.12 unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null]
- to label %__except unwind label %catchendblock
-
-__except: ; preds = %catch.dispatch
- catchret %0 to label %__except.2
-
__except.2: ; preds = %__except
%call4 = invoke i32 @do_div(i32 1, i32 0) #4
to label %invoke.cont.3 unwind label %ehcleanup
@@ -60,24 +53,6 @@ invoke.cont.3: ; preds = %__except.2
invoke fastcc void @"\01?fin$0@0@main@@"() #4
to label %__try.cont.12 unwind label %catch.dispatch.7
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.7
-
-ehcleanup: ; preds = %__except.2
- %1 = cleanuppad []
- invoke fastcc void @"\01?fin$0@0@main@@"() #4
- to label %invoke.cont.6 unwind label %ehcleanup.end
-
-invoke.cont.6: ; preds = %ehcleanup
- cleanupret %1 unwind label %catch.dispatch.7
-
-catch.dispatch.7: ; preds = %invoke.cont.3, %invoke.cont.6, %ehcleanup.end, %catchendblock
- %2 = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@main@@" to i8*)]
- to label %__except.ret unwind label %catchendblock.8
-
-__except.ret: ; preds = %catch.dispatch.7
- catchret %2 to label %__except.9
-
__except.9: ; preds = %__except.ret
%call11 = tail call i32 @puts(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @"\01??_C@_06IBDBCMGJ@caught?$AA@", i64 0, i64 0))
br label %__try.cont.12
@@ -85,11 +60,27 @@ __except.9: ; preds = %__except.ret
__try.cont.12: ; preds = %invoke.cont.3, %entry, %__except.9
ret i32 0
-catchendblock.8: ; preds = %catch.dispatch.7
- catchendpad unwind to caller
+catch.dispatch: ; preds = %entry
+ %cs1 = catchswitch within none [label %__except] unwind label %catch.dispatch.7
+
+__except: ; preds = %catch.dispatch
+ %cp1 = catchpad within %cs1 [i8* null]
+ catchret from %cp1 to label %__except.2
-ehcleanup.end: ; preds = %ehcleanup
- cleanupendpad %1 unwind label %catch.dispatch.7
+ehcleanup: ; preds = %__except.2
+ %cp2 = cleanuppad within none []
+ invoke fastcc void @"\01?fin$0@0@main@@"() #4
+ to label %invoke.cont.6 unwind label %catch.dispatch.7
+
+invoke.cont.6: ; preds = %ehcleanup
+ cleanupret from %cp2 unwind label %catch.dispatch.7
+
+catch.dispatch.7:
+ %cs2 = catchswitch within none [label %__except.ret] unwind to caller
+
+__except.ret: ; preds = %catch.dispatch.7
+ %cp3 = catchpad within %cs2 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@main@@" to i8*)]
+ catchret from %cp3 to label %__except.9
}
; CHECK: main: # @main
@@ -112,7 +103,7 @@ ehcleanup.end: ; preds = %ehcleanup
; CHECK: addq $32, %rsp
; CHECK: popq %rbp
; CHECK: retq
-; CHECK: .LBB1_[[except1bb:[0-9]+]]: # %catch.dispatch
+; CHECK: .LBB1_[[except1bb:[0-9]+]]: # %__except
; CHECK: .Ltmp2:
; CHECK: movl $1, %ecx
; CHECK: xorl %edx, %edx
@@ -120,7 +111,7 @@ ehcleanup.end: ; preds = %ehcleanup
; CHECK: .Ltmp3:
; CHECK: callq "?fin$0@0@main@@"
; CHECK: jmp .LBB1_[[epilogue]]
-; CHECK: .LBB1_[[except2bb:[0-9]+]]: # %catch.dispatch.7
+; CHECK: .LBB1_[[except2bb:[0-9]+]]: # %__except.ret
; CHECK: leaq "??_C@_06IBDBCMGJ@caught?$AA@"(%rip), %rcx
; CHECK: callq puts
; CHECK: jmp .LBB1_[[epilogue]]
@@ -143,18 +134,18 @@ ehcleanup.end: ; preds = %ehcleanup
; CHECK-NEXT: .long .Ltmp2@IMGREL+1
; CHECK-NEXT: .long .Ltmp3@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
-; CHECK-NEXT: .long .LBB1_5@IMGREL
+; CHECK-NEXT: .long .LBB1_3@IMGREL
; CHECK-NEXT: .long .Ltmp6@IMGREL+1
; CHECK-NEXT: .long .Ltmp7@IMGREL+1
; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL
-; CHECK-NEXT: .long .LBB1_5@IMGREL
+; CHECK-NEXT: .long .LBB1_3@IMGREL
; CHECK-NEXT: .Llsda_end0:
; CHECK: .text
; CHECK: .seh_endproc
-; CHECK: "?dtor$3@?0?main@4HA":
-; CHECK: .seh_proc "?dtor$3@?0?main@4HA"
+; CHECK: "?dtor$[[finbb]]@?0?main@4HA":
+; CHECK: .seh_proc "?dtor$[[finbb]]@?0?main@4HA"
; CHECK: .seh_handler __C_specific_handler, @unwind, @except
; CHECK: .LBB1_[[finbb]]: # %ehcleanup
; CHECK: movq %rdx, 16(%rsp)
diff --git a/llvm/test/CodeGen/X86/seh-except-finally.ll b/llvm/test/CodeGen/X86/seh-except-finally.ll
index 7acb802aa68..b252b5b1248 100644
--- a/llvm/test/CodeGen/X86/seh-except-finally.ll
+++ b/llvm/test/CodeGen/X86/seh-except-finally.ll
@@ -49,37 +49,24 @@ invoke.cont2: ; preds = %invoke.cont
br label %__try.cont
__finally: ; preds = %entry
- %cleanuppad = cleanuppad []
+ %cleanuppad = cleanuppad within none []
%locals = call i8* @llvm.localaddress()
invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5
- to label %invoke.cont3 unwind label %cleanupendpad
+ to label %invoke.cont3 unwind label %catch.dispatch
invoke.cont3: ; preds = %__finally
- cleanupret %cleanuppad unwind label %catch.dispatch
-
-cleanupendpad:
- cleanupendpad %cleanuppad unwind label %catch.dispatch
+ cleanupret from %cleanuppad unwind label %catch.dispatch
catch.dispatch: ; preds = %invoke.cont3, %lpad1
- %catchpad = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
- to label %__except unwind label %catchendpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %catch.dispatch
+ %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
%call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
- catchret %catchpad to label %__try.cont
-
-catchendpad:
- catchendpad unwind to caller
+ catchret from %catchpad to label %__try.cont
__try.cont: ; preds = %__except, %invoke.cont2
ret void
-
-eh.resume: ; preds = %catch.dispatch
- %exn = load i8*, i8** %exn.slot
- %sel4 = load i32, i32* %ehselector.slot
- %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0
- %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %sel4, 1
- resume { i8*, i32 } %lpad.val5
}
; CHECK-LABEL: use_both:
diff --git a/llvm/test/CodeGen/X86/seh-exception-code.ll b/llvm/test/CodeGen/X86/seh-exception-code.ll
index e481a8e308c..20e1544e0b5 100644
--- a/llvm/test/CodeGen/X86/seh-exception-code.ll
+++ b/llvm/test/CodeGen/X86/seh-exception-code.ll
@@ -14,11 +14,11 @@ entry:
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %pad = catchpad [i8* null]
- to label %__except unwind label %catchendblock
+ %cs = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %catch.dispatch
- catchret %pad to label %__except.1
+ %pad = catchpad within %cs [i8* null]
+ catchret from %pad to label %__except.1
__except.1: ; preds = %__except
%code = call i32 @llvm.eh.exceptioncode(token %pad)
@@ -27,15 +27,12 @@ __except.1: ; preds = %__except
__try.cont: ; preds = %entry, %__except.1
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: ehcode:
; CHECK: xorl %ecx, %ecx
; CHECK: callq f
-; CHECK: # %catch.dispatch
+; CHECK: # %__except
; CHECK: movl %eax, %ecx
; CHECK-NEXT: callq f
diff --git a/llvm/test/CodeGen/X86/seh-finally.ll b/llvm/test/CodeGen/X86/seh-finally.ll
index 57c2c8c20f7..67bce81a66a 100644
--- a/llvm/test/CodeGen/X86/seh-finally.ll
+++ b/llvm/test/CodeGen/X86/seh-finally.ll
@@ -17,15 +17,9 @@ invoke.cont: ; preds = %entry
ret i32 0
lpad: ; preds = %entry
- %p = cleanuppad []
- %call2 = invoke i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
- to label %invoke.cont1 unwind label %endpad
-
-invoke.cont1: ; preds = %lpad
- cleanupret %p unwind to caller
-
-endpad: ; preds = %lpad
- cleanupendpad %p unwind to caller
+ %p = cleanuppad within none []
+ %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
+ cleanupret from %p unwind to caller
}
; X64-LABEL: main:
diff --git a/llvm/test/CodeGen/X86/seh-safe-div-win32.ll b/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
index 7f83b0c6466..3f88696fe60 100644
--- a/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
+++ b/llvm/test/CodeGen/X86/seh-safe-div-win32.ll
@@ -31,28 +31,22 @@ entry:
to label %__try.cont unwind label %lpad0
lpad0:
- %p0 = catchpad [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
- to label %handler0 unwind label %endpad0
+ %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
handler0:
+ %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- catchret %p0 to label %__try.cont
-
-endpad0:
- catchendpad unwind label %lpad1
+ catchret from %p0 to label %__try.cont
lpad1:
- %p1 = catchpad [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
- to label %handler1 unwind label %endpad1
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
handler1:
+ %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- catchret %p1 to label %__try.cont
-
-endpad1:
- catchendpad unwind to caller
+ catchret from %p1 to label %__try.cont
__try.cont:
%safe_ret = load i32, i32* %r, align 4
@@ -71,13 +65,13 @@ __try.cont:
; Landing pad code
-; CHECK: [[lpad0:LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:LBB0_[0-9]+]]: # %handler0
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
; CHECK: jmp [[cont_bb]]
-; CHECK: [[lpad1:LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:LBB0_[0-9]+]]: # %handler1
; Restore SP
; CHECK: movl {{.*}}(%ebp), %esp
; CHECK: calll _puts
@@ -87,10 +81,10 @@ __try.cont:
; CHECK: L__ehtable$safe_div:
; CHECK-NEXT: .long -1
; CHECK-NEXT: .long _safe_div_filt1
-; CHECK-NEXT: .long [[lpad1]]
+; CHECK-NEXT: .long [[handler1]]
; CHECK-NEXT: .long 0
; CHECK-NEXT: .long _safe_div_filt0
-; CHECK-NEXT: .long [[lpad0]]
+; CHECK-NEXT: .long [[handler0]]
define void @try_body(i32* %r, i32* %n, i32* %d) {
entry:
diff --git a/llvm/test/CodeGen/X86/seh-safe-div.ll b/llvm/test/CodeGen/X86/seh-safe-div.ll
index 1c7318b5614..3eeeab09ffb 100644
--- a/llvm/test/CodeGen/X86/seh-safe-div.ll
+++ b/llvm/test/CodeGen/X86/seh-safe-div.ll
@@ -30,28 +30,22 @@ entry:
to label %__try.cont unwind label %lpad0
lpad0:
- %p0 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
- to label %handler0 unwind label %endpad0
+ %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
handler0:
+ %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
store i32 -1, i32* %r, align 4
- catchret %p0 to label %__try.cont
-
-endpad0:
- catchendpad unwind label %lpad1
+ catchret from %p0 to label %__try.cont
lpad1:
- %p1 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
- to label %handler1 unwind label %endpad1
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
handler1:
+ %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
store i32 -2, i32* %r, align 4
- catchret %p1 to label %__try.cont
-
-endpad1:
- catchendpad unwind to caller
+ catchret from %p1 to label %__try.cont
__try.cont:
%safe_ret = load i32, i32* %r, align 4
@@ -73,12 +67,12 @@ __try.cont:
; Landing pad code
-; CHECK: [[lpad0:\.LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:\.LBB0_[0-9]+]]: # %handler0
; CHECK: callq puts
; CHECK: movl $-1, [[rloc]]
; CHECK: jmp [[cont_bb]]
-; CHECK: [[lpad1:\.LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:\.LBB0_[0-9]+]]: # %handler1
; CHECK: callq puts
; CHECK: movl $-2, [[rloc]]
; CHECK: jmp [[cont_bb]]
@@ -89,11 +83,11 @@ __try.cont:
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt0@IMGREL
-; CHECK-NEXT: .long [[lpad0]]@IMGREL
+; CHECK-NEXT: .long [[handler0]]@IMGREL
; CHECK-NEXT: .long .Ltmp0@IMGREL+1
; CHECK-NEXT: .long .Ltmp1@IMGREL+1
; CHECK-NEXT: .long safe_div_filt1@IMGREL
-; CHECK-NEXT: .long [[lpad1]]@IMGREL
+; CHECK-NEXT: .long [[handler1]]@IMGREL
; CHECK-NEXT: .Llsda_end0:
; CHECK: .text
; CHECK: .seh_endproc
diff --git a/llvm/test/CodeGen/X86/seh-stack-realign.ll b/llvm/test/CodeGen/X86/seh-stack-realign.ll
index 8494cadddb7..880533b4392 100644
--- a/llvm/test/CodeGen/X86/seh-stack-realign.ll
+++ b/llvm/test/CodeGen/X86/seh-stack-realign.ll
@@ -23,16 +23,13 @@ entry:
to label %__try.cont unwind label %lpad
lpad: ; preds = %entry
- %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
- to label %__except unwind label %endpad
+ %cs1 = catchswitch within none [label %__except] unwind to caller
__except: ; preds = %lpad
+ %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
%code = load i32, i32* %__exceptioncode, align 4
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
- catchret %p to label %__try.cont
-
-endpad:
- catchendpad unwind to caller
+ catchret from %p to label %__try.cont
__try.cont: ; preds = %entry, %__except
ret i32 0
@@ -63,7 +60,7 @@ entry:
; CHECK: movl $0, 40(%esi)
; CHECK: calll _crash
; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except
; Restore ESP
; CHECK: movl -24(%ebp), %esp
; Restore ESI
diff --git a/llvm/test/CodeGen/X86/tail-dup-catchret.ll b/llvm/test/CodeGen/X86/tail-dup-catchret.ll
index 18682fb690e..3eeb24d20f2 100644
--- a/llvm/test/CodeGen/X86/tail-dup-catchret.ll
+++ b/llvm/test/CodeGen/X86/tail-dup-catchret.ll
@@ -8,19 +8,16 @@ entry:
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
- catchret %0 to label %try.cont
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ catchret from %0 to label %try.cont
try.cont: ; preds = %entry, %catch
%b.0 = phi i1 [ false, %catch ], [ true, %entry ]
tail call void @h(i1 zeroext %b.0)
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: _f:
diff --git a/llvm/test/CodeGen/X86/tail-merge-wineh.ll b/llvm/test/CodeGen/X86/tail-merge-wineh.ll
index d0f6b72df24..69c2fda6949 100644
--- a/llvm/test/CodeGen/X86/tail-merge-wineh.ll
+++ b/llvm/test/CodeGen/X86/tail-merge-wineh.ll
@@ -54,11 +54,11 @@ entry:
to label %unreachable unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind label %catch.dispatch.7
catch: ; preds = %catch.dispatch
- catchret %1 to label %catchret.dest
+ %1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %1 to label %catchret.dest
catchret.dest: ; preds = %catch
br label %try.cont
@@ -70,11 +70,11 @@ try.cont: ; preds = %catchret.dest
to label %unreachable unwind label %catch.dispatch.2
catch.dispatch.2: ; preds = %try.cont
- %3 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.4 unwind label %catchendblock.3
+ %cs2 = catchswitch within none [label %catch.4] unwind label %catch.dispatch.7
catch.4: ; preds = %catch.dispatch.2
- catchret %3 to label %catchret.dest.5
+ %3 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %3 to label %catchret.dest.5
catchret.dest.5: ; preds = %catch.4
br label %try.cont.6
@@ -82,15 +82,12 @@ catchret.dest.5: ; preds = %catch.4
try.cont.6: ; preds = %catchret.dest.5
br label %try.cont.11
-catchendblock.3: ; preds = %catch.dispatch.2
- catchendpad unwind label %catch.dispatch.7
-
-catch.dispatch.7: ; preds = %catchendblock.3, %catchendblock
- %4 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.9 unwind label %catchendblock.8
+catch.dispatch.7:
+ %cs3 = catchswitch within none [label %catch.9] unwind to caller
catch.9: ; preds = %catch.dispatch.7
- catchret %4 to label %catchret.dest.10
+ %4 = catchpad within %cs3 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %4 to label %catchret.dest.10
catchret.dest.10: ; preds = %catch.9
br label %try.cont.11
@@ -98,12 +95,6 @@ catchret.dest.10: ; preds = %catch.9
try.cont.11: ; preds = %catchret.dest.10, %try.cont.6
ret void
-catchendblock.8: ; preds = %catch.dispatch.7
- catchendpad unwind to caller
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.7
-
unreachable: ; preds = %try.cont, %entry
unreachable
}
diff --git a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
index b6b4a9319b0..9f7a49536ca 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-csrs.ll
@@ -16,7 +16,7 @@ declare void @useints(...)
declare void @f(i32 %p)
declare i32 @__CxxFrameHandler3(...)
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
entry:
%a = call i32 @getint()
%b = call i32 @getint()
@@ -26,22 +26,16 @@ entry:
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
-
-catch:
- invoke void @f(i32 2)
- to label %invoke.cont.2 unwind label %catchendblock
-
-invoke.cont.2: ; preds = %catch
- catchret %0 to label %try.cont
-
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
+
+handler1:
+ %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ call void @f(i32 2)
+ catchret from %h1 to label %try.cont
}
; X86-LABEL: _try_catch_catch:
@@ -71,7 +65,7 @@ catchendblock: ; preds = %catch,
; X86: jmp [[contbb]]
; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
; X86: pushl %ebp
; X86-NOT: pushl
; X86: subl $16, %esp
@@ -120,7 +114,7 @@ catchendblock: ; preds = %catch,
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -159,18 +153,15 @@ entry:
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
-catch:
- catchret %0 to label %try.cont
+handler1:
+ %0 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %0 to label %try.cont
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
}
; X64-LABEL: try_one_csr:
@@ -198,7 +189,7 @@ catchendblock: ; preds = %catch,
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_one_csr@4HA":
-; X64: LBB1_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -226,18 +217,15 @@ entry:
invoke void @f(i32 1)
to label %try.cont unwind label %catch.dispatch
-catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %catchendblock
+catch.dispatch:
+ %cs = catchswitch within none [label %handler1] unwind to caller
-catch:
- catchret %0 to label %try.cont
+handler1:
+ %cp1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ catchret from %cp1 to label %try.cont
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch,
- catchendpad unwind to caller
}
; X64-LABEL: try_no_csr:
@@ -259,7 +247,7 @@ catchendblock: ; preds = %catch,
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_no_csr@4HA":
-; X64: LBB2_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB2_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
diff --git a/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
new file mode 100644
index 00000000000..22ce7e5cd87
--- /dev/null
+++ b/llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
@@ -0,0 +1,105 @@
+; RUN: llc -verify-machineinstrs -mtriple=i686-pc-windows-msvc < %s \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=X86 %s
+; RUN: llc -verify-machineinstrs -mtriple=x86_64-pc-windows-msvc < %s \
+; RUN: | FileCheck --check-prefix=CHECK --check-prefix=X64 %s
+
+; Loosely based on IR for this C++ source code:
+; void f(int p);
+; void try_in_catch() {
+; try {
+; f(1);
+; } catch (...) {
+; try {
+; f(2);
+; } catch (...) {
+; f(3);
+; }
+; }
+; }
+
+declare void @f(i32 %p)
+declare i32 @__CxxFrameHandler3(...)
+
+define i32 @try_in_catch() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ invoke void @f(i32 1)
+ to label %try.cont unwind label %catch.dispatch.1
+try.cont:
+ ret i32 0
+
+catch.dispatch.1:
+ %cs1 = catchswitch within none [label %handler1] unwind to caller
+handler1:
+ %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ invoke void @f(i32 2)
+ to label %catchret1 unwind label %catch.dispatch.2
+catchret1:
+ catchret from %h1 to label %try.cont
+
+catch.dispatch.2:
+ %cs2 = catchswitch within %h1 [label %handler2] unwind to caller
+handler2:
+ %h2 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+ call void @f(i32 3)
+ catchret from %h2 to label %catchret1
+}
+
+; X86-LABEL: L__ehtable$try_in_catch:
+; X64-LABEL: $cppxdata$try_in_catch:
+; CHECK-NEXT: .long 429065506
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long ($stateUnwindMap$try_in_catch)
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long ($tryMap$try_in_catch)
+; ip2state num + ptr
+; X86-NEXT: .long 0
+; X86-NEXT: .long 0
+; X64-NEXT: .long 7
+; X64-NEXT: .long ($ip2state$try_in_catch)
+; unwindhelp offset
+; X64-NEXT: .long 40
+; CHECK-NEXT: .long 0
+; EHFlags
+; CHECK-NEXT: .long 1
+
+; CHECK: $tryMap$try_in_catch:
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long ($handlerMap$0$try_in_catch)
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long ($handlerMap$1$try_in_catch)
+
+; CHECK: $handlerMap$0$try_in_catch:
+; CHECK-NEXT: .long 64
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long "?catch${{[0-9]+}}@?0?try_in_catch@4HA"
+; X64-NEXT: .long 56
+
+; CHECK: $handlerMap$1$try_in_catch:
+; CHECK-NEXT: .long 64
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long "?catch${{[0-9]+}}@?0?try_in_catch@4HA"
+; X64-NEXT: .long 56
+
+; X64: $ip2state$try_in_catch:
+; X64-NEXT: .long .Lfunc_begin0@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp0@IMGREL+1
+; X64-NEXT: .long 0
+; X64-NEXT: .long .Ltmp1@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$2@?0?try_in_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp2@IMGREL+1
+; X64-NEXT: .long 2
+; X64-NEXT: .long .Ltmp3@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long "?catch$4@?0?try_in_catch@4HA"@IMGREL
+; X64-NEXT: .long 3
diff --git a/llvm/test/CodeGen/X86/win-catchpad-nested.ll b/llvm/test/CodeGen/X86/win-catchpad-nested.ll
index 25adfdf8c80..d20f9f69a5e 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-nested.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-nested.ll
@@ -7,26 +7,25 @@ declare void @f()
define void @test1() personality void ()* @ProcessCLRException {
entry:
invoke void @f()
- to label %exit unwind label %outer.pad
-outer.pad:
- %outer = catchpad [i32 1]
- to label %outer.catch unwind label %outer.end
+ to label %exit unwind label %catch.dispatch.1
+exit:
+ ret void
+
+catch.dispatch.1:
+ %cs1 = catchswitch within none [label %outer.catch] unwind to caller
+
outer.catch:
+ %cp1 = catchpad within %cs1 [i32 1]
invoke void @f()
- to label %outer.ret unwind label %inner.pad
-inner.pad:
- %inner = catchpad [i32 2]
- to label %inner.ret unwind label %inner.end
-inner.ret:
- catchret %inner to label %outer.ret
-inner.end:
- catchendpad unwind label %outer.end
+ to label %outer.ret unwind label %catch.dispatch.2
outer.ret:
- catchret %outer to label %exit
-outer.end:
- catchendpad unwind to caller
-exit:
- ret void
+ catchret from %cp1 to label %exit
+
+catch.dispatch.2:
+ %cs2 = catchswitch within %cp1 [label %inner.catch] unwind to caller
+inner.catch:
+ %cp2 = catchpad within %cs2 [i32 2]
+ catchret from %cp2 to label %outer.ret
}
; Check the catchret targets
@@ -37,7 +36,7 @@ exit:
; CHECK-NEXT: # %outer.ret
; CHECK-NEXT: leaq [[Exit]](%rip), %rax
; CHECK: retq # CATCHRET
-; CHECK: {{^[^: ]+}}: # %inner.pad
+; CHECK: {{^[^: ]+}}: # %inner.catch
; CHECK: .seh_endprolog
; CHECK-NEXT: leaq [[OuterRet]](%rip), %rax
; CHECK: retq # CATCHRET
diff --git a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
index a2988a3059e..6508f3bd7d6 100644
--- a/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad-varargs.ll
@@ -13,20 +13,17 @@ entry:
to label %return unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
%ap1 = bitcast i8** %ap to i8*
call void @llvm.va_start(i8* %ap1)
%argp.cur = load i8*, i8** %ap
%1 = bitcast i8* %argp.cur to i32*
%arg2 = load i32, i32* %1
call void @llvm.va_end(i8* %ap1)
- catchret %0 to label %return
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
+ catchret from %0 to label %return
return: ; preds = %entry, %catch
%retval.0 = phi i32 [ %arg2, %catch ], [ -1, %entry ]
diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll
index d9c8307cb08..5bd25046130 100644
--- a/llvm/test/CodeGen/X86/win-catchpad.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad.ll
@@ -28,7 +28,7 @@ declare void @f(i32 %p, i32* %l)
declare i1 @getbool()
declare i32 @__CxxFrameHandler3(...)
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
entry:
%e.addr = alloca i32
%local = alloca i32
@@ -36,33 +36,21 @@ entry:
to label %try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
- to label %catch unwind label %catch.dispatch.2
+ %cs = catchswitch within none [label %handler1, label %handler2] unwind to caller
-catch: ; preds = %catch.dispatch
+handler1:
+ %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
%e = load i32, i32* %e.addr
- invoke void @f(i32 %e, i32* %local)
- to label %invoke.cont.2 unwind label %catchendblock
+ call void @f(i32 %e, i32* %local)
+ catchret from %h1 to label %try.cont
-invoke.cont.2: ; preds = %catch
- catchret %0 to label %try.cont
+handler2:
+ %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
+ call void @f(i32 3, i32* %local)
+ catchret from %h2 to label %try.cont
-catch.dispatch.2: ; preds = %catch.dispatch
- %1 = catchpad [i8* null, i32 u0x40, i8* null]
- to label %catch.2 unwind label %catchendblock
-
-catch.2: ; preds = %catch.dispatch.2
- invoke void @f(i32 3, i32* %local)
- to label %invoke.cont.3 unwind label %catchendblock
-
-invoke.cont.3: ; preds = %catch.2
- catchret %1 to label %try.cont
-
-try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
ret i32 0
-
-catchendblock: ; preds = %catch, %catch.2, %catch.dispatch.2
- catchendpad unwind to caller
}
; X86-LABEL: _try_catch_catch:
@@ -76,25 +64,25 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X86: retl
; X86: [[restorebb1:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT: # %invoke.cont.2
+; X86-NEXT: # %handler1
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
; FIXME: These should be de-duplicated.
; X86: [[restorebb2:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT: # %invoke.cont.3
+; X86-NEXT: # %handler2
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl -32(%ebp), %[[e_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: movl -32(%ebp), %[[e_reg:[a-z]+]]
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
; X86-DAG: movl %[[addr_reg]], 4(%esp)
; X86-DAG: movl %[[e_reg]], (%esp)
; X86: calll _f
@@ -104,13 +92,13 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X86-NEXT: retl
; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X86: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X86: LBB0_[[catch2bb]]: # %handler2{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
; X86-DAG: movl %[[addr_reg]], 4(%esp)
; X86-DAG: movl $3, (%esp)
; X86: calll _f
@@ -151,7 +139,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64: retq
; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -159,7 +147,6 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64: .seh_stackalloc 32
; X64: leaq 48(%rdx), %rbp
; X64: .seh_endprologue
-; X64-DAG: .Ltmp4
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
; X64-DAG: movl -12(%rbp), %ecx
; X64: callq f
@@ -169,7 +156,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64-NEXT: retq
; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch@4HA":
-; X64: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X64: LBB0_[[catch2bb]]: # %handler2{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -180,7 +167,6 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
; X64-DAG: movl $3, %ecx
; X64: callq f
-; X64: .Ltmp3
; X64: leaq [[contbb]](%rip), %rax
; X64-NEXT: addq $32, %rsp
; X64-NEXT: popq %rbp
@@ -192,7 +178,7 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64-NEXT: .long ($stateUnwindMap$try_catch_catch)@IMGREL
; X64-NEXT: .long 1
; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL
-; X64-NEXT: .long 4
+; X64-NEXT: .long 5
; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL
; X64-NEXT: .long 40
; X64-NEXT: .long 0
@@ -222,33 +208,35 @@ catchendblock: ; preds = %catch, %catch.2, %c
; X64-NEXT: .long -1
; X64-NEXT: .long .Ltmp0@IMGREL+1
; X64-NEXT: .long 0
-; X64-NEXT: .long .Ltmp4@IMGREL+1
-; X64-NEXT: .long 1
-; X64-NEXT: .long .Ltmp3@IMGREL+1
+; X64-NEXT: .long .Ltmp1@IMGREL+1
; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
+; X64-NEXT: .long "?catch$[[catch2bb]]@?0?try_catch_catch@4HA"@IMGREL
+; X64-NEXT: .long 1
-define i32 @branch_to_normal_dest() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 {
entry:
invoke void @f(i32 1, i32* null)
to label %try.cont unwind label %catch.dispatch
catch.dispatch:
- %0 = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
+ %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+ br label %loop
+
+loop:
%V = call i1 @getbool()
- br i1 %V, label %catch, label %catch.done
+ br i1 %V, label %loop, label %catch.done
catch.done:
- catchret %0 to label %try.cont
+ catchret from %cp1 to label %try.cont
try.cont:
ret i32 0
-
-catchendblock:
- catchendpad unwind to caller
}
; X86-LABEL: _branch_to_normal_dest:
@@ -262,17 +250,16 @@ catchendblock:
; X86-NEXT: addl $12, %ebp
; X86: jmp [[contbb]]
-; X86: "?catch$[[catchdispbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
-; X86: LBB1_[[catchdispbb]]: # %catch.dispatch{{$}}
+; X86: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
+; X86: LBB1_[[catchbb]]: # %catch{{$}}
; X86: pushl %ebp
; X86: subl $8, %esp
; X86: addl $12, %ebp
-
-; X86: LBB1_[[catchbb:[0-9]+]]: # %catch
-; X86: movl $-1, -16(%ebp)
+; X86: LBB1_[[loopbb:[0-9]+]]: # %loop
+; X86: movl $1, -16(%ebp)
; X86: calll _getbool
; X86: testb $1, %al
-; X86: jne LBB1_[[catchbb]]
+; X86: jne LBB1_[[loopbb]]
; X86: # %catch.done
; X86-NEXT: movl $[[restorebb]], %eax
; X86-NEXT: addl $8, %esp
@@ -284,7 +271,7 @@ catchendblock:
; X86-NEXT: .long 64
; X86-NEXT: .long 0
; X86-NEXT: .long 0
-; X86-NEXT: .long "?catch$[[catchdispbb]]@?0?branch_to_normal_dest@4HA"
+; X86-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"
; X64-LABEL: branch_to_normal_dest:
; X64: # %entry
@@ -305,7 +292,7 @@ catchendblock:
; X64: retq
; X64: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest@4HA":
-; X64: LBB1_[[catchbb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catchbb]]: # %catch{{$}}
; X64: movq %rdx, 16(%rsp)
; X64: pushq %rbp
; X64: .seh_pushreg 5
@@ -313,7 +300,7 @@ catchendblock:
; X64: .seh_stackalloc 32
; X64: leaq 48(%rdx), %rbp
; X64: .seh_endprologue
-; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %catch
+; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %loop
; X64: callq getbool
; X64: testb $1, %al
; X64: jne .LBB1_[[normal_dest_bb]]
@@ -329,7 +316,7 @@ catchendblock:
; X64-NEXT: .long ($stateUnwindMap$branch_to_normal_dest)@IMGREL
; X64-NEXT: .long 1
; X64-NEXT: .long ($tryMap$branch_to_normal_dest)@IMGREL
-; X64-NEXT: .long 3
+; X64-NEXT: .long 4
; X64-NEXT: .long ($ip2state$branch_to_normal_dest)@IMGREL
; X64-NEXT: .long 40
; X64-NEXT: .long 0
@@ -362,3 +349,5 @@ catchendblock:
; X64-NEXT: .long 0
; X64-NEXT: .long .Ltmp[[after_call]]@IMGREL+1
; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch$[[catchbb]]@?0?branch_to_normal_dest@4HA"@IMGREL
+; X64-NEXT: .long 1
diff --git a/llvm/test/CodeGen/X86/win-cleanuppad.ll b/llvm/test/CodeGen/X86/win-cleanuppad.ll
index 27bb6e2abed..37090c2f6bc 100644
--- a/llvm/test/CodeGen/X86/win-cleanuppad.ll
+++ b/llvm/test/CodeGen/X86/win-cleanuppad.ll
@@ -14,9 +14,9 @@ invoke.cont: ; preds = %entry
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2
- cleanupret %0 unwind to caller
+ cleanupret from %0 unwind to caller
}
; CHECK: simple_cleanup: # @simple_cleanup
@@ -77,14 +77,14 @@ invoke.cont.2: ; preds = %invoke.cont.1
ret void
cleanup.inner: ; preds = %invoke.cont
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2
- cleanupret %0 unwind label %cleanup.outer
+ cleanupret from %0 unwind label %cleanup.outer
cleanup.outer: ; preds = %invoke.cont.1, %cleanup.inner, %entry
- %1 = cleanuppad []
+ %1 = cleanuppad within none []
call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2
- cleanupret %1 unwind to caller
+ cleanupret from %1 unwind to caller
}
; X86-LABEL: _nested_cleanup:
diff --git a/llvm/test/CodeGen/X86/win-funclet-cfi.ll b/llvm/test/CodeGen/X86/win-funclet-cfi.ll
index 52589ee1918..95afa75a709 100644
--- a/llvm/test/CodeGen/X86/win-funclet-cfi.ll
+++ b/llvm/test/CodeGen/X86/win-funclet-cfi.ll
@@ -9,24 +9,21 @@ entry:
to label %unreachable unwind label %cleanupblock
cleanupblock:
- %cleanp = cleanuppad []
+ %cleanp = cleanuppad within none []
call void @g()
- cleanupret %cleanp unwind label %catch.dispatch
+ cleanupret from %cleanp unwind label %catch.dispatch
catch.dispatch:
- %cp = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %catchendblock
+ %cs1 = catchswitch within none [label %catch] unwind to caller
catch:
+ %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
call void @g()
- catchret %cp to label %try.cont
+ catchret from %cp to label %try.cont
try.cont:
ret void
-catchendblock:
- catchendpad unwind to caller
-
unreachable:
unreachable
}
@@ -70,7 +67,7 @@ declare i32 @__CxxFrameHandler3(...)
; CHECK: "?catch$[[catch:[0-9]+]]@?0??f@@YAXXZ@4HA":
; CHECK: .seh_proc "?catch$[[catch]]@?0??f@@YAXXZ@4HA"
; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except
-; CHECK: LBB0_[[catch]]: # %catch.dispatch{{$}}
+; CHECK: LBB0_[[catch]]: # %catch{{$}}
; Emit CFI for pushing RBP.
; CHECK: movq %rdx, 16(%rsp)
diff --git a/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll b/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
index 9b6916554e5..f7b6d0702eb 100644
--- a/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
+++ b/llvm/test/CodeGen/X86/win-mixed-ehpersonality.ll
@@ -18,12 +18,10 @@ cont:
ret i32 0
lpad:
- %p = catchpad [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %ret1
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
+ catchret from %p to label %ret1
ret1:
ret i32 1
@@ -39,7 +37,7 @@ define internal i32 @filt_g(i8*, i8*) {
; CHECK: xorl %eax, %eax
; CHECK: .LBB0_[[epilogue:[0-9]+]]
; CHECK: retq
-; CHECK: # %lpad
+; CHECK: # %catch{{$}}
; CHECK: movl $1, %eax
; CHECK: jmp .LBB0_[[epilogue]]
diff --git a/llvm/test/CodeGen/X86/win32-eh-states.ll b/llvm/test/CodeGen/X86/win32-eh-states.ll
index cb7b053e14d..fe3639b97a4 100644
--- a/llvm/test/CodeGen/X86/win32-eh-states.ll
+++ b/llvm/test/CodeGen/X86/win32-eh-states.ll
@@ -1,4 +1,5 @@
-; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
+; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s --check-prefix=X64
; Based on this source:
; extern "C" void may_throw(int);
@@ -40,59 +41,167 @@ invoke.cont: ; preds = %entry
to label %try.cont.9 unwind label %lpad
try.cont.9: ; preds = %invoke.cont.3, %invoke.cont, %catch.7
- ; FIXME: Something about our CFG breaks TailDuplication. This empy asm blocks
- ; it so we can focus on testing the state numbering.
- call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
ret void
lpad: ; preds = %catch, %entry
- %p1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch unwind label %end.inner.catch
+ %cs1 = catchswitch within none [label %catch] unwind label %lpad.1
catch: ; preds = %lpad.1
+ %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
invoke void @may_throw(i32 3)
- to label %invoke.cont.3 unwind label %end.inner.catch
+ to label %invoke.cont.3 unwind label %lpad.1
invoke.cont.3: ; preds = %catch
- catchret %p1 to label %try.cont.9
-
-
-end.inner.catch:
- catchendpad unwind label %lpad.1
+ catchret from %p1 to label %try.cont.9
lpad.1: ; preds = %invoke.cont
- %p2 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
- to label %catch.7 unwind label %eh.resume
+ %cs2 = catchswitch within none [label %catch.7] unwind to caller
catch.7:
- invoke void @may_throw(i32 4)
- to label %invoke.cont.10 unwind label %eh.resume
+ %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+ call void @may_throw(i32 4)
+ catchret from %p2 to label %try.cont.9
+}
+
+; X86-LABEL: _f:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$f, {{.*}}
+;
+; X86: movl $0, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $3, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $4, (%esp)
+; X86: calll _may_throw
+
+
+; X64-LABEL: f:
+; X64-LABEL: $ip2state$f:
+; X64-NEXT: .long .Lfunc_begin0@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 0
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch${{.*}}@?0?f@4HA"@IMGREL
+; X64-NEXT: .long 2
+; X64-NEXT: .long "?catch${{.*}}@?0?f@4HA"@IMGREL
+; X64-NEXT: .long 3
+
+; Based on this source:
+; extern "C" void may_throw(int);
+; struct S { ~S(); };
+; void g() {
+; S x;
+; try {
+; may_throw(-1);
+; } catch (...) {
+; may_throw(0);
+; {
+; S y;
+; may_throw(1);
+; }
+; may_throw(2);
+; }
+; }
-invoke.cont.10:
- catchret %p2 to label %try.cont.9
+%struct.S = type { i8 }
+declare void @"\01??1S@@QEAA@XZ"(%struct.S*)
-eh.resume: ; preds = %catch.dispatch.4
- catchendpad unwind to caller
+define void @g() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ %x = alloca %struct.S, align 1
+ %y = alloca %struct.S, align 1
+ invoke void @may_throw(i32 -1)
+ to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch: ; preds = %entry
+ %0 = catchswitch within none [label %catch] unwind label %ehcleanup5
+
+catch: ; preds = %catch.dispatch
+ %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+ invoke void @may_throw(i32 0)
+ to label %invoke.cont unwind label %ehcleanup5
+
+invoke.cont: ; preds = %catch
+ invoke void @may_throw(i32 1)
+ to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2: ; preds = %invoke.cont
+ invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+ to label %invoke.cont3 unwind label %ehcleanup5
+
+invoke.cont3: ; preds = %invoke.cont2
+ invoke void @may_throw(i32 2)
+ to label %invoke.cont4 unwind label %ehcleanup5
+
+invoke.cont4: ; preds = %invoke.cont3
+ catchret from %1 to label %try.cont
+
+try.cont: ; preds = %invoke.cont4
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
+ ret void
+
+ehcleanup: ; preds = %invoke.cont
+ %2 = cleanuppad within %1 []
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+ cleanupret from %2 unwind label %ehcleanup5
+
+ehcleanup5: ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
+ %3 = cleanuppad within none []
+ call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
+ cleanupret from %3 unwind to caller
+
+unreachable: ; preds = %entry
+ unreachable
}
-; CHECK-LABEL: _f:
-; CHECK: movl $-1, [[state:[-0-9]+]](%ebp)
-; CHECK: movl $___ehhandler$f, {{.*}}
+; X86-LABEL: _g:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$g, {{.*}}
;
-; CHECK: movl $0, [[state]](%ebp)
-; CHECK: movl $1, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $-1, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $1, [[state]](%ebp)
-; CHECK: movl $2, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $0, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $2, [[state]](%ebp)
-; CHECK: movl $3, (%esp)
-; CHECK: calll _may_throw
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
;
-; CHECK: movl $3, [[state]](%ebp)
-; CHECK: movl $4, (%esp)
-; CHECK: calll _may_throw
-
-; CHECK: .safeseh ___ehhandler$f
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
+
+; X64-LABEL: g:
+; X64-LABEL: $ip2state$g:
+; X64-NEXT: .long .Lfunc_begin1@IMGREL
+; X64-NEXT: .long -1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 1
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long -1
+; X64-NEXT: .long "?catch${{.*}}@?0?g@4HA"@IMGREL
+; X64-NEXT: .long 2
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 3
+; X64-NEXT: .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT: .long 2
+
+
+; X86: .safeseh ___ehhandler$f
+; X86: .safeseh ___ehhandler$g
diff --git a/llvm/test/CodeGen/X86/win32-eh.ll b/llvm/test/CodeGen/X86/win32-eh.ll
index 87926a463f7..73c7b486a55 100644
--- a/llvm/test/CodeGen/X86/win32-eh.ll
+++ b/llvm/test/CodeGen/X86/win32-eh.ll
@@ -19,12 +19,10 @@ entry:
cont:
ret void
lpad:
- %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_except_handler3:
@@ -45,7 +43,7 @@ endpad:
; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
; CHECK: movl %[[next]], %fs:0
; CHECK: retl
-; CHECK: LBB1_2: # %lpad{{$}}
+; CHECK: LBB1_2: # %catch{{$}}
; CHECK: .section .xdata,"dr"
; CHECK-LABEL: L__ehtable$use_except_handler3:
@@ -60,12 +58,10 @@ entry:
cont:
ret void
lpad:
- %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
- to label %catch unwind label %endpad
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-endpad:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_except_handler4:
@@ -86,7 +82,7 @@ endpad:
; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
; CHECK: movl %[[next]], %fs:0
; CHECK: retl
-; CHECK: LBB2_2: # %lpad{{$}}
+; CHECK: LBB2_2: # %catch{{$}}
; CHECK: .section .xdata,"dr"
; CHECK-LABEL: L__ehtable$use_except_handler4:
@@ -105,14 +101,10 @@ cont:
ret void
catchall:
- %p = catchpad [i8* null, i32 64, i8* null]
- to label %catch unwind label %endcatch
-
+ %cs = catchswitch within none [label %catch] unwind to caller
catch:
- catchret %p to label %cont
-
-endcatch:
- catchendpad unwind to caller
+ %p = catchpad within %cs [i8* null, i32 64, i8* null]
+ catchret from %p to label %cont
}
; CHECK-LABEL: _use_CxxFrameHandler3:
diff --git a/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll b/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
index 24db1649eb8..23aeea37c11 100644
--- a/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-catchpad-realign.ll
@@ -15,17 +15,14 @@ entry:
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %pad = catchpad [i8* bitcast (i32 ()* @"\01?filt$0@0@realigned_try@@" to i8*)]
- to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
- catchret %pad to label %__try.cont
+ %pad = catchpad within %cs1 [i8* bitcast (i32 ()* @"\01?filt$0@0@realigned_try@@" to i8*)]
+ catchret from %pad to label %__try.cont
__try.cont: ; preds = %entry, %__except.ret
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; Function Attrs: nounwind argmemonly
@@ -69,7 +66,7 @@ declare i32 @_except_handler3(...)
; CHECK: popl %ebp
; CHECK: retl
;
-; CHECK: LBB0_1: # %catch.dispatch
+; CHECK: LBB0_1: # %__except.ret
; Restore ESP
; CHECK: movl -24(%ebp), %esp
; Recompute ESI by subtracting 60 from the end of the registration node.
diff --git a/llvm/test/CodeGen/X86/win32-seh-catchpad.ll b/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
index 4e373af23e4..88dea367572 100644
--- a/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-catchpad.ll
@@ -11,10 +11,11 @@ entry:
to label %invoke.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
- catchret %0 to label %__except
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
+ catchret from %0 to label %__except
__except: ; preds = %__except.ret
call void @f(i32 2)
@@ -24,9 +25,6 @@ __try.cont: ; preds = %__except, %invoke.c
call void @f(i32 3)
ret void
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
-
invoke.cont: ; preds = %entry
br label %__try.cont
}
@@ -77,81 +75,69 @@ entry:
to label %__try.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
__except.ret: ; preds = %catch.dispatch
- catchret %0 to label %__try.cont
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %0 to label %__try.cont
__try.cont: ; preds = %entry, %__except.ret
invoke void @crash() #3
to label %__try.cont.9 unwind label %catch.dispatch.5
catch.dispatch.5: ; preds = %__try.cont
- %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
+ %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
__except.ret.7: ; preds = %catch.dispatch.5
- catchret %1 to label %__try.cont.9
+ %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %1 to label %__try.cont.9
__try.cont.9: ; preds = %__try.cont, %__except.ret.7
invoke void @crash() #3
to label %__try.cont.15 unwind label %catch.dispatch.11
catch.dispatch.11: ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
- %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
+ %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
__except.ret.13: ; preds = %catch.dispatch.11
- catchret %2 to label %__try.cont.15
+ %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %2 to label %__try.cont.15
__try.cont.15: ; preds = %__try.cont.9, %__except.ret.13
invoke void @crash() #3
to label %__try.cont.35 unwind label %catch.dispatch.17
catch.dispatch.17: ; preds = %catchendblock.12, %__try.cont.15
- %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
+ %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
__except.ret.19: ; preds = %catch.dispatch.17
- catchret %3 to label %__except.20
+ %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %3 to label %__except.20
__except.20: ; preds = %__except.ret.19
invoke void @crash() #3
to label %__try.cont.27 unwind label %catch.dispatch.23
catch.dispatch.23: ; preds = %__except.20
- %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
+ %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
__except.ret.25: ; preds = %catch.dispatch.23
- catchret %4 to label %__try.cont.27
+ %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %4 to label %__try.cont.27
__try.cont.27: ; preds = %__except.20, %__except.ret.25
invoke void @crash() #3
to label %__try.cont.35 unwind label %catch.dispatch.30
catch.dispatch.30: ; preds = %__try.cont.27
- %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
+ %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
__except.ret.32: ; preds = %catch.dispatch.30
- catchret %5 to label %__try.cont.35
+ %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+ catchret from %5 to label %__try.cont.35
__try.cont.35: ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
ret void
-
-catchendblock.31: ; preds = %catch.dispatch.30
- catchendpad unwind to caller
-
-catchendblock.24: ; preds = %catch.dispatch.23
- catchendpad unwind to caller
-
-catchendblock.18: ; preds = %catch.dispatch.17
- catchendpad unwind to caller
-
-catchendblock.12: ; preds = %catch.dispatch.11
- catchendpad unwind label %catch.dispatch.17
-
-catchendblock.6: ; preds = %catch.dispatch.5
- catchendpad unwind label %catch.dispatch.11
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind label %catch.dispatch.11
}
; This table is equivalent to the one produced by MSVC, even if it isn't in
@@ -162,19 +148,19 @@ catchendblock: ; preds = %catch.dispatch
; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long -1
+; CHECK: .long 0
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long -1
+; CHECK: .long 1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long 2
+; CHECK: .long 1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long 3
+; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
-; CHECK: .long 3
+; CHECK: .long -1
; CHECK: .long _nested_exceptions_filter_catchall
; CHECK: .long LBB
@@ -203,21 +189,19 @@ entry:
to label %__except unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
- %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+ %cs1 = catchswitch within none [label %__except.ret] unwind to caller
__except.ret: ; preds = %catch.dispatch
+ %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
call void @f(i32 2)
- catchret %0 to label %__except
+ catchret from %0 to label %__except
__except:
ret void
-
-catchendblock: ; preds = %catch.dispatch
- catchendpad unwind to caller
}
; CHECK-LABEL: _code_in_catchpad:
-; CHECK: # %catch.dispatch
+; CHECK: # %__except.ret
; CHECK-NEXT: movl -24(%ebp), %esp
; CHECK-NEXT: addl $12, %ebp
; CHECK-NEXT: movl $-1, -16(%ebp)
diff --git a/llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll b/llvm/test/CodeGen/X86/win32-seh-nested-finally.ll
index 35d9bfeb66e..c91a14278ec 100644
--- a/llvm/test/CodeGen/X86/win32-seh-cleanupendpad.ll
+++ b/llvm/test/CodeGen/X86/win32-seh-nested-finally.ll
@@ -17,26 +17,17 @@ invoke.cont.1: ; preds = %invoke.cont
ret void
ehcleanup: ; preds = %entry
- %0 = cleanuppad []
+ %0 = cleanuppad within none []
invoke void @f(i32 2) #3
- to label %invoke.cont.2 unwind label %ehcleanup.end
+ to label %invoke.cont.2 unwind label %ehcleanup.3
invoke.cont.2: ; preds = %ehcleanup
- cleanupret %0 unwind label %ehcleanup.3
-
-ehcleanup.end: ; preds = %ehcleanup
- cleanupendpad %0 unwind label %ehcleanup.3
+ cleanupret from %0 unwind label %ehcleanup.3
ehcleanup.3: ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
- %1 = cleanuppad []
- invoke void @f(i32 3) #3
- to label %invoke.cont.4 unwind label %ehcleanup.end.5
-
-invoke.cont.4: ; preds = %ehcleanup.3
- cleanupret %1 unwind to caller
-
-ehcleanup.end.5: ; preds = %ehcleanup.3
- cleanupendpad %1 unwind to caller
+ %1 = cleanuppad within none []
+ call void @f(i32 3) #3
+ cleanupret from %1 unwind to caller
}
declare void @f(i32) #0
diff --git a/llvm/test/CodeGen/WinEH/wineh-coreclr.ll b/llvm/test/CodeGen/X86/wineh-coreclr.ll
index 079993f74db..7bbc64ece8e 100644
--- a/llvm/test/CodeGen/WinEH/wineh-coreclr.ll
+++ b/llvm/test/CodeGen/X86/wineh-coreclr.ll
@@ -13,7 +13,7 @@ declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
; f(2);
; } catch (type1) {
; f(3);
-; } catch (type2) [
+; } catch (type2) {
; f(4);
; try {
; f(5);
@@ -50,10 +50,10 @@ inner_try:
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
+ %cs1 = catchswitch within none [label %catch1.body, label %catch2.body] unwind label %finally.pad
catch1.body:
+ %catch1 = catchpad within %cs1 [i32 1]
+; CHECK: .seh_proc [[L_catch1:[^ ]+]]
; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
; ^ all funclets use the same frame size
; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -71,14 +71,12 @@ catch1.body:
; CHECK-NEXT: callq f
; CHECK-NEXT: [[L_after_f3:.+]]:
invoke void @f(i32 3)
- to label %catch1.ret unwind label %catch.end
+ to label %catch1.ret unwind label %finally.pad
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
+ catchret from %catch1 to label %finally.clone
catch2.body:
+ %catch2 = catchpad within %cs1 [i32 2]
+; CHECK: .seh_proc [[L_catch2:[^ ]+]]
; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
; ^ all funclets use the same frame size
; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -96,7 +94,7 @@ catch2.body:
; CHECK-NEXT: callq f
; CHECK-NEXT: [[L_after_f4:.+]]:
invoke void @f(i32 4)
- to label %try_in_catch unwind label %catch.end
+ to label %try_in_catch unwind label %finally.pad
try_in_catch:
; CHECK: # %try_in_catch
; CHECK: [[L_before_f5:.+]]:
@@ -107,7 +105,7 @@ try_in_catch:
to label %catch2.ret unwind label %fault.pad
fault.pad:
; CHECK: .seh_proc [[L_fault:[^ ]+]]
- %fault = cleanuppad [i32 undef]
+ %fault = cleanuppad within none [i32 undef]
; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
; ^ all funclets use the same frame size
; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -120,21 +118,17 @@ fault.pad:
; CHECK-NEXT: callq f
; CHECK-NEXT: [[L_after_f6:.+]]:
invoke void @f(i32 6)
- to label %fault.ret unwind label %fault.end
+ to label %fault.ret unwind label %finally.pad
fault.ret:
- cleanupret %fault unwind label %catch.end
-fault.end:
- cleanupendpad %fault unwind label %catch.end
+ cleanupret from %fault unwind label %finally.pad
catch2.ret:
- catchret %catch2 to label %finally.clone
-catch.end:
- catchendpad unwind label %finally.pad
+ catchret from %catch2 to label %finally.clone
finally.clone:
call void @f(i32 7)
br label %tail
finally.pad:
; CHECK: .seh_proc [[L_finally:[^ ]+]]
- %finally = cleanuppad []
+ %finally = cleanuppad within none []
; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
; ^ all funclets use the same frame size
; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -142,136 +136,132 @@ finally.pad:
; 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
+ call void @f(i32 7)
+ cleanupret from %finally unwind to caller
tail:
call void @f(i32 8)
ret void
; CHECK: [[L_end:.*func_end.*]]:
}
+; FIXME: Verify that the new clauses are correct and re-enable these checks.
+
; Now check for EH table in xdata (following standard xdata)
-; CHECK-LABEL: .section .xdata
+; CHECKX-LABEL: .section .xdata
; standard xdata comes here
-; CHECK: .long 4{{$}}
+; CHECKX: .long 4{{$}}
; ^ number of funclets
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
; ^ offset from L_begin to start of 1st funclet
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
; ^ offset from L_begin to start of 2nd funclet
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
; ^ offset from L_begin to start of 3rd funclet
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset from L_begin to start of 4th funclet
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
; ^ offset from L_begin to end of last funclet
-; CHECK-NEXT: .long 7
+; CHECKX-NEXT: .long 7
; ^ number of EH clauses
; Clause 1: call f(2) is guarded by catch1
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
; ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 1
+; CHECKX-NEXT: .long 1
; ^ type token of catch (from catchpad)
; Clause 2: call f(2) is also guarded by catch2
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
; ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 2
+; CHECKX-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
+; CHECKX-NEXT: .long 2
; ^ flags (2 => finally handler)
-; CHECK-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-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
+; CHECKX-NEXT: .long 10
; ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
; ^ type token slot (null for finally)
; Clause 5: call f(5) is guarded by fault
-; CHECK-NEXT: .long 4
+; CHECKX-NEXT: .long 4
; ^ flags (4 => fault handler)
-; CHECK-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-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
+; CHECKX-NEXT: .long 10
; ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-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
+; CHECKX-NEXT: .long 10
; ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
; ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
; ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
; ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
; ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
; ^ type token slot (null for finally)
diff --git a/llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll b/llvm/test/CodeGen/X86/wineh-exceptionpointer.ll
index 47ffc35acac..9c1f0aaf3de 100644
--- a/llvm/test/CodeGen/WinEH/wineh-exceptionpointer.ll
+++ b/llvm/test/CodeGen/X86/wineh-exceptionpointer.ll
@@ -11,18 +11,16 @@ 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
+ %cs1 = catchswitch within none [label %catch.body] unwind to caller
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: {{^[^: ]+}}: # %catch.body
; CHECK: movq %rdx, %rcx
; CHECK-NEXT: callq g
+ %catch = catchpad within %cs1 [i32 5]
+ %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
+ %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
call void @g(i32 addrspace(1)* %cast_exn)
- catchret %catch to label %exit
-catch.end:
- catchendpad unwind to caller
+ catchret from %catch to label %exit
exit:
ret void
}
OpenPOWER on IntegriCloud