diff options
Diffstat (limited to 'llvm/test')
59 files changed, 1257 insertions, 3151 deletions
diff --git a/llvm/test/Assembler/invalid-OperatorConstraint.ll b/llvm/test/Assembler/invalid-OperatorConstraint.ll deleted file mode 100644 index fa90c96c803..00000000000 --- a/llvm/test/Assembler/invalid-OperatorConstraint.ll +++ /dev/null @@ -1,89 +0,0 @@ -; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s -; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s -; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s -; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s -; RUN: sed -e s/.T5:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s -; RUN: sed -e s/.T6:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s -; RUN: sed -e s/.T7:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK7 %s -; RUN: sed -e s/.T8:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK8 %s -; RUN: sed -e s/.T9:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK9 %s - -;T1: define void @f() { -;T1: entry: -;T1: ; operator constraint requires an operator -;T1: catchret undef to label %entry -;T1: ; CHECK1: [[@LINE-1]]:15: error: Catchpad value required in this position -;T1: } - -;T2: define void @f() { -;T2: entry: -;T2: %x = cleanuppad [] -;T2: ; catchret's first operand's operator must be catchpad -;T2: catchret %x to label %entry -;T2: ; CHECK2: [[@LINE-1]]:15: error: '%x' is not a catchpad -;T2: } - -;T3: define void @f() { -;T3: entry: -;T3: ; catchret's first operand's operator must be catchpad -;T3: ; (forward reference case) -;T3: catchret %x to label %next -;T3: ; CHECK3: [[@LINE-1]]:15: error: '%x' is not a catchpad -;T3: next: -;T3: %x = cleanuppad [] -;T3: ret void -;T3: } - -;T4: define void @f() { -;T4: entry: -;T4: ; operator constraint requires an operator -;T4: cleanupret undef unwind label %entry -;T4: ; CHECK4: [[@LINE-1]]:17: error: Cleanuppad value required in this position -;T4: } - -;T5: define void @f() { -;T5: entry: -;T5: %x = catchpad [] -;T5: to label %next unwind label %entry -;T5: next: -;T5: ; cleanupret first operand's operator must be cleanuppad -;T5: cleanupret %x unwind to caller -;T5: ; CHECK5: [[@LINE-1]]:17: error: '%x' is not a cleanuppad -;T5: } - -;T6: define void @f() { -;T6: entry: -;T6: ; cleanupret's first operand's operator must be cleanuppad -;T6: ; (forward reference case) -;T6: cleanupret %x unwind label %next -;T6: ; CHECK6: [[@LINE-1]]:17: error: '%x' is not a cleanuppad -;T6: next: -;T6: %x = catchpad [] to label %entry unwind label %next -;T6: } - -;T7: define void @f() { -;T7: entry: -;T7: ; operator constraint requires an operator -;T7: cleanupendpad undef unwind to caller -;T7: ; CHECK7: [[@LINE-1]]:20: error: Cleanuppad value required in this position -;T7: } - -;T8: define void @f() { -;T8: entry: -;T8: %x = catchpad [] -;T8: to label %next unwind label %entry -;T8: next: -;T8: ; cleanupret first operand's operator must be cleanuppad -;T8: cleanupendpad %x unwind label next -;T8: ; CHECK8: [[@LINE-1]]:20: error: '%x' is not a cleanuppad -;T8: } - -;T9: define void @f() { -;T9: entry: -;T9: ; cleanupret's first operand's operator must be cleanuppad -;T9: ; (forward reference case) -;T9: cleanupendpad %x unwind label %next -;T9: ; CHECK9: [[@LINE-1]]:20: error: '%x' is not a cleanuppad -;T9: next: -;T9: %x = catchpad [] to label %entry unwind label %next -;T9: } diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index 6c08a930209..e2a18ebe131 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -769,95 +769,91 @@ define i32 @instructions.win_eh.1() personality i32 -3 { entry: %arg1 = alloca i32 %arg2 = alloca i32 - invoke void @f.ccc() to label %normal unwind label %catchpad1 - invoke void @f.ccc() to label %normal unwind label %catchpad2 - invoke void @f.ccc() to label %normal unwind label %catchpad3 + invoke void @f.ccc() to label %normal unwind label %catchswitch1 + invoke void @f.ccc() to label %normal unwind label %catchswitch2 + invoke void @f.ccc() to label %normal unwind label %catchswitch3 + +catchswitch1: + %cs1 = catchswitch within none [label %catchpad1] unwind label %terminate.1 catchpad1: - catchpad [] to label %normal unwind label %exn.1 - ; CHECK: catchpad [] - ; CHECK-NEXT: to label %normal unwind label %exn.1 + catchpad within %cs1 [] + br label %normal + ; CHECK: catchpad within %cs1 [] + ; CHECK-NEXT: br label %normal -catchpad2: - catchpad [i32* %arg1] to label %normal unwind label %exn.2 - ; CHECK: catchpad [i32* %arg1] - ; CHECK-NEXT: to label %normal unwind label %exn.2 +catchswitch2: + %cs2 = catchswitch within none [label %catchpad2] unwind to caller -catchpad3: - catchpad [i32* %arg1, i32* %arg2] to label %normal unwind label %exn.3 - ; CHECK: catchpad [i32* %arg1, i32* %arg2] - ; CHECK-NEXT: to label %normal unwind label %exn.3 - -exn.1: - catchendpad unwind label %terminate.1 - ; CHECK: catchendpad unwind label %terminate.1 +catchpad2: + catchpad within %cs2 [i32* %arg1] + br label %normal + ; CHECK: catchpad within %cs2 [i32* %arg1] + ; CHECK-NEXT: br label %normal -exn.2: - catchendpad unwind to caller - ; CHECK: catchendpad unwind to caller +catchswitch3: + %cs3 = catchswitch within none [label %catchpad3] unwind label %cleanuppad1 -exn.3: - catchendpad unwind label %cleanuppad1 - ; CHECK: catchendpad unwind label %cleanuppad1 +catchpad3: + catchpad within %cs3 [i32* %arg1, i32* %arg2] + br label %normal + ; CHECK: catchpad within %cs3 [i32* %arg1, i32* %arg2] + ; CHECK-NEXT: br label %normal cleanuppad1: - %clean.1 = cleanuppad [] - ; CHECK: %clean.1 = cleanuppad [] - invoke void @f.ccc() to label %normal unwind label %cleanupendpad1 - -cleanupendpad1: - cleanupendpad %clean.1 unwind label %terminate.2 - ; CHECK: cleanupendpad %clean.1 unwind label %terminate.2 + %clean.1 = cleanuppad within none [] + ; CHECK: %clean.1 = cleanuppad within none [] + invoke void @f.ccc() to label %normal unwind label %terminate.2 terminate.1: - terminatepad [] unwind to caller - ; CHECK: terminatepad [] unwind to caller + terminatepad within none [] unwind to caller + ; CHECK: terminatepad within none [] unwind to caller terminate.2: - terminatepad [i32* %arg1] unwind label %normal.pre - ; CHECK: terminatepad [i32* %arg1] unwind label %normal.pre + terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre + ; CHECK: terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre normal.pre: - terminatepad [i32* %arg1, i32* %arg2] unwind to caller - ; CHECK: terminatepad [i32* %arg1, i32* %arg2] unwind to caller + terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller + ; CHECK: terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller normal: ret i32 0 } - +; define i32 @instructions.win_eh.2() personality i32 -4 { entry: - invoke void @f.ccc() to label %invoke.cont unwind label %catchpad + invoke void @f.ccc() to label %invoke.cont unwind label %catchswitch invoke.cont: invoke void @f.ccc() to label %continue unwind label %cleanup cleanup: - %clean = cleanuppad [] - ; CHECK: %clean = cleanuppad [] - cleanupret %clean unwind to caller - ; CHECK: cleanupret %clean unwind to caller + %clean = cleanuppad within none [] + ; CHECK: %clean = cleanuppad within none [] + cleanupret from %clean unwind to caller + ; CHECK: cleanupret from %clean unwind to caller + +catchswitch: + %cs = catchswitch within none [label %catchpad] unwind label %terminate catchpad: - %catch = catchpad [] to label %body unwind label %catchend - ; CHECK: %catch = catchpad [] - ; CHECK-NEXT: to label %body unwind label %catchend + %catch = catchpad within %cs [] + br label %body + ; CHECK: %catch = catchpad within %cs [] + ; CHECK-NEXT: br label %body body: - invoke void @f.ccc() to label %continue unwind label %catchend - catchret %catch to label %return - ; CHECK: catchret %catch to label %return + invoke void @f.ccc() to label %continue unwind label %terminate + catchret from %catch to label %return + ; CHECK: catchret from %catch to label %return return: ret i32 0 -catchend: - catchendpad unwind label %terminate - ; CHECK: catchendpad unwind label %terminate - terminate: - terminatepad [] unwind to caller - ; CHECK: terminatepad [] unwind to caller + terminatepad within %cs [] unwind to caller + ; CHECK: terminatepad within %cs [] unwind to caller continue: ret i32 0 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 } diff --git a/llvm/test/Feature/exception.ll b/llvm/test/Feature/exception.ll index c6c436ae83d..05dbfe89645 100644 --- a/llvm/test/Feature/exception.ll +++ b/llvm/test/Feature/exception.ll @@ -31,8 +31,8 @@ entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad pad: - %cp = cleanuppad [i7 4] - cleanupret %cp unwind to caller + %cp = cleanuppad within none [i7 4] + cleanupret from %cp unwind to caller exit: ret void } @@ -43,9 +43,9 @@ entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad cleanup: - cleanupret %cp unwind label %pad + cleanupret from %cp unwind label %pad pad: - %cp = cleanuppad [] + %cp = cleanuppad within none [] br label %cleanup exit: ret void @@ -57,9 +57,9 @@ entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad cleanup: - cleanupret %0 unwind label %pad + cleanupret from %0 unwind label %pad pad: - %0 = cleanuppad [] + %0 = cleanuppad within none [] br label %cleanup exit: ret void @@ -70,12 +70,10 @@ entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad pad: - %cp = catchpad [i7 4] - to label %catch unwind label %endpad + %cs1 = catchswitch within none [label %catch] unwind to caller catch: - catchret %cp to label %exit -endpad: - catchendpad unwind to caller + %cp = catchpad within %cs1 [i7 4] + catchret from %cp to label %exit exit: ret void } @@ -85,13 +83,13 @@ define void @catchret1() personality i32 (...)* @__gxx_personality_v0 { entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad -catch: - catchret %cp to label %exit +catchret: + catchret from %cp to label %exit pad: - %cp = catchpad [] - to label %catch unwind label %endpad -endpad: - catchendpad unwind to caller + %cs1 = catchswitch within none [label %catch] unwind to caller +catch: + %cp = catchpad within %cs1 [i7 4] + br label %catchret exit: ret void } @@ -101,13 +99,13 @@ define void @catchret2() personality i32 (...)* @__gxx_personality_v0 { entry: invoke void @_Z3quxv() optsize to label %exit unwind label %pad -catch: - catchret %0 to label %exit +catchret: + catchret from %0 to label %exit pad: - %0 = catchpad [] - to label %catch unwind label %endpad -endpad: - catchendpad unwind to caller + %cs1 = catchswitch within none [label %catch] unwind to caller +catch: + %0 = catchpad within %cs1 [i7 4] + br label %catchret exit: ret void } @@ -117,9 +115,10 @@ entry: invoke void @_Z3quxv() optsize to label %exit unwind label %bb2 bb2: - catchpad [i7 4] to label %exit unwind label %bb3 -bb3: - catchendpad unwind to caller + %cs1 = catchswitch within none [label %catch] unwind to caller +catch: + catchpad within %cs1 [i7 4] + br label %exit exit: ret i8 0 } @@ -132,7 +131,7 @@ try.cont: invoke void @_Z3quxv() optsize to label %try.cont unwind label %bb bb: - terminatepad [i7 4] unwind label %bb + terminatepad within none [i7 4] unwind label %bb } define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 { @@ -143,7 +142,7 @@ try.cont: invoke void @_Z3quxv() optsize to label %try.cont unwind label %bb bb: - terminatepad [i7 4] unwind to caller + terminatepad within none [i7 4] unwind to caller } define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 { @@ -154,78 +153,6 @@ try.cont: invoke void @_Z3quxv() optsize to label %try.cont unwind label %bb bb: - cleanuppad [i7 4] - ret void -} - -define void @catchendpad0() personality i32 (...)* @__gxx_personality_v0 { -entry: - br label %try.cont - -try.cont: - invoke void @_Z3quxv() optsize - to label %try.cont unwind label %bb -bb: - catchendpad unwind label %bb -} - -define void @catchendpad1() personality i32 (...)* @__gxx_personality_v0 { -entry: - br label %try.cont - -try.cont: - invoke void @_Z3quxv() optsize - to label %try.cont unwind label %bb -bb: - catchendpad unwind to caller -} - -define void @cleanupendpad0() personality i32 (...)* @__gxx_personality_v0 { -entry: - invoke void @_Z3quxv() optsize - to label %exit unwind label %pad -pad: - %cp = cleanuppad [i7 4] - invoke void @_Z3quxv() optsize - to label %stop unwind label %endpad -stop: - unreachable -endpad: - cleanupendpad %cp unwind label %pad -exit: - ret void -} - -; forward ref by name -define void @cleanupendpad1() personality i32 (...)* @__gxx_personality_v0 { -entry: - invoke void @_Z3quxv() optsize - to label %exit unwind label %pad -endpad: - cleanupendpad %cp unwind to caller -pad: - %cp = cleanuppad [] - invoke void @_Z3quxv() optsize - to label %stop unwind label %endpad -stop: - unreachable -exit: - ret void -} - -; forward ref by ID -define void @cleanupendpad2() personality i32 (...)* @__gxx_personality_v0 { -entry: - invoke void @_Z3quxv() optsize - to label %exit unwind label %pad -endpad: - cleanupendpad %0 unwind label %pad -pad: - %0 = cleanuppad [] - invoke void @_Z3quxv() optsize - to label %stop unwind label %endpad -stop: - unreachable -exit: + cleanuppad within none [i7 4] ret void } diff --git a/llvm/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll b/llvm/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll index c0b63b7d6d9..8c5e01e3634 100644 --- a/llvm/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll +++ b/llvm/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll @@ -18,9 +18,6 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2 ; CHECK-LABEL: @test( define void @test(i32* %addr) personality i32 (...)* @__CxxFrameHandler3 { -; CHECK: entry: -; CHECK-NEXT: %x = getelementptr i32, i32* %addr, i32 1 -; CHECK-NEXT: %p1 = bitcast i32* %x to i8* entry: %x = getelementptr i32, i32* %addr, i32 1 %p1 = bitcast i32* %x to i8* @@ -29,7 +26,6 @@ entry: ; CHECK: invoke.cont: ; CHECK-NEXT: %y = getelementptr i32, i32* %addr, i32 2 -; CHECK-NEXT: %p2 = bitcast i32* %y to i8* invoke.cont: %y = getelementptr i32, i32* %addr, i32 2 %p2 = bitcast i32* %y to i8* @@ -40,23 +36,31 @@ done: ret void catch1: - %cp1 = catchpad [] to label %catch.dispatch unwind label %catchend1 + %cs1 = catchswitch within none [label %handler1] unwind to caller -catch2: - %cp2 = catchpad [] to label %catch.dispatch unwind label %catchend2 +handler1: + %cp1 = catchpad within %cs1 [] + br label %catch.shared +; CHECK: handler1: +; CHECK-NEXT: catchpad within %cs1 +; CHECK: %[[p1:[0-9]+]] = bitcast i32* %x to i8* -; CHECK: catch.dispatch: -; CHECK-NEXT: %p = phi i8* [ %p1, %catch1 ], [ %p2, %catch2 ] -catch.dispatch: - %p = phi i8* [ %p1, %catch1 ], [ %p2, %catch2 ] +catch2: + %cs2 = catchswitch within none [label %handler2] unwind to caller + +handler2: + %cp2 = catchpad within %cs2 [] + br label %catch.shared +; CHECK: handler2: +; CHECK: catchpad within %cs2 +; CHECK: %[[p2:[0-9]+]] = bitcast i32* %y to i8* + +; CHECK: catch.shared: +; CHECK-NEXT: %p = phi i8* [ %[[p1]], %handler1 ], [ %[[p2]], %handler2 ] +catch.shared: + %p = phi i8* [ %p1, %handler1 ], [ %p2, %handler2 ] call void @g(i8* %p) unreachable - -catchend1: - catchendpad unwind to caller - -catchend2: - catchendpad unwind to caller } ; CodeGenPrepare will want to hoist these llvm.dbg.value calls to the phi, but @@ -75,24 +79,22 @@ ret: catch.dispatch: %p = phi i8* [%a, %entry], [%b, %next] - %cp1 = catchpad [] to label %catch unwind label %catchend + %cs1 = catchswitch within none [label %catch] unwind to caller catch: + %cp1 = catchpad within %cs1 [] tail call void @llvm.dbg.value(metadata i8* %p, i64 0, metadata !11, metadata !13), !dbg !14 - invoke void @g(i8* %p) to label %catchret unwind label %catchend -catchret: - catchret %cp1 to label %ret + call void @g(i8* %p) + catchret from %cp1 to label %ret ; CHECK: catch.dispatch: ; CHECK-NEXT: phi i8 -; CHECK-NEXT: catchpad +; CHECK-NEXT: catchswitch ; CHECK-NOT: llvm.dbg.value ; CHECK: catch: +; CHECK-NEXT: catchpad ; CHECK-NEXT: call void @llvm.dbg.value - -catchend: - catchendpad unwind to caller } !llvm.dbg.cu = !{!0} diff --git a/llvm/test/Transforms/GVN/funclet.ll b/llvm/test/Transforms/GVN/funclet.ll index c9faf8ee4c8..2669256f0bd 100644 --- a/llvm/test/Transforms/GVN/funclet.ll +++ b/llvm/test/Transforms/GVN/funclet.ll @@ -17,12 +17,12 @@ entry: to label %unreachable unwind label %catch.dispatch catch.dispatch: ; preds = %entry - %catchpad = 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 + %catchpad = catchpad within %cs1 [i8* null, i32 64, i8* null] store i8 5, i8* %b - catchret %catchpad to label %try.cont + catchret from %catchpad to label %try.cont try.cont: ; preds = %catch %load_b = load i8, i8* %b @@ -30,9 +30,6 @@ try.cont: ; preds = %catch %add = add i8 %load_b, %load_c ret i8 %add -catchendblock: ; preds = %catch.dispatch - catchendpad unwind to caller - unreachable: ; preds = %entry unreachable } diff --git a/llvm/test/Transforms/GVN/pre-load.ll b/llvm/test/Transforms/GVN/pre-load.ll index c165a5a4932..685df24f62b 100644 --- a/llvm/test/Transforms/GVN/pre-load.ll +++ b/llvm/test/Transforms/GVN/pre-load.ll @@ -399,7 +399,7 @@ define void @test12(i32* %p) personality i32 (...)* @__CxxFrameHandler3 { ; CHECK-LABEL: @test12( block1: invoke void @f() - to label %block2 unwind label %catch + to label %block2 unwind label %catch.dispatch block2: invoke void @f() @@ -408,31 +408,25 @@ block2: block3: ret void -catch: - %c = catchpad [] - to label %catch.dispatch unwind label %catchend - catch.dispatch: - catchret %c to label %block2 + %cs1 = catchswitch within none [label %catch] unwind label %cleanup2 -; CHECK: catchend: -; CHECK-NOT: load -; CHECK-NEXT: catchendpad -catchend: - catchendpad unwind label %cleanup2 +catch: + %c = catchpad within %cs1 [] + catchret from %c to label %block2 cleanup: - %c1 = cleanuppad [] + %c1 = cleanuppad within none [] store i32 0, i32* %p - cleanupret %c1 unwind label %cleanup2 + cleanupret from %c1 unwind label %cleanup2 ; CHECK: cleanup2: ; CHECK-NOT: phi -; CHECK-NEXT: %c2 = cleanuppad [] +; CHECK-NEXT: %c2 = cleanuppad within none [] ; CHECK-NEXT: %NOTPRE = load i32, i32* %p cleanup2: - %c2 = cleanuppad [] + %c2 = cleanuppad within none [] %NOTPRE = load i32, i32* %p call void @g(i32 %NOTPRE) - cleanupret %c2 unwind to caller + cleanupret from %c2 unwind to caller } diff --git a/llvm/test/Transforms/Inline/PR25155.ll b/llvm/test/Transforms/Inline/PR25155.ll index f2a9ec32fda..aed9a58ab3d 100644 --- a/llvm/test/Transforms/Inline/PR25155.ll +++ b/llvm/test/Transforms/Inline/PR25155.ll @@ -8,21 +8,23 @@ 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 + %0 = catchpad within %cs1 [i8* null, i32 64, i8* null] invoke void @dtor() - to label %invoke.cont.1 unwind label %catchendblock + to label %invoke.cont.1 unwind label %ehcleanup invoke.cont.1: ; preds = %catch - catchret %0 to label %try.cont + catchret from %0 to label %try.cont try.cont: ; preds = %entry, %invoke.cont.1 ret void -catchendblock: ; preds = %catch, %catch.dispatch - catchendpad unwind to caller +ehcleanup: + %cp2 = cleanuppad within none [] + call void @g() + cleanupret from %cp2 unwind to caller } ; CHECK-LABEL: define void @f( @@ -31,10 +33,7 @@ catchendblock: ; preds = %catch, %catch.dispa ; CHECK: to label %dtor.exit unwind label %terminate.i ; CHECK: terminate.i: -; CHECK-NEXT: terminatepad [void ()* @terminate] unwind label %catchendblock - -; CHECK: catchendblock: -; CHECK-NEXT: catchendpad unwind to caller +; CHECK-NEXT: terminatepad within %0 [void ()* @terminate] unwind label %ehcleanup declare i32 @__CxxFrameHandler3(...) @@ -47,7 +46,7 @@ invoke.cont: ; preds = %entry ret void terminate: ; preds = %entry - terminatepad [void ()* @terminate] unwind to caller + terminatepad within none [void ()* @terminate] unwind to caller } declare void @g() diff --git a/llvm/test/Transforms/InstCombine/token.ll b/llvm/test/Transforms/InstCombine/token.ll index e47109b6164..0929cf7ebee 100644 --- a/llvm/test/Transforms/InstCombine/token.ll +++ b/llvm/test/Transforms/InstCombine/token.ll @@ -9,14 +9,14 @@ bb: unreachable unreachable: - %cl = cleanuppad [] - cleanupret %cl unwind to caller + %cl = cleanuppad within none [] + cleanupret from %cl unwind to caller } ; CHECK-LABEL: define void @test1( ; CHECK: unreachable: -; CHECK: %cl = cleanuppad [] -; CHECK: cleanupret %cl unwind to caller +; CHECK: %cl = cleanuppad within none [] +; CHECK: cleanupret from %cl unwind to caller define void @test2(i8 %A, i8 %B) personality i32 (...)* @__CxxFrameHandler3 { bb: @@ -33,19 +33,15 @@ cont: catch: %phi = phi i32 [ %X, %bb ], [ %Y, %cont ] - %cl = catchpad [] - to label %doit - unwind label %endpad + %cs = catchswitch within none [label %doit] unwind to caller doit: + %cl = catchpad within %cs [] call void @g(i32 %phi) unreachable unreachable: unreachable - -endpad: - catchendpad unwind to caller } ; CHECK-LABEL: define void @test2( @@ -73,19 +69,15 @@ cont2: catch: %phi = phi i32 [ %X, %bb ], [ %Y, %cont ], [ %Y, %cont2 ] - %cl = catchpad [] - to label %doit - unwind label %endpad + %cs = catchswitch within none [label %doit] unwind to caller doit: + %cl = catchpad within %cs [] call void @g(i32 %phi) unreachable unreachable: unreachable - -endpad: - catchendpad unwind to caller } ; CHECK-LABEL: define void @test3( diff --git a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll index 03799ddfdb5..a2da3208a38 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/funclet.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/funclet.ll @@ -20,19 +20,17 @@ throw: ; preds = %throw, %entry pad: ; preds = %throw %phi2 = phi i8* [ %tmp96, %throw ] - terminatepad [] unwind label %blah + terminatepad within none [] unwind label %blah blah: - catchpad [] to label %unreachable unwind label %blah3 + %cs = catchswitch within none [label %unreachable] unwind label %blah2 unreachable: + catchpad within %cs [] unreachable -blah3: - catchendpad unwind label %blah2 - blah2: - %cleanuppadi4.i.i.i = cleanuppad [] + %cleanuppadi4.i.i.i = cleanuppad within none [] br label %loop_body loop_body: ; preds = %iter, %pad @@ -45,11 +43,11 @@ iter: ; preds = %loop_body br i1 undef, label %unwind_out, label %loop_body unwind_out: ; preds = %iter, %loop_body - cleanupret %cleanuppadi4.i.i.i unwind to caller + cleanupret from %cleanuppadi4.i.i.i unwind to caller } ; CHECK-LABEL: define void @f( -; CHECK: cleanuppad [] +; CHECK: cleanuppad within none [] ; CHECK-NEXT: ptrtoint i8* %phi2 to i32 define void @g() personality i32 (...)* @_except_handler3 { @@ -63,20 +61,18 @@ throw: ; preds = %throw, %entry pad: %phi2 = phi i8* [ %tmp96, %throw ] - catchpad [] to label %unreachable unwind label %blah + %cs = catchswitch within none [label %unreachable, label %blah] unwind to caller unreachable: + catchpad within %cs [] unreachable blah: - %catchpad = catchpad [] to label %loop_body unwind label %blah3 - - -blah3: - catchendpad unwind to caller ;label %blah2 + %catchpad = catchpad within %cs [] + br label %loop_body unwind_out: - catchret %catchpad to label %leave + catchret from %catchpad to label %leave leave: ret void @@ -93,10 +89,7 @@ iter: ; preds = %loop_body ; CHECK-LABEL: define void @g( ; CHECK: blah: -; CHECK-NEXT: catchpad [] -; CHECK-NEXT: to label %loop_body.preheader - -; CHECK: loop_body.preheader: +; CHECK-NEXT: catchpad within %cs [] ; CHECK-NEXT: ptrtoint i8* %phi2 to i32 @@ -110,29 +103,25 @@ throw: ; preds = %throw, %entry to label %throw unwind label %pad pad: - catchpad [] to label %unreachable unwind label %blug + %cs = catchswitch within none [label %unreachable, label %blug] unwind to caller unreachable: + catchpad within %cs [] unreachable blug: %phi2 = phi i8* [ %tmp96, %pad ] - %catchpad = catchpad [] to label %blah2 unwind label %blah3 - -blah2: + %catchpad = catchpad within %cs [] br label %loop_body -blah3: - catchendpad unwind to caller ;label %blah2 - unwind_out: - catchret %catchpad to label %leave + catchret from %catchpad to label %leave leave: ret void loop_body: ; preds = %iter, %pad - %tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah2 ] + %tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blug ] %tmp100 = icmp eq i8* %tmp99, undef br i1 %tmp100, label %unwind_out, label %iter @@ -143,10 +132,7 @@ iter: ; preds = %loop_body ; CHECK-LABEL: define void @h( ; CHECK: blug: -; CHECK: catchpad [] -; CHECK-NEXT: to label %blah2 - -; CHECK: blah2: +; CHECK: catchpad within %cs [] ; CHECK-NEXT: ptrtoint i8* %phi2 to i32 define void @i() personality i32 (...)* @_except_handler3 { @@ -160,16 +146,14 @@ throw: ; preds = %throw, %entry catchpad: ; preds = %throw %phi2 = phi i8* [ %tmp96, %throw ] - catchpad [] to label %cp_body unwind label %catchendpad + %cs = catchswitch within none [label %cp_body] unwind label %cleanuppad cp_body: + catchpad within %cs [] br label %loop_head -catchendpad: - catchendpad unwind label %cleanuppad - cleanuppad: - cleanuppad [] + cleanuppad within none [] br label %loop_head loop_head: @@ -205,39 +189,31 @@ for.inc: ; preds = %for.cond br label %for.cond catch.dispatch: ; preds = %for.cond - %0 = catchpad [i8* null, i32 64, i8* null] - to label %catch unwind label %catchendblock - -catchendblock: ; preds = %catch.dispatch - catchendpad unwind label %catch.dispatch.2 + %cs = catchswitch within none [label %catch] unwind label %catch.dispatch.2 catch: ; preds = %catch.dispatch - catchret %0 to label %try.cont + %0 = catchpad within %cs [i8* null, i32 64, i8* null] + catchret from %0 to label %try.cont try.cont: ; preds = %catch invoke void @external(i32* %c) to label %try.cont.7 unwind label %catch.dispatch.2 catch.dispatch.2: ; preds = %try.cont, %catchendblock - %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catchendblock ] - %1 = catchpad [i8* null, i32 64, i8* null] - to label %catch.4 unwind label %catchendblock.3 + %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ] + %cs2 = catchswitch within none [label %catch.4] unwind to caller catch.4: ; preds = %catch.dispatch.2 + catchpad within %cs2 [i8* null, i32 64, i8* null] unreachable try.cont.7: ; preds = %try.cont ret void - -catchendblock.3: ; preds = %catch.dispatch.2 - catchendpad unwind to caller } ; CHECK-LABEL: define void @test1( ; CHECK: for.cond: ; CHECK: %d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ] -; CHECK: catchendpad unwind label %catch.dispatch.2 - ; CHECK: catch.dispatch.2: -; CHECK: %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catchendblock ] +; CHECK: %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ] diff --git a/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll b/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll index fa64875d9af..011998b9089 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/pr25541.ll @@ -12,10 +12,10 @@ for.cond.i: ; preds = %for.inc.i, %entry to label %for.inc.i unwind label %catch.dispatch.i catch.dispatch.i: ; preds = %for.cond.i - %0 = catchpad [i8* null, i32 64, i8* null] - to label %for.cond.1.preheader.i unwind label %catchendblock.i + %cs = catchswitch within none [label %for.cond.1.preheader.i] unwind to caller for.cond.1.preheader.i: ; preds = %catch.dispatch.i + %0 = catchpad within %cs [i8* null, i32 64, i8* null] %cmp.i = icmp eq i32* %_First.addr.0.i, null br label %for.cond.1.i @@ -23,18 +23,15 @@ for.cond.1.i: ; preds = %for.body.i, %for.co br i1 %cmp.i, label %for.end.i, label %for.body.i for.body.i: ; preds = %for.cond.1.i - invoke void @g() - to label %for.cond.1.i unwind label %catchendblock.i - -catchendblock.i: ; preds = %for.body.i, %catch.dispatch.i - catchendpad unwind to caller + call void @g() + br label %for.cond.1.i for.inc.i: ; preds = %for.cond.i %incdec.ptr.i = getelementptr inbounds i32, i32* %_First.addr.0.i, i64 1 br label %for.cond.i for.end.i: ; preds = %for.cond.1.i - catchret %0 to label %leave + catchret from %0 to label %leave leave: ; preds = %for.end.i ret void diff --git a/llvm/test/Transforms/LoopUnswitch/cleanuppad.ll b/llvm/test/Transforms/LoopUnswitch/cleanuppad.ll new file mode 100644 index 00000000000..b06ebd7235c --- /dev/null +++ b/llvm/test/Transforms/LoopUnswitch/cleanuppad.ll @@ -0,0 +1,44 @@ +; RUN: opt -S -loop-unswitch < %s | FileCheck %s +target triple = "x86_64-pc-win32" + +define void @f(i32 %doit, i1 %x, i1 %y) personality i32 (...)* @__CxxFrameHandler3 { +entry: + %tobool = icmp eq i32 %doit, 0 + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + br i1 %x, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br i1 %tobool, label %if.then, label %for.inc + +if.then: ; preds = %for.body + br i1 %y, label %for.inc, label %delete.notnull + +delete.notnull: ; preds = %if.then + invoke void @g() + to label %invoke.cont unwind label %lpad + +invoke.cont: ; preds = %delete.notnull + br label %for.inc + +lpad: ; preds = %delete.notnull + %cp = cleanuppad within none [] + cleanupret from %cp unwind to caller + +for.inc: ; preds = %invoke.cont, %if.then, %for.body + br label %for.cond + +for.end: ; preds = %for.cond + ret void +} + +declare void @g() + +declare i32 @__CxxFrameHandler3(...) + +; CHECK-LABEL: define void @f( +; CHECK: cleanuppad within none [] +; CHECK-NOT: cleanuppad + +attributes #0 = { ssp uwtable } diff --git a/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll b/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll index d04c567e503..0ba29043912 100644 --- a/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll +++ b/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll @@ -31,12 +31,12 @@ invoke.cont: ; preds = %entry ret void ehcleanup: ; preds = %entry - %0 = cleanuppad [] - cleanupret %0 unwind label %ehcleanup.1 + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %ehcleanup.1 ehcleanup.1: ; preds = %ehcleanup - %1 = cleanuppad [] - cleanupret %1 unwind to caller + %1 = cleanuppad within none [] + cleanupret from %1 unwind to caller } @@ -60,15 +60,14 @@ ehcleanup.1: ; preds = %ehcleanup ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: ehcleanup: -; CHECK: cleanuppad +; CHECK: cleanuppad within none ; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) -; CHECK: cleanupret %0 unwind label %catch.dispatch +; CHECK: cleanupret from %0 unwind label %catch.dispatch ; CHECK: catch.dispatch: -; CHECK: catchpad +; CHECK: catchswitch within none [label %catch] unwind to caller ; CHECK: catch: +; CHECK: catchpad ; CHECK: catchret -; CHECK: catchendblock: ; preds = %catch.dispatch -; CHECK: catchendpad unwind to caller ; CHECK-NOT: cleanuppad ; CHECK: } ; @@ -81,15 +80,16 @@ invoke.cont: ; preds = %entry br label %try.cont ehcleanup: ; preds = %entry - %0 = cleanuppad [] + %0 = cleanuppad within none [] call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) - cleanupret %0 unwind label %catch.dispatch + cleanupret from %0 unwind label %catch.dispatch catch.dispatch: ; preds = %ehcleanup - %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock + %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 catch: ; preds = %catch.dispatch - catchret %1 to label %catchret.dest + %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %1 to label %catchret.dest catchret.dest: ; preds = %catch br label %try.cont @@ -97,12 +97,9 @@ catchret.dest: ; preds = %catch try.cont: ; preds = %catchret.dest, %invoke.cont ret void -catchendblock: ; preds = %catch.dispatch - catchendpad unwind label %ehcleanup.1 - -ehcleanup.1: ; preds = %catchendblock - %2 = cleanuppad [] - cleanupret %2 unwind to caller +ehcleanup.1: + %2 = cleanuppad within none [] + cleanupret from %2 unwind to caller } @@ -121,21 +118,19 @@ ehcleanup.1: ; preds = %catchendblock ; In this case the inner cleanup pad should be eliminated and the invoke of g() ; should unwind directly to the catchpad. ; -; CHECK: define void @f3() +; CHECK-LABEL: define void @f3() ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: to label %try.cont unwind label %catch.dispatch ; CHECK: catch.dispatch: -; CHECK: catchpad [i8* null, i32 64, i8* null] -; CHECK-NEXT: to label %catch unwind label %catchendblock +; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1 ; CHECK: catch: +; CHECK: catchpad within %cs1 [i8* null, i32 64, i8* null] ; CHECK: catchret -; CHECK: catchendblock: -; CHECK: catchendpad unwind label %ehcleanup.1 ; CHECK: ehcleanup.1: ; CHECK: cleanuppad ; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) -; CHECK: cleanupret %1 unwind to caller +; CHECK: cleanupret from %cp3 unwind to caller ; CHECK: } ; define void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { @@ -147,14 +142,15 @@ invoke.cont: ; preds = %entry br label %try.cont ehcleanup: ; preds = %entry - %0 = cleanuppad [] - cleanupret %0 unwind label %catch.dispatch + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %catch.dispatch catch.dispatch: ; preds = %ehcleanup - %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock + %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 catch: ; preds = %catch.dispatch - catchret %1 to label %catchret.dest + %cp2 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %cp2 to label %catchret.dest catchret.dest: ; preds = %catch br label %try.cont @@ -162,13 +158,10 @@ catchret.dest: ; preds = %catch try.cont: ; preds = %catchret.dest, %invoke.cont ret void -catchendblock: ; preds = %catch.dispatch - catchendpad unwind label %ehcleanup.1 - -ehcleanup.1: ; preds = %catchendblock - %2 = cleanuppad [] +ehcleanup.1: + %cp3 = cleanuppad within none [] call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) - cleanupret %2 unwind to caller + cleanupret from %cp3 unwind to caller } @@ -184,11 +177,10 @@ ehcleanup.1: ; preds = %catchendblock ; } ; ; In this case, the cleanuppad should be eliminated, the invoke outside of the -; call block should be converted to a call and the catchendpad should unwind -; to the caller (that is, that is, exception handling continues with the parent -; frame of the caller).) +; catch block should be converted to a call (that is, that is, exception +; handling continues with the parent frame of the caller).) ; -; CHECK: define void @f4() +; CHECK-LABEL: define void @f4() ; CHECK: entry: ; CHECK: call void @g ; Note: The cleanuppad simplification will insert an unconditional branch here @@ -196,11 +188,10 @@ ehcleanup.1: ; preds = %catchendblock ; CHECK: invoke void @g() ; CHECK: to label %try.cont unwind label %catch.dispatch ; CHECK: catch.dispatch: -; CHECK: catchpad +; CHECK: catchswitch within none [label %catch] unwind to caller ; CHECK: catch: +; CHECK: catchpad ; CHECK: catchret -; CHECK: catchendblock: -; CHECK: catchendpad unwind to caller ; CHECK-NOT: cleanuppad ; CHECK: } ; @@ -214,43 +205,41 @@ invoke.cont: ; preds = %entry to label %try.cont unwind label %catch.dispatch catch.dispatch: ; preds = %invoke.cont - %0 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock + %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup catch: ; preds = %catch.dispatch - catchret %0 to label %try.cont + %0 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %0 to label %try.cont try.cont: ; preds = %catch, %invoke.cont ret void -catchendblock: ; preds = %catch.dispatch - catchendpad unwind label %ehcleanup - -ehcleanup: ; preds = %catchendblock, %entry - %1 = cleanuppad [] - cleanupret %1 unwind to caller +ehcleanup: + %cp2 = cleanuppad within none [] + cleanupret from %cp2 unwind to caller } ; This tests the case where a terminatepad unwinds to a cleanuppad. ; I'm not sure how this case would arise, but it seems to be syntactically ; legal so I'm testing it. ; -; CHECK: define void @f5() +; CHECK-LABEL: define void @f5() ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: to label %try.cont unwind label %terminate ; CHECK: terminate: -; CHECK: terminatepad [i7 4] unwind to caller +; CHECK: terminatepad within none [i7 4] unwind to caller ; CHECK-NOT: cleanuppad ; CHECK: try.cont: ; CHECK: invoke void @g() ; CHECK: to label %try.cont.1 unwind label %terminate.1 ; CHECK: terminate.1: -; CHECK: terminatepad [i7 4] unwind label %ehcleanup.2 +; CHECK: terminatepad within none [i7 4] unwind label %ehcleanup.2 ; CHECK-NOT: ehcleanup.1: ; CHECK: ehcleanup.2: ; CHECK: [[TMP:\%.+]] = cleanuppad ; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) -; CHECK: cleanupret [[TMP]] unwind to caller +; CHECK: cleanupret from [[TMP]] unwind to caller ; CHECK: } define void @f5() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { entry: @@ -259,27 +248,27 @@ entry: to label %try.cont unwind label %terminate terminate: ; preds = %entry - terminatepad [i7 4] unwind label %ehcleanup + terminatepad within none [i7 4] unwind label %ehcleanup ehcleanup: ; preds = %terminate - %0 = cleanuppad [] - cleanupret %0 unwind to caller + %0 = cleanuppad within none [] + cleanupret from %0 unwind to caller try.cont: ; preds = %entry invoke void @g() to label %try.cont.1 unwind label %terminate.1 terminate.1: ; preds = %try.cont - terminatepad [i7 4] unwind label %ehcleanup.1 + terminatepad within none [i7 4] unwind label %ehcleanup.1 ehcleanup.1: ; preds = %terminate.1 - %1 = cleanuppad [] - cleanupret %1 unwind label %ehcleanup.2 + %1 = cleanuppad within none [] + cleanupret from %1 unwind label %ehcleanup.2 ehcleanup.2: ; preds = %ehcleanup.1 - %2 = cleanuppad [] + %2 = cleanuppad within none [] call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) - cleanupret %2 unwind to caller + cleanupret from %2 unwind to caller try.cont.1: ; preds = %try.cont ret void @@ -304,7 +293,7 @@ try.cont.1: ; preds = %try.cont ; In this case, the cleanup pad should be eliminated and the PHI node in the ; cleanup pad should be sunk into the catch dispatch block. ; -; CHECK: define i32 @f6() +; CHECK-LABEL: define i32 @f6() ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: invoke.cont: @@ -325,17 +314,15 @@ invoke.cont: ; preds = %entry ehcleanup: ; preds = %invoke.cont, %entry %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] - %0 = cleanuppad [] - cleanupret %0 unwind label %catch.dispatch + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %catch.dispatch catch.dispatch: ; preds = %ehcleanup - %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 - catchret %1 to label %return - -catchendblock: ; preds = %catch.dispatch - catchendpad unwind to caller + %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %1 to label %return return: ; preds = %invoke.cont, %catch %retval.0 = phi i32 [ %state.0, %catch ], [ 0, %invoke.cont ] @@ -363,7 +350,7 @@ return: ; preds = %invoke.cont, %catch ; In this case, the cleanup pad should be eliminated and the PHI node in the ; cleanup pad should be merged with the PHI node in the catch dispatch block. ; -; CHECK: define i32 @f7() +; CHECK-LABEL: define i32 @f7() ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: invoke.cont: @@ -390,18 +377,16 @@ invoke.cont.1: ; preds = %invoke.cont ehcleanup: ; preds = %invoke.cont.1, %invoke.cont %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ] - %0 = cleanuppad [] - cleanupret %0 unwind label %catch.dispatch + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %catch.dispatch catch.dispatch: ; preds = %ehcleanup, %entry %state.1 = phi i32 [ %state.0, %ehcleanup ], [ 1, %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 - catchret %1 to label %return - -catchendblock: ; preds = %catch.dispatch - catchendpad unwind to caller + %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null] + catchret from %1 to label %return return: ; preds = %invoke.cont.1, %catch %retval.0 = phi i32 [ %state.1, %catch ], [ 0, %invoke.cont.1 ] @@ -435,7 +420,7 @@ return: ; preds = %invoke.cont.1, %cat ; should have an incoming value entry for path from 'foo' that references the ; PHI node itself. ; -; CHECK: define void @f8() +; CHECK-LABEL: define void @f8() ; CHECK: entry: ; CHECK: invoke void @g() ; CHECK: invoke.cont: @@ -456,18 +441,16 @@ invoke.cont: ; preds = %entry ehcleanup: ; preds = %invoke.cont, %entry %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] - %0 = cleanuppad [] - cleanupret %0 unwind label %catch.dispatch + %0 = cleanuppad within none [] + cleanupret from %0 unwind label %catch.dispatch catch.dispatch: ; preds = %ehcleanup, %catch.cont - %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] call void @use_x(i32 %x) - catchret %1 to label %catch.cont - -catchendblock: ; preds = %catch.dispatch - catchendpad unwind to caller + catchret from %1 to label %catch.cont catch.cont: ; preds = %catch invoke void @g() diff --git a/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll index 31d567f6492..aa1feb7b171 100644 --- a/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll +++ b/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll @@ -12,7 +12,7 @@ entry: exit: ret void unreachable.unwind: - cleanuppad [] + cleanuppad within none [] unreachable } @@ -22,24 +22,21 @@ entry: invoke void @f() to label %exit unwind label %catch.pad catch.pad: - ; CHECK: catchpad [] - ; CHECK-NEXT: to label %catch.body unwind label %catch.end - %catch = catchpad [] - to label %catch.body unwind label %catch.end + %cs1 = catchswitch within none [label %catch.body] unwind label %unreachable.unwind + ; CHECK: catch.pad: + ; CHECK-NEXT: catchswitch within none [label %catch.body] unwind to caller catch.body: ; CHECK: catch.body: + ; CHECK-NEXT: catchpad within %cs1 ; CHECK-NEXT: call void @f() ; CHECK-NEXT: unreachable + %catch = catchpad within %cs1 [] call void @f() - catchret %catch to label %unreachable -catch.end: - ; CHECK: catch.end: - ; CHECK-NEXT: catchendpad unwind to caller - catchendpad unwind label %unreachable.unwind + catchret from %catch to label %unreachable exit: ret void unreachable.unwind: - cleanuppad [] + cleanuppad within none [] unreachable unreachable: unreachable @@ -51,24 +48,20 @@ entry: invoke void @f() to label %exit unwind label %cleanup.pad cleanup.pad: - ; CHECK: %cleanup = cleanuppad [] + ; CHECK: %cleanup = cleanuppad within none [] ; CHECK-NEXT: call void @f() ; CHECK-NEXT: unreachable - %cleanup = cleanuppad [] + %cleanup = cleanuppad within none [] invoke void @f() - to label %cleanup.ret unwind label %cleanup.end + to label %cleanup.ret unwind label %unreachable.unwind cleanup.ret: ; This cleanupret should be rewritten to unreachable, ; and merged into the pred block. - cleanupret %cleanup unwind label %unreachable.unwind -cleanup.end: - ; This cleanupendpad should be rewritten to unreachable, - ; causing the invoke to be rewritten to a call. - cleanupendpad %cleanup unwind label %unreachable.unwind + cleanupret from %cleanup unwind label %unreachable.unwind exit: ret void unreachable.unwind: - cleanuppad [] + cleanuppad within none [] unreachable } @@ -78,12 +71,12 @@ entry: invoke void @f() to label %exit unwind label %terminate.pad terminate.pad: - ; CHECK: terminatepad [] unwind to caller - terminatepad [] unwind label %unreachable.unwind + ; CHECK: terminatepad within none [] unwind to caller + terminatepad within none [] unwind label %unreachable.unwind exit: ret void unreachable.unwind: - cleanuppad [] + cleanuppad within none [] unreachable } @@ -94,14 +87,11 @@ entry: to label %exit unwind label %catch.pad catch.pad: - %catch = catchpad [] - 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 [] + catchret from %catch to label %exit exit: unreachable diff --git a/llvm/test/Transforms/Sink/catchswitch.ll b/llvm/test/Transforms/Sink/catchswitch.ll new file mode 100644 index 00000000000..2648f85f3eb --- /dev/null +++ b/llvm/test/Transforms/Sink/catchswitch.ll @@ -0,0 +1,37 @@ +; RUN: opt -sink -S < %s | FileCheck %s + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-pc-windows-msvc" + +define void @h() personality i32 (...)* @__CxxFrameHandler3 { +entry: + %call = call i32 @g(i32 1) readnone + invoke void @_CxxThrowException(i8* null, i8* null) noreturn + to label %unreachable unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %cs = catchswitch within none [label %catch] unwind to caller + +catch: ; preds = %catch.dispatch + %cp = catchpad within %cs [i8* null, i32 64, i8* null] + catchret from %cp to label %try.cont + +try.cont: ; preds = %catch + call void @k(i32 %call) + ret void + +unreachable: ; preds = %entry + unreachable +} + +declare x86_stdcallcc void @_CxxThrowException(i8*, i8*) + +declare i32 @__CxxFrameHandler3(...) + +declare i32 @g(i32) readnone + +declare void @k(i32) + +; CHECK-LABEL: define void @h( +; CHECK: call i32 @g(i32 1) +; CHECK-NEXT: invoke void @_CxxThrowException( diff --git a/llvm/test/Verifier/invalid-eh.ll b/llvm/test/Verifier/invalid-eh.ll new file mode 100644 index 00000000000..906b24a15c3 --- /dev/null +++ b/llvm/test/Verifier/invalid-eh.ll @@ -0,0 +1,38 @@ +; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s +; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s +; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s +; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s + +;T1: define void @f() { +;T1: entry: +;T1: catchret from undef to label %next +;T1: ; CHECK1: CatchReturnInst needs to be provided a CatchPad +;T1: next: +;T1: unreachable +;T1: } + +;T2: define void @f() { +;T2: entry: +;T2: %x = cleanuppad within none [] +;T2: ; catchret's first operand's operator must be catchpad +;T2: catchret from %x to label %entry +;T2: ; CHECK2: CatchReturnInst needs to be provided a CatchPad +;T2: } + +;T3: define void @f() { +;T3: entry: +;T3: cleanupret from undef unwind label %next +;T3: ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad +;T3: next: +;T3: unreachable +;T3: } + +;T4: define void @f() { +;T4: entry: +;T4: %cs = catchswitch within none [label %next] unwind to caller +;T4: next: +;T4: %x = catchpad within %cs [] +;T4: ; cleanupret first operand's operator must be cleanuppad +;T4: cleanupret from %x unwind to caller +;T4: ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad +;T4: } |