X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=test%2FCodeGen%2FWinEH%2Fwineh-cloning.ll;h=66a9132980fcbf1f22a47b46d81015f811d35097;hb=8cec2f281696a19faee58cd0749a70fbcc0fa218;hp=7d6529d6009bda131b2812c2b751147a4cf6e334;hpb=b73b3474ad5dac5bcf2e02836c51c169d71b6ada;p=oota-llvm.git diff --git a/test/CodeGen/WinEH/wineh-cloning.ll b/test/CodeGen/WinEH/wineh-cloning.ll index 7d6529d6009..66a9132980f 100644 --- a/test/CodeGen/WinEH/wineh-cloning.ll +++ b/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