summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2015-11-06 10:07:33 +0000
committerNAKAMURA Takumi <geek4civic@gmail.com>2015-11-06 10:07:33 +0000
commit9947cacebfc667b033e0b2297fd2173b34716b12 (patch)
treeb0d1314128d0e9d6484804067b784a5b6ffda023 /llvm/test
parent7856ad0bccd6d4956b2dd319ccdf8375d3b73964 (diff)
downloadbcm5719-llvm-9947cacebfc667b033e0b2297fd2173b34716b12.tar.gz
bcm5719-llvm-9947cacebfc667b033e0b2297fd2173b34716b12.zip
Revert r252249 (and r252255, r252258), "[WinEH] Clone funclets with multiple parents"
It behaved flaky due to iterating pointer key values on std::set and std::map. llvm-svn: 252279
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-cloning.ll115
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-demotion.ll6
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll1561
-rw-r--r--llvm/test/CodeGen/WinEH/wineh-no-demotion.ll18
4 files changed, 10 insertions, 1690 deletions
diff --git a/llvm/test/CodeGen/WinEH/wineh-cloning.ll b/llvm/test/CodeGen/WinEH/wineh-cloning.ll
index 58bf71e62b6..b4e785d42dd 100644
--- a/llvm/test/CodeGen/WinEH/wineh-cloning.ll
+++ b/llvm/test/CodeGen/WinEH/wineh-cloning.ll
@@ -280,30 +280,7 @@ exit:
; 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: 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: store i32 %x, i32* %x.wineh.spillslot
-; 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: cleanupret [[I_R]] unwind label %right.end
-; CHECK: [[INNER_LEFT]]:
-; CHECK: [[I_L:\%.+]] = cleanuppad []
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
+; TODO: CHECKs
define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
@@ -335,32 +312,7 @@ unreachable:
; 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: unreachable
+; TODO: CHECKs
define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
@@ -398,40 +350,7 @@ 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
+; TODO: CHECKs
define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
@@ -464,33 +383,7 @@ unreachable:
; of which was which along the way; generating each possibility lets
; whichever case was correct execute correctly.
; 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: [[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
-
+; TODO: CHECKs
define void @test10() personality i32 (...)* @__CxxFrameHandler3 {
entry:
diff --git a/llvm/test/CodeGen/WinEH/wineh-demotion.ll b/llvm/test/CodeGen/WinEH/wineh-demotion.ll
index e849a8ec80c..113d95015a0 100644
--- a/llvm/test/CodeGen/WinEH/wineh-demotion.ll
+++ b/llvm/test/CodeGen/WinEH/wineh-demotion.ll
@@ -86,18 +86,18 @@ catch.inner:
; 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
merge.outer:
; CHECK: merge.outer:
+ ; CHECK-NOT: = phi
; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
+ %y = phi i32 [ %x, %catchend.inner ], [ %z, %catch.inner ]
%cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer
catchend.outer:
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 96028542671..00000000000
--- a/llvm/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll
+++ /dev/null
@@ -1,1561 +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: 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: store i32 %x, i32* %x.wineh.spillslot
-; 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: cleanupret [[I_R]] unwind label %right.end
-; CHECK: [[INNER_LEFT]]:
-; CHECK: [[I_L:\%.+]] = cleanuppad []
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; 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: 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; 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: 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; 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: 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[LEFT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind to caller
-
-
-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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[LEFT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind to caller
-
-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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[LEFT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind to caller
-
-
-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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[INNER_SIBLING_LEFT:.+]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]]
-; 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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[LEFT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind to caller
-
-
-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: [[X_RELOAD_R:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_R]])
-; CHECK: unreachable
-; CHECK: [[INNER_CATCH_LEFT]]:
-; CHECK: [[X_RELOAD_L:\%.+]] = load i32, i32* %x.wineh.spillslot
-; CHECK: call void @h(i32 [[X_RELOAD_L]])
-; CHECK: unreachable
-; CHECK: [[INNER_END_LEFT]]:
-; CHECK: catchendpad unwind label %[[RIGHT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; 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_LEFT]]:
-; CHECK: catchendpad unwind label %[[LEFT_END]]
-; CHECK: [[INNER_END_RIGHT]]:
-; CHECK: catchendpad unwind to caller
-
-
-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()
-; TODO: Re-enable this check when it is less flaky.
-; to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
-; CHECK: [[INNER_SIBLING_CATCH_LEFT]]:
-; CHECK: invoke void @f()
-; TODO: Re-enable this check when it is less flaky.
-; 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 []
-; TODO: Re-enable this check when it is less flaky.
-; to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
-; CHECK: [[INNER_SIBLING_LEFT]]:
-; CHECK: [[IS_LEFT:\%.+]] = catchpad []
-; TODO: Re-enable this check when it is less flaky.
-; 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..4e4206eb2be 100644
--- a/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll
+++ b/llvm/test/CodeGen/WinEH/wineh-no-demotion.ll
@@ -39,20 +39,12 @@ shared.cont:
unreachable
inner:
+ ; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
%phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
%i = cleanuppad []
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)
-
exit:
unreachable
}
@@ -84,16 +76,12 @@ shared.cont:
unreachable
inner:
+ ; CHECK: %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
+ ; CHECK: call void @h(i32 %x1)
%i = cleanuppad []
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)
-
exit:
unreachable
}
OpenPOWER on IntegriCloud