diff options
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll')
-rw-r--r-- | llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll | 470 |
1 files changed, 0 insertions, 470 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll b/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll deleted file mode 100644 index f2e0114a2a3..00000000000 --- a/llvm/test/Transforms/SimplifyCFG/empty-cleanuppad.ll +++ /dev/null @@ -1,470 +0,0 @@ -; RUN: opt < %s -simplifycfg -S | FileCheck %s - -; ModuleID = 'cppeh-simplify.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc18.0.0" - - -; This case arises when two objects with empty destructors are cleaned up. -; -; void f1() { -; S a; -; S b; -; g(); -; } -; -; In this case, both cleanup pads can be eliminated and the invoke can be -; converted to a call. -; -; CHECK: define void @f1() -; CHECK: entry: -; CHECK: call void @g() -; CHECK: ret void -; CHECK-NOT: cleanuppad -; CHECK: } -; -define void @f1() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @g() to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - ret void - -ehcleanup: ; preds = %entry - %0 = cleanuppad within none [] - cleanupret from %0 unwind label %ehcleanup.1 - -ehcleanup.1: ; preds = %ehcleanup - %1 = cleanuppad within none [] - cleanupret from %1 unwind to caller -} - - -; This case arises when an object with an empty destructor must be cleaned up -; outside of a try-block and an object with a non-empty destructor must be -; cleaned up within the try-block. -; -; void f2() { -; S a; -; try { -; S2 b; -; g(); -; } catch (...) {} -; } -; -; In this case, the outermost cleanup pad can be eliminated and the catch block -; should unwind to the caller (that is, exception handling continues with the -; parent frame of the caller). -; -; CHECK: define void @f2() -; CHECK: entry: -; CHECK: invoke void @g() -; CHECK: ehcleanup: -; CHECK: cleanuppad within none -; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) -; CHECK: cleanupret from %0 unwind label %catch.dispatch -; CHECK: catch.dispatch: -; CHECK: catchswitch within none [label %catch] unwind to caller -; CHECK: catch: -; CHECK: catchpad -; CHECK: catchret -; CHECK-NOT: cleanuppad -; CHECK: } -; -define void @f2() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %b = alloca %struct.S2, align 1 - invoke void @g() to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - br label %try.cont - -ehcleanup: ; preds = %entry - %0 = cleanuppad within none [] - call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %b) - cleanupret from %0 unwind label %catch.dispatch - -catch.dispatch: ; preds = %ehcleanup - %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 - -catch: ; preds = %catch.dispatch - %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 - -try.cont: ; preds = %catchret.dest, %invoke.cont - ret void - -ehcleanup.1: - %2 = cleanuppad within none [] - cleanupret from %2 unwind to caller -} - - -; This case arises when an object with a non-empty destructor must be cleaned up -; outside of a try-block and an object with an empty destructor must be cleaned -; within the try-block. -; -; void f3() { -; S2 a; -; try { -; S b; -; g(); -; } catch (...) {} -; } -; -; In this case the inner cleanup pad should be eliminated and the invoke of g() -; should unwind directly to the catchpad. -; -; CHECK-LABEL: define void @f3() -; CHECK: entry: -; CHECK: invoke void @g() -; CHECK: to label %try.cont unwind label %catch.dispatch -; CHECK: catch.dispatch: -; 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: ehcleanup.1: -; CHECK: cleanuppad -; CHECK: call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) -; CHECK: cleanupret from %cp3 unwind to caller -; CHECK: } -; -define void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %a = alloca %struct.S2, align 1 - invoke void @g() to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - br label %try.cont - -ehcleanup: ; preds = %entry - %0 = cleanuppad within none [] - cleanupret from %0 unwind label %catch.dispatch - -catch.dispatch: ; preds = %ehcleanup - %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1 - -catch: ; preds = %catch.dispatch - %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 - -try.cont: ; preds = %catchret.dest, %invoke.cont - ret void - -ehcleanup.1: - %cp3 = cleanuppad within none [] - call void @"\01??1S2@@QEAA@XZ"(%struct.S2* %a) - cleanupret from %cp3 unwind to caller -} - - -; This case arises when an object with an empty destructor may require cleanup -; from either inside or outside of a try-block. -; -; void f4() { -; S a; -; g(); -; try { -; g(); -; } catch (...) {} -; } -; -; In this case, the cleanuppad should be eliminated, the invoke outside of the -; catch block should be converted to a call (that is, that is, exception -; handling continues with the parent frame of the caller).) -; -; CHECK-LABEL: define void @f4() -; CHECK: entry: -; CHECK: call void @g -; Note: The cleanuppad simplification will insert an unconditional branch here -; but it will be eliminated, placing the following invoke in the entry BB. -; CHECK: invoke void @g() -; CHECK: to label %try.cont unwind label %catch.dispatch -; CHECK: catch.dispatch: -; CHECK: catchswitch within none [label %catch] unwind to caller -; CHECK: catch: -; CHECK: catchpad -; CHECK: catchret -; CHECK-NOT: cleanuppad -; CHECK: } -; -define void @f4() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @g() - to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - invoke void @g() - to label %try.cont unwind label %catch.dispatch - -catch.dispatch: ; preds = %invoke.cont - %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup - -catch: ; preds = %catch.dispatch - %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 - -ehcleanup: - %cp2 = cleanuppad within none [] - cleanupret from %cp2 unwind to caller -} - -; This case tests simplification of an otherwise empty cleanup pad that contains -; a PHI node. -; -; int f6() { -; int state = 1; -; try { -; S a; -; g(); -; state = 2; -; g(); -; } catch (...) { -; return state; -; } -; return 0; -; } -; -; 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-LABEL: define i32 @f6() -; CHECK: entry: -; CHECK: invoke void @g() -; CHECK: invoke.cont: -; CHECK: invoke void @g() -; CHECK-NOT: ehcleanup: -; CHECK-NOT: cleanuppad -; CHECK: catch.dispatch: -; CHECK: %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] -; CHECK: } -define i32 @f6() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @g() - to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - invoke void @g() - to label %return unwind label %ehcleanup - -ehcleanup: ; preds = %invoke.cont, %entry - %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] - %0 = cleanuppad within none [] - cleanupret from %0 unwind label %catch.dispatch - -catch.dispatch: ; preds = %ehcleanup - %cs1 = catchswitch within none [label %catch] unwind to caller - -catch: ; preds = %catch.dispatch - %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 ] - ret i32 %retval.0 -} - -; This case tests another variation of simplification of an otherwise empty -; cleanup pad that contains a PHI node. -; -; int f7() { -; int state = 1; -; try { -; g(); -; state = 2; -; S a; -; g(); -; state = 3; -; g(); -; } catch (...) { -; return state; -; } -; return 0; -; } -; -; 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-LABEL: define i32 @f7() -; CHECK: entry: -; CHECK: invoke void @g() -; CHECK: invoke.cont: -; CHECK: invoke void @g() -; CHECK: invoke.cont.1: -; CHECK: invoke void @g() -; CHECK-NOT: ehcleanup: -; CHECK-NOT: cleanuppad -; CHECK: catch.dispatch: -; CHECK: %state.1 = phi i32 [ 1, %entry ], [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ] -; CHECK: } -define i32 @f7() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @g() - to label %invoke.cont unwind label %catch.dispatch - -invoke.cont: ; preds = %entry - invoke void @g() - to label %invoke.cont.1 unwind label %ehcleanup - -invoke.cont.1: ; preds = %invoke.cont - invoke void @g() - to label %return unwind label %ehcleanup - -ehcleanup: ; preds = %invoke.cont.1, %invoke.cont - %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ] - %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 ] - %cs1 = catchswitch within none [label %catch] unwind to caller - -catch: ; preds = %catch.dispatch - %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 ] - ret i32 %retval.0 -} - -; This case tests a scenario where an empty cleanup pad is not dominated by all -; of the predecessors of its successor, but the successor references a PHI node -; in the empty cleanup pad. -; -; Conceptually, the case being modeled is something like this: -; -; int f8() { -; int x = 1; -; try { -; S a; -; g(); -; x = 2; -; retry: -; g(); -; return -; } catch (...) { -; use_x(x); -; } -; goto retry; -; } -; -; While that C++ syntax isn't legal, the IR below is. -; -; In this case, the PHI node that is sunk from ehcleanup to catch.dispatch -; should have an incoming value entry for path from 'foo' that references the -; PHI node itself. -; -; CHECK-LABEL: define void @f8() -; CHECK: entry: -; CHECK: invoke void @g() -; CHECK: invoke.cont: -; CHECK: invoke void @g() -; CHECK-NOT: ehcleanup: -; CHECK-NOT: cleanuppad -; CHECK: catch.dispatch: -; CHECK: %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ], [ %x, %catch.cont ] -; CHECK: } -define void @f8() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @g() - to label %invoke.cont unwind label %ehcleanup - -invoke.cont: ; preds = %entry - invoke void @g() - to label %return unwind label %ehcleanup - -ehcleanup: ; preds = %invoke.cont, %entry - %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ] - %0 = cleanuppad within none [] - cleanupret from %0 unwind label %catch.dispatch - -catch.dispatch: ; preds = %ehcleanup, %catch.cont - %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 from %1 to label %catch.cont - -catch.cont: ; preds = %catch - invoke void @g() - to label %return unwind label %catch.dispatch - -return: ; preds = %invoke.cont, %catch.cont - ret void -} -; CHECK-LABEL: define i32 @f9() -; CHECK: entry: -; CHECK: invoke void @"\01??1S2@@QEAA@XZ"( -; CHECK-NOT: cleanuppad -; CHECK: catch.dispatch: -; CHECK: } -define i32 @f9() personality i32 (...)* @__CxxFrameHandler3 { -entry: - %s = alloca i8, align 1 - call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %s) - %bc = bitcast i8* %s to %struct.S2* - invoke void @"\01??1S2@@QEAA@XZ"(%struct.S2* %bc) - to label %try.cont unwind label %ehcleanup - -ehcleanup: - %cleanup.pad = cleanuppad within none [] - call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %s) - cleanupret from %cleanup.pad unwind label %catch.dispatch - -catch.dispatch: - %catch.switch = catchswitch within none [label %catch] unwind to caller - -catch: - %catch.pad = catchpad within %catch.switch [i8* null, i32 0, i8* null] - catchret from %catch.pad to label %try.cont - -try.cont: - ret i32 0 -} - -; CHECK-LABEL: define void @f10( -define void @f10(i32 %V) personality i32 (...)* @__CxxFrameHandler3 { -entry: - invoke void @g() - to label %unreachable unwind label %cleanup -; CHECK: call void @g() -; CHECK-NEXT: unreachable - -unreachable: - unreachable - -cleanup: - %cp = cleanuppad within none [] - switch i32 %V, label %cleanupret1 [ - i32 0, label %cleanupret2 - ] - -cleanupret1: - cleanupret from %cp unwind to caller - -cleanupret2: - cleanupret from %cp unwind to caller -} - -%struct.S = type { i8 } -%struct.S2 = type { i8 } -declare void @"\01??1S2@@QEAA@XZ"(%struct.S2*) -declare void @g() -declare void @use_x(i32 %x) - -declare i32 @__CxxFrameHandler3(...) - -declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) -declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) |