majnemer created this revision.
majnemer added a reviewer: rnk.
majnemer added a subscriber: cfe-commits.
majnemer added a dependency: D15139: [IR] Reformulate LLVM's EH funclet IR.

Depends on D15139.

http://reviews.llvm.org/D15140

Files:
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/CGCleanup.cpp
  lib/CodeGen/CGCleanup.h
  lib/CodeGen/CGException.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/EHScopeStack.h
  lib/CodeGen/MicrosoftCXXABI.cpp
  test/CodeGen/exceptions-seh-finally.c
  test/CodeGen/exceptions-seh-leave.c
  test/CodeGen/exceptions-seh.c
  test/CodeGenCXX/exceptions-cxx-new.cpp
  test/CodeGenCXX/exceptions-seh.cpp
  test/CodeGenCXX/microsoft-abi-arg-order.cpp
  test/CodeGenCXX/microsoft-abi-eh-catch.cpp
  test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
  test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
  test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
  test/CodeGenCXX/microsoft-abi-try-throw.cpp

Index: test/CodeGenCXX/microsoft-abi-try-throw.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-try-throw.cpp
+++ test/CodeGenCXX/microsoft-abi-try-throw.cpp
@@ -19,7 +19,7 @@
     external(); // TRY: invoke void @"\01?external@@YAXXZ"
   } catch (int) {
     rv = 1;
-    // TRY: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+    // TRY: catchpad %0 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
     // TRY: catchret
   }
 #endif
@@ -39,7 +39,7 @@
     external();
   } catch (const int *) {
   }
-  // TRY: catchpad [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
+  // TRY: catchpad %0 [%rtti.TypeDescriptor4* @"\01??_R0PAH@8", i32 1, i8* null]
   // TRY: catchret
 }
 #endif
Index: test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
+++ test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
@@ -39,7 +39,7 @@
 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
 
 // CHECK:     [[lpad:.*]]:
-// CHECK-NEXT: cleanuppad []
+// CHECK-NEXT: cleanuppad none []
 // CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
 // CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
 // CHECK-NEXT:  store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
@@ -75,7 +75,7 @@
 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
 //
 // CHECK:     [[lpad]]:
-// CHECK-NEXT: cleanuppad []
+// CHECK-NEXT: cleanuppad none []
 // CHECK:       call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ")
 // CHECK-NEXT:  cleanupret {{.*}} unwind to caller
   return s;
Index: test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
+++ test/CodeGenCXX/microsoft-abi-eh-terminate.cpp
@@ -9,6 +9,6 @@
 // CHECK-LABEL: define void @"\01?never_throws@@YAXXZ"()
 // CHECK-SAME:          personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
 // CHECK:      invoke void @"\01?may_throw@@YAXXZ"()
-// MSVC2013:      terminatepad [void ()* @"\01?terminate@@YAXXZ"]
-// MSVC2015:      terminatepad [void ()* @__std_terminate]
+// MSVC2013:      terminatepad none [void ()* @"\01?terminate@@YAXXZ"]
+// MSVC2015:      terminatepad none [void ()* @__std_terminate]
 // CHECK-NEXT: unreachable
Index: test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -27,7 +27,7 @@
 //
 //    There should be one dtor call for unwinding from the second getA.
 // WIN32:   cleanuppad
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline:[0-9]+]]
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
 // WIN32-NOT: @"\01??1A@@QAE@XZ"
 // WIN32: }
 
@@ -62,7 +62,7 @@
 //        Conditionally destroy arg1.
 // WIN32:   %[[cond:.*]] = load i1, i1* %[[isactive]]
 // WIN32:   br i1 %[[cond]]
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) #[[noinline]]
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]])
 // WIN32: }
 
 // Test putting the cleanups inside a conditional.
@@ -85,7 +85,7 @@
 // WIN32:   call i32 @"\01?CouldThrow@@YAHXZ"()
 //
 //        Only one dtor in the invoke for arg1
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
 // WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"
 // WIN32: }
 
@@ -126,7 +126,7 @@
 //        Somewhere in the landing pad soup, we conditionally destroy arg1.
 // WIN32:   %[[isactive:.*]] = load i1, i1* %[[arg1_cond]]
 // WIN32:   br i1 %[[isactive]]
-// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32:   call x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}})
 // WIN32: }
 
 namespace crash_on_partial_destroy {
@@ -164,7 +164,7 @@
 // WIN32:      getelementptr inbounds i8, i8* %{{.*}}, i32 4
 // WIN32-NOT:  load
 // WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
-// WIN32:      call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}}) #[[noinline]]
+// WIN32:      call x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ"({{.*}})
 // WIN32: }
 }
 
@@ -187,7 +187,7 @@
 //
 // WIN32: [[lpad]]
 // WIN32-NEXT: cleanuppad
-// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}}) #[[noinline]]
+// WIN32: call x86_thiscallcc void @"\01??1C@dont_call_terminate@@QAE@XZ"({{.*}})
 }
 
 namespace noexcept_false_dtor {
@@ -204,9 +204,5 @@
 // WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"()
 // WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
 // WIN32: cleanuppad
-// WIN32: invoke x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}}) #[[invoke_noinline:[0-9]+]]
+// WIN32: call x86_thiscallcc void @"\01??1D@noexcept_false_dtor@@QAE@XZ"(%"struct.noexcept_false_dtor::D"* %{{.*}})
 // WIN32: cleanupret
-// WIN32: cleanupendpad
-
-// WIN32: attributes #[[noinline]] = { noinline nounwind }
-// WIN32: attributes #[[invoke_noinline]] = { noinline }
Index: test/CodeGenCXX/microsoft-abi-eh-catch.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-eh-catch.cpp
+++ test/CodeGenCXX/microsoft-abi-eh-catch.cpp
@@ -19,11 +19,14 @@
 
 // WIN64-LABEL: define void @catch_all()
 // WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
+// WIN64-NEXT: to label %[[cont:[^ ]*]] unwind label %[[catchswitch_lpad:[^ ]*]]
 //
-// WIN64: [[lpad]]
-// WIN64: catchpad [i8* null, i32 64, i8* null]
-// WIN64:     to label %[[catchit:[^ ]*]] unwind label %{{.*}}
+// WIN64: [[catchswitch_lpad]]
+// WIN64: %[[catchswitch:[^ ]*]] = catchswitch none, unwind to caller [label %[[catchpad_lpad:[^ ]*]]]
+//
+// WIN64: [[catchpad_lpad]]
+// WIN64: catchpad %[[catchswitch]] [i8* null, i32 64, i8* null]
+// WIN64: br label %[[catchit:[^ ]*]]
 //
 // WIN64: [[catchit]]
 // WIN64: call void @recover()
@@ -47,7 +50,7 @@
 }
 
 // WIN64-LABEL: define void @catch_int()
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
+// WIN64: catchpad %{{[^ ]*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %[[e_addr:[^\]]*]]]
 //
 // The catchpad instruction starts the lifetime of 'e'. Unfortunately, that
 // leaves us with nowhere to put lifetime.start, so we don't emit lifetime
@@ -69,7 +72,7 @@
 }
 
 // WIN64-LABEL: define void @catch_int_unnamed()
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: catchpad %{{.*}} [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
 // WIN64: catchret
 
 struct A {
@@ -96,7 +99,7 @@
 
 // WIN64-LABEL: define void @catch_a_byval()
 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A
-// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
+// WIN64: catchpad %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, %struct.A* %[[e_addr]]]
 // WIN64: %[[e_i8:[^ ]*]] = bitcast %struct.A* %[[e_addr]] to i8*
 // WIN64: call void @handle_exception(i8* %[[e_i8]])
 // WIN64: catchret
@@ -111,7 +114,7 @@
 
 // WIN64-LABEL: define void @catch_a_ref()
 // WIN64: %[[e_addr:[^ ]*]] = alloca %struct.A*
-// WIN64: catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
+// WIN64: catchpad %{{[^ ]*}} [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 8, %struct.A** %[[e_addr]]]
 // WIN64: %[[eptr:[^ ]*]] = load %struct.A*, %struct.A** %[[e_addr]]
 // WIN64: %[[eptr_i8:[^ ]*]] = bitcast %struct.A* %[[eptr]] to i8*
 // WIN64: call void @handle_exception(i8* %[[eptr_i8]])
@@ -139,32 +142,32 @@
 
 // WIN64-LABEL: define void @catch_nested()
 // WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %{{.*}} unwind label %[[lp1:[^ ]*]]
+// WIN64-NEXT: to label %{{.*}} unwind label %[[catchswitch_outer:[^ ]*]]
+//
+// WIN64: [[catchswitch_outer]]
+// WIN64: %[[catchswitch_outer_scope:[^ ]*]] = catchswitch none, unwind to caller [label %[[catch_int_outer:[^ ]*]]]
 //
-// WIN64: [[lp1]]
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// WIN64:     to label %[[catchit:[^ ]*]] unwind label %{{.*}}
+// WIN64: [[catch_int_outer]]
+// WIN64: %[[catchpad:[^ ]*]] = catchpad %[[catchswitch_outer_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: br label %[[catchit:[^ ]*]]
 //
 // WIN64: [[catchit]]
 // WIN64: invoke void @might_throw()
-// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[lp2:[^ ]*]]
+// WIN64-NEXT: to label %[[cont2:[^ ]*]] unwind label %[[catchswitch_inner:[^ ]*]]
 //
-// WIN64: [[lp2]]
-// WIN64: catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// WIN64:     to label %[[catchit2:[^ ]*]] unwind label %[[endcatch2:[^ ]*]]
+// WIN64: [[catchswitch_inner]]
+// WIN64: %[[catchswitch_inner_scope:[^ ]*]] = catchswitch %[[catchpad]], unwind to caller [label %[[catch_int_inner:[^ ]*]]]
 //
-// WIN64: [[catchit2]]
-// WIN64-NEXT: invoke void @might_throw()
-// WIN64-NEXT:    to label %[[catchret1:[^ ]*]] unwind label %[[endcatch2]]
+// WIN64: [[catch_int_inner]]
+// WIN64: catchpad %[[catchswitch_inner_scope]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// WIN64: br label %[[catchit2:[^ ]*]]
 //
-// WIN64: [[catchret1]]
+// WIN64: [[catchit2]]
+// WIN64-NEXT: call void @might_throw()
 // WIN64: catchret {{.*}} to label %[[catchret2:[^ ]*]]
 //
 // WIN64: [[catchret2]]
 // WIN64: catchret {{.*}} to label %[[mainret:[^ ]*]]
 //
 // WIN64: [[mainret]]
 // WIN64: ret void
-//
-// WIN64: [[endcatch2]]
-// WIN64: catchendpad unwind label %{{.*}}
Index: test/CodeGenCXX/microsoft-abi-arg-order.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -52,7 +52,7 @@
 // X86: ret void
 //
 //   lpad2:
-// X86: cleanuppad []
+// X86: cleanuppad none []
 // X86: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg2]])
 // X86: cleanupret
 //
@@ -68,7 +68,7 @@
 // X64: ret void
 //
 //   lpad2:
-// X64: cleanuppad []
+// X64: cleanuppad none []
 // X64: call void @"\01??1A@@QEAA@XZ"(%struct.A* %[[arg2]])
 // X64: cleanupret
 //
Index: test/CodeGenCXX/exceptions-seh.cpp
===================================================================
--- test/CodeGenCXX/exceptions-seh.cpp
+++ test/CodeGenCXX/exceptions-seh.cpp
@@ -61,7 +61,10 @@
 // CHECK:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
 //
 // CHECK: [[lpad]]
-// CHECK-NEXT: catchpad
+// CHECK-NEXT: %[[switch:.*]] = catchswitch none, unwind to caller [label %[[cpad:.*]]]
+//
+// CHECK: [[cpad]]
+// CHECK-NEXT: catchpad %[[switch]]
 // CHECK: catchret {{.*}} label %[[except:[^ ]*]]
 //
 // CHECK: [[except]]
@@ -119,7 +122,7 @@
 // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
 // CHECK: invoke void @might_throw()
 //
-// CHECK: catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
+// CHECK: catchpad {{.*}} [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_seh_in_inline_func@@" to i8*)]
 //
 // CHECK: invoke void @might_throw()
 //
@@ -129,7 +132,7 @@
 //
 // CHECK: cleanuppad
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0@0@use_seh_in_inline_func@@"(i8 1, i8* %[[fp]])
 
 // CHECK-LABEL: define internal i32 @"\01?filt$0@0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
 // CHECK: icmp eq i32 %{{.*}}, 424242
Index: test/CodeGenCXX/exceptions-cxx-new.cpp
===================================================================
--- test/CodeGenCXX/exceptions-cxx-new.cpp
+++ test/CodeGenCXX/exceptions-cxx-new.cpp
@@ -14,17 +14,17 @@
 
 // CHECK-LABEL: define void @"\01?test_catch@@YAXXZ"(
 // CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 1)
-// CHECK:         to label %[[NORMAL:.*]] unwind label %[[CATCH_INT:.*]]
+// CHECK:         to label %[[NORMAL:.*]] unwind label %[[CATCHSWITCH:.*]]
+
+// CHECK: [[CATCHSWITCH]]
+// CHECK:   %[[CATCHSWITCHPAD:.*]] = catchswitch none, unwind to caller [label %[[CATCH_INT:.*]], label %[[CATCH_DOUBLE:.*]]]
 
 // CHECK: [[CATCH_INT]]
-// CHECK:   %[[CATCHPAD_INT:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-// CHECK:         to label %[[CATCH_INT_HANDLER:.*]] unwind label %[[CATCH_DOUBLE:.*]]
+// CHECK:   %[[CATCHPAD_INT:.*]] = catchpad %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
+// CHECK:   br label %[[CATCH_INT_HANDLER:.*]]
 
 // CHECK: [[CATCH_INT_HANDLER]]
-// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 2)
-// CHECK:           to label %[[CATCH_INT_DONE:.*]] unwind label %[[CATCHENDPAD:.*]]
-
-// CHECK: [[CATCH_INT_DONE]]
+// CHECK:   call i32 @"\01?f@@YAHH@Z"(i32 2)
 // CHECK:   catchret %[[CATCHPAD_INT]] to label %[[LEAVE_INT_CATCH:.*]]
 
 // CHECK: [[LEAVE_INT_CATCH]]
@@ -34,22 +34,16 @@
 // CHECK:   ret void
 
 // CHECK: [[CATCH_DOUBLE]]
-// CHECK:   %[[CATCHPAD_DOUBLE:.*]] = catchpad [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
-// CHECK:           to label %[[CATCH_DOUBLE_HANDLER:.*]] unwind label %[[CATCHENDPAD]]
+// CHECK:   %[[CATCHPAD_DOUBLE:.*]] = catchpad %[[CATCHSWITCHPAD]] [%rtti.TypeDescriptor2* @"\01??_R0N@8", i32 0, i8* null]
+// CHECK:   br label %[[CATCH_DOUBLE_HANDLER:.*]]
 
 // CHECK: [[CATCH_DOUBLE_HANDLER]]
-// CHECK:   invoke i32 @"\01?f@@YAHH@Z"(i32 3)
-// CHECK:           to label %[[CATCH_DOUBLE_DONE:.*]] unwind label %[[CATCHENDPAD]]
-
-// CHECK: [[CATCH_DOUBLE_DONE]]
+// CHECK:   call i32 @"\01?f@@YAHH@Z"(i32 3)
 // CHECK:   catchret %[[CATCHPAD_DOUBLE]] to label %[[LEAVE_DOUBLE_CATCH:.*]]
 
 // CHECK: [[LEAVE_DOUBLE_CATCH]]
 // CHECK:   br label %[[LEAVE_FUNC]]
 
-// CHECK: [[CATCHENDPAD]]
-// CHECK:   catchendpad unwind to caller
-
 // CHECK: [[NORMAL]]
 // CHECK:   br label %[[LEAVE_FUNC]]
 
@@ -71,7 +65,7 @@
 // CHECK:   ret void
 
 // CHECK: [[CLEANUP]]
-// CHECK:   %[[CLEANUPPAD:.*]] = cleanuppad []
+// CHECK:   %[[CLEANUPPAD:.*]] = cleanuppad none []
 // CHECK:   call x86_thiscallcc void @"\01??_DCleanup@@QAE@XZ"(
 // CHECK:   cleanupret %[[CLEANUPPAD]] unwind to caller
 
@@ -84,5 +78,5 @@
 // CHECK:   ret void
 
 // CHECK: [[TERMINATE]]
-// CHECK:   terminatepad [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
+// CHECK:   terminatepad none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
 
Index: test/CodeGen/exceptions-seh.c
===================================================================
--- test/CodeGen/exceptions-seh.c
+++ test/CodeGen/exceptions-seh.c
@@ -34,9 +34,9 @@
 // CHECK:       to label %{{.*}} unwind label %[[catchpad:[^ ]*]]
 //
 // CHECK: [[catchpad]]
-// X64: %[[padtoken:[^ ]*]] = catchpad [i8* null]
-// X86: %[[padtoken:[^ ]*]] = catchpad [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
-// CHECK-NEXT:    to label %[[exceptret:[^ ]*]] unwind label
+// X64: %[[padtoken:[^ ]*]] = catchpad %{{[^ ]*}} [i8* null]
+// X86: %[[padtoken:[^ ]*]] = catchpad %{{[^ ]*}} [i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*)]
+// CHECK-NEXT:    br label %[[exceptret:[^ ]*]]
 //
 // CHECK: [[exceptret]]
 // CHECK: catchret %[[padtoken]] to label %[[except:[^ ]*]]
@@ -85,7 +85,7 @@
 // CHECK: store i32 42, i32* %[[r]]
 // CHECK: invoke void @j() #[[NOINLINE]]
 //
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
+// CHECK: catchpad %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*)]
 // CHECK: store i32 13, i32* %[[r]]
 //
 // CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
@@ -121,37 +121,43 @@
 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
 // CHECK: store i32 42, i32* %[[r:[^ ,]*]]
 // CHECK: invoke void @j() #[[NOINLINE]]
-// CHECK:       to label %[[cont:[^ ]*]] unwind label %[[cpad_inner:[^ ]*]]
+// CHECK:       to label %[[cont:[^ ]*]] unwind label %[[cswitch_inner:[^ ]*]]
 //
-// CHECK: [[cpad_inner]]
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
-// CHECK-NEXT: to label %[[exceptret_inner:[^ ]*]] unwind label %[[cpad_outer:[^ ]*]]
-//
-// CHECK: [[exceptret_inner]]
-// CHECK: catchret {{.*}} to label %[[except_inner:[^ ]*]]
-//
-// CHECK: [[except_inner]]
-// CHECK: store i32 123, i32* %[[r]]
-// CHECK: br label %[[inner_try_cont:[^ ]*]]
+// CHECK: [[cswitch_inner]]
+// CHECK: %[[cs_inner:[^ ]*]] = catchswitch none, unwind label %[[cswitch_outer:[^ ]*]] [label %[[cpad_inner:[^ ]*]]]
 //
-// CHECK: [[inner_try_cont]]
-// CHECK: br label %[[outer_try_cont:[^ ]*]]
+// CHECK: [[cswitch_outer]]
+// CHECK: %[[cs_outer:[^ ]*]] = catchswitch none, unwind to caller [label %[[cpad_outer:[^ ]*]]]
 //
 // CHECK: [[cpad_outer]]
-// CHECK: catchpad [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
-// CHECK-NEXT: to label %[[exceptret_outer:[^ ]*]] unwind label
+// CHECK: catchpad %{{[^ ]*}} [i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)]
+// CHECK-NEXT: br label %[[exceptret_outer:[^ ]*]]
 //
 // CHECK: [[exceptret_outer]]
 // CHECK: catchret {{.*}} to label %[[except_outer:[^ ]*]]
 //
 // CHECK: [[except_outer]]
 // CHECK: store i32 456, i32* %[[r]]
-// CHECK: br label %[[outer_try_cont]]
+// CHECK: br label %[[outer_try_cont:[^ ]*]]
 //
 // CHECK: [[outer_try_cont]]
 // CHECK: %[[r_load:[^ ]*]] = load i32, i32* %[[r]]
 // CHECK: ret i32 %[[r_load]]
 //
+// CHECK: [[cpad_inner]]
+// CHECK: catchpad %[[cs_inner]] [i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)]
+// CHECK-NEXT: br label %[[exceptret_inner:[^ ]*]]
+//
+// CHECK: [[exceptret_inner]]
+// CHECK: catchret {{.*}} to label %[[except_inner:[^ ]*]]
+//
+// CHECK: [[except_inner]]
+// CHECK: store i32 123, i32* %[[r]]
+// CHECK: br label %[[inner_try_cont:[^ ]*]]
+//
+// CHECK: [[inner_try_cont]]
+// CHECK: br label %[[outer_try_cont]]
+//
 // CHECK: [[cont]]
 // CHECK: store i32 0, i32* %[[r]]
 // CHECK: br label %[[inner_try_cont]]
@@ -193,14 +199,10 @@
 // CHECK: ret i32
 //
 // CHECK: [[cleanuppad]]
-// CHECK: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK: %[[padtoken:[^ ]*]] = cleanuppad none []
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK:     to label %[[cleanupcont:[^ ]*]] unwind label %[[cleanupend:[^ ]*]]
-// CHECK: [[cleanupcont]]
+// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
 // CHECK: cleanupret %[[padtoken]] unwind to caller
-// CHECK: [[cleanupend]]
-// CHECK: cleanupendpad %[[padtoken]] unwind to caller
 
 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
 // CHECK:   call i8* @llvm.localrecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0)
Index: test/CodeGen/exceptions-seh-leave.c
===================================================================
--- test/CodeGen/exceptions-seh-leave.c
+++ test/CodeGen/exceptions-seh-leave.c
@@ -160,20 +160,17 @@
 // CHECK-NEXT: cleanuppad
 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
 // CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i8 1, i8* %[[fp]])
-// CHECK-NEXT:       to label %[[g1_resume:.*]] unwind label %[[cleanupend:[^ ]*]]
+// CHECK-NEXT:       to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
 // CHECK: cleanupret {{.*}} unwind label %[[g2_lpad]]
 
 // CHECK: [[g2_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
 // CHECK: catchret
 // CHECK: br label %[[trycont]]
 
 // CHECK: [[trycont]]
 // CHECK-NEXT: ret i32 1
 
-// CHECK: [[cleanupend]]
-// CHECK-NEXT: cleanupendpad {{.*}} unwind label %[[g2_lpad]]
-
 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___except___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: call void @g()
 // CHECK: unreachable
@@ -203,14 +200,14 @@
 // CHECK-NEXT:       to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
 
 // CHECK: [[g1_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
 // CHECK: catchret {{.*}} to label %[[except:[^ ]*]]
 // CHECK: [[except]]
 // CHECK: invoke void @g()
 // CHECK-NEXT:       to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
 
 // CHECK: [[g2_lpad]]
-// CHECK: catchpad [i8* null]
+// CHECK: catchpad {{.*}} [i8* null]
 // CHECK: catchret
 // CHECK: br label %[[trycont4:[^ ]*]]
 
@@ -280,7 +277,7 @@
 // CHECK: [[g2_lpad]]
 // CHECK: cleanuppad
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i8 1, i8* %[[fp]])
 // CHECK: cleanupret {{.*}} unwind to caller
 
 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___except@@"(i8 %abnormal_termination, i8* %frame_pointer)
@@ -323,20 +320,17 @@
 // CHECK-NEXT: ret i32 1
 
 // CHECK: [[g1_lpad]]
-// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad none []
 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
 // CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
-// CHECK-NEXT:       to label %[[finally_cont2:.*]] unwind label %[[endcleanup:[^ ]*]]
+// CHECK-NEXT:       to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
 // CHECK: [[finally_cont2]]
 // CHECK: cleanupret %[[padtoken]] unwind label %[[g2_lpad]]
 
-// CHECK: [[endcleanup]]
-// CHECK-NEXT: cleanupendpad %[[padtoken]] unwind label %[[g2_lpad]]
-
 // CHECK: [[g2_lpad]]
-// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad []
+// CHECK-NEXT: %[[padtoken:[^ ]*]] = cleanuppad none []
 // CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
+// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
 // CHECK: cleanupret %[[padtoken]] unwind to caller
 
 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
Index: test/CodeGen/exceptions-seh-finally.c
===================================================================
--- test/CodeGen/exceptions-seh-finally.c
+++ test/CodeGen/exceptions-seh-finally.c
@@ -25,12 +25,8 @@
 // CHECK: [[lpad]]
 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK-NEXT: cleanupret %[[pad]] unwind to caller
 
 // CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}})
 // CHECK: call void @cleanup()
@@ -95,12 +91,8 @@
 // CHECK: [[lpad]]
 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.localaddress()
-// CHECK: invoke void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK-NEXT: cleanupret %[[pad]] unwind to caller
 
 // CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
 // CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
@@ -141,12 +133,8 @@
 //
 // CHECK: [[lpad]]
 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
+// CHECK-NEXT: cleanupret %[[pad]] unwind to caller
 
 // CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}})
 // CHECK: call void @abort()
@@ -189,12 +177,8 @@
 //
 // CHECK: [[lpad]]
 // CHECK-NEXT: %[[pad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
-// CHECK-NEXT: to label %{{.*}} unwind label %[[end:[^ ]*]]
-// CHECK: cleanupret %[[pad]] unwind to caller
-//
-// CHECK: [[end]]
-// CHECK: cleanupendpad %[[pad]] unwind to caller
+// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
+// CHECK-NEXT: cleanupret %[[pad]] unwind to caller
 
 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}})
 // CHECK: ret void
@@ -231,24 +215,15 @@
 // CHECK: [[lpad1]]
 // CHECK-NEXT: %[[innerpad:[^ ]*]] = cleanuppad
 // CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}})
-// CHECK-NEXT:     to label %[[innercleanupretbb:[^ ]*]] unwind label %[[innerend:[^ ]*]]
+// CHECK-NEXT:    label %[[innercleanupretbb:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
 //
 // CHECK: [[innercleanupretbb]]
 // CHECK-NEXT: cleanupret %[[innerpad]] unwind label %[[lpad2]]
 //
-// CHECK: [[innerend]]
-// CHECK-NEXT: cleanupendpad %[[innerpad]] unwind label %[[lpad2:[^ ]*]]
-//
 // CHECK: [[lpad2]]
 // CHECK-NEXT: %[[outerpad:[^ ]*]] = cleanuppad
-// CHECK: invoke void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
-// CHECK-NEXT:     to label %[[outercleanupretbb:[^ ]*]] unwind label %[[outerend:[^ ]*]]
-//
-// CHECK: [[outercleanupretbb]]
+// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
 // CHECK-NEXT: cleanupret %[[outerpad]] unwind to caller
-//
-// CHECK: [[outerend]]
-// CHECK-NEXT: cleanupendpad %[[outerpad]] unwind to caller
 
 // CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}})
 // CHECK: ret void
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -897,6 +897,7 @@
       CGF.Builder.GetInsertBlock()->getSinglePredecessor();
   llvm::CatchPadInst *CPI =
       cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+  CGF.CurrentFuncletPad = CPI;
 
   // If this is a catch-all or the catch parameter is unnamed, we don't need to
   // emit an alloca to the object.
Index: lib/CodeGen/EHScopeStack.h
===================================================================
--- lib/CodeGen/EHScopeStack.h
+++ lib/CodeGen/EHScopeStack.h
@@ -334,10 +334,6 @@
   /// Pops a terminate handler off the stack.
   void popTerminate();
 
-  void pushPadEnd(llvm::BasicBlock *PadEndBB);
-
-  void popPadEnd();
-
   // Returns true iff the current scope is either empty or contains only
   // lifetime markers, i.e. no real cleanup code
   bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -279,8 +279,6 @@
   /// finally block or filter expression.
   bool IsOutlinedSEHHelper;
 
-  bool IsCleanupPadScope = false;
-
   const CodeGen::CGBlockInfo *BlockInfo;
   llvm::Value *BlockPointer;
 
@@ -295,6 +293,8 @@
   llvm::SmallVector<char, 256> LifetimeExtendedCleanupStack;
   llvm::SmallVector<const JumpDest *, 2> SEHTryEpilogueStack;
 
+  llvm::Instruction *CurrentFuncletPad = nullptr;
+
   /// Header for data within LifetimeExtendedCleanupStack.
   struct LifetimeExtendedCleanupHeader {
     /// The size of the following cleanup object.
@@ -375,7 +375,9 @@
   bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
 
   /// Returns true while emitting a cleanuppad.
-  bool isCleanupPadScope() const { return IsCleanupPadScope; }
+  bool isCleanupPadScope() const {
+    return CurrentFuncletPad && isa<llvm::CleanupPadInst>(CurrentFuncletPad);
+  }
 
   /// pushFullExprCleanup - Push a cleanup to be run at the end of the
   /// current full-expression.  Safe against the possibility that
Index: lib/CodeGen/CGException.cpp
===================================================================
--- lib/CodeGen/CGException.cpp
+++ lib/CodeGen/CGException.cpp
@@ -871,58 +871,53 @@
   return lpad;
 }
 
-static llvm::BasicBlock *emitCatchPadBlock(CodeGenFunction &CGF,
-                                           EHCatchScope &CatchScope) {
+static void emitCatchPadBlock(CodeGenFunction &CGF, EHCatchScope &CatchScope) {
   llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
   assert(DispatchBlock);
 
   CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
   CGF.EmitBlockAfterUses(DispatchBlock);
 
-  // Figure out the next block.
-  llvm::BasicBlock *NextBlock = nullptr;
+  llvm::Value *OuterScope = CGF.CurrentFuncletPad;
+  if (!OuterScope)
+    OuterScope = llvm::ConstantTokenNone::get(CGF.getLLVMContext());
+  llvm::BasicBlock *UnwindBB =
+      CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope());
+
+  unsigned NumHandlers = CatchScope.getNumHandlers();
+  llvm::CatchSwitchInst *CatchSwitch =
+      CGF.Builder.CreateCatchSwitch(OuterScope, UnwindBB, NumHandlers);
 
   // Test against each of the exception types we claim to catch.
-  for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) {
+  for (unsigned I = 0; I < NumHandlers; ++I) {
     const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
 
     CatchTypeInfo TypeInfo = Handler.Type;
     if (!TypeInfo.RTTI)
       TypeInfo.RTTI = llvm::Constant::getNullValue(CGF.VoidPtrTy);
 
-    // If this is the last handler, we're at the end, and the next
-    // block is the block for the enclosing EH scope.
-    if (I + 1 == E) {
-      NextBlock = CGF.createBasicBlock("catchendblock");
-      CGBuilderTy(CGF, NextBlock).CreateCatchEndPad(
-          CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()));
-    } else {
-      NextBlock = CGF.createBasicBlock("catch.dispatch");
-    }
+    llvm::BasicBlock *CatchPadBB = CGF.createBasicBlock("catch");
+    CGF.EmitBlock(CatchPadBB);
 
     if (EHPersonality::get(CGF).isMSVCXXPersonality()) {
-      CGF.Builder.CreateCatchPad(Handler.Block, NextBlock,
-                                 {TypeInfo.RTTI,
-                                  CGF.Builder.getInt32(TypeInfo.Flags),
-                                  llvm::Constant::getNullValue(CGF.VoidPtrTy)});
+      CGF.Builder.CreateCatchPad(
+          CatchSwitch, {TypeInfo.RTTI, CGF.Builder.getInt32(TypeInfo.Flags),
+                        llvm::Constant::getNullValue(CGF.VoidPtrTy)});
     } else {
-      CGF.Builder.CreateCatchPad(Handler.Block, NextBlock, {TypeInfo.RTTI});
+      CGF.Builder.CreateCatchPad(CatchSwitch, {TypeInfo.RTTI});
     }
 
-    // Otherwise we need to emit and continue at that block.
-    CGF.EmitBlock(NextBlock);
+    CGF.Builder.CreateBr(Handler.Block);
+
+    CatchSwitch->addHandler(CatchPadBB);
   }
   CGF.Builder.restoreIP(SavedIP);
-
-  return NextBlock;
 }
 
 /// Emit the structure of the dispatch block for the given catch scope.
 /// It is an invariant that the dispatch block already exists.
-/// If the catchblock instructions are used for EH dispatch, then the basic
-/// block holding the final catchendblock instruction is returned.
-static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
-                                                EHCatchScope &catchScope) {
+static void emitCatchDispatchBlock(CodeGenFunction &CGF,
+                                   EHCatchScope &catchScope) {
   if (EHPersonality::get(CGF).usesFuncletPads())
     return emitCatchPadBlock(CGF, catchScope);
 
@@ -934,7 +929,7 @@
   if (catchScope.getNumHandlers() == 1 &&
       catchScope.getHandler(0).isCatchAll()) {
     assert(dispatchBlock == catchScope.getHandler(0).Block);
-    return nullptr;
+    return;
   }
 
   CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
@@ -992,12 +987,11 @@
     // If the next handler is a catch-all, we're completely done.
     if (nextIsEnd) {
       CGF.Builder.restoreIP(savedIP);
-      return nullptr;
+      return;
     }
     // Otherwise we need to emit and continue at that block.
     CGF.EmitBlock(nextBlock);
   }
-  return nullptr;
 }
 
 void CodeGenFunction::popCatchScope() {
@@ -1020,7 +1014,7 @@
   }
 
   // Emit the structure of the EH dispatch for this catch.
-  llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope);
+  emitCatchDispatchBlock(*this, CatchScope);
 
   // Copy the handler blocks off before we pop the EH stack.  Emitting
   // the handlers might scribble on this memory.
@@ -1043,9 +1037,6 @@
     doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
                         isa<CXXConstructorDecl>(CurCodeDecl);
 
-  if (CatchEndBlockBB)
-    EHStack.pushPadEnd(CatchEndBlockBB);
-
   // Perversely, we emit the handlers backwards precisely because we
   // want them to appear in source order.  In all of these cases, the
   // catch block will have exactly one predecessor, which will be a
@@ -1065,6 +1056,8 @@
     RunCleanupsScope CatchScope(*this);
 
     // Initialize the catch variable and set up the cleanups.
+    SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+        CurrentFuncletPad);
     CGM.getCXXABI().emitBeginCatch(*this, C);
 
     // Emit the PGO counter increment.
@@ -1098,8 +1091,6 @@
 
   EmitBlock(ContBB);
   incrementProfileCounter(&S);
-  if (CatchEndBlockBB)
-    EHStack.popPadEnd();
 }
 
 namespace {
@@ -1338,7 +1329,11 @@
   TerminateHandler = createBasicBlock("terminate.handler");
   Builder.SetInsertPoint(TerminateHandler);
   if (EHPersonality::get(*this).usesFuncletPads()) {
-    Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn());
+    llvm::Value *OuterScope = CurrentFuncletPad;
+    if (!OuterScope)
+      OuterScope = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+    Builder.CreateTerminatePad(OuterScope, /*UnwindBB=*/nullptr,
+                               {CGM.getTerminateFn()});
   } else {
     llvm::Value *Exn = nullptr;
     if (getLangOpts().CPlusPlus)
Index: lib/CodeGen/CGCleanup.h
===================================================================
--- lib/CodeGen/CGCleanup.h
+++ lib/CodeGen/CGCleanup.h
@@ -587,14 +587,6 @@
   deallocate(EHTerminateScope::getSize());
 }
 
-inline void EHScopeStack::popPadEnd() {
-  assert(!empty() && "popping exception stack when not empty");
-
-  EHPadEndScope &scope = cast<EHPadEndScope>(*begin());
-  InnermostEHScope = scope.getEnclosingEHScope();
-  deallocate(EHPadEndScope::getSize());
-}
-
 inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
   assert(sp.isValid() && "finding invalid savepoint");
   assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
Index: lib/CodeGen/CGCleanup.cpp
===================================================================
--- lib/CodeGen/CGCleanup.cpp
+++ lib/CodeGen/CGCleanup.cpp
@@ -246,13 +246,6 @@
   InnermostEHScope = stable_begin();
 }
 
-void EHScopeStack::pushPadEnd(llvm::BasicBlock *PadEndBB) {
-  char *Buffer = allocate(EHPadEndScope::getSize());
-  auto *CES = new (Buffer) EHPadEndScope(InnermostEHScope);
-  CES->setCachedEHDispatchBlock(PadEndBB);
-  InnermostEHScope = stable_begin();
-}
-
 /// Remove any 'null' fixups on the stack.  However, we can't pop more
 /// fixups than the fixup depth on the innermost normal cleanup, or
 /// else fixups that we try to add to that cleanup will end up in the
@@ -909,24 +902,17 @@
     // throwing cleanups. For funclet EH personalities, the cleanupendpad models
     // program termination when cleanups throw.
     bool PushedTerminate = false;
-    SaveAndRestore<bool> RestoreIsCleanupPadScope(IsCleanupPadScope);
+    SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(
+        CurrentFuncletPad);
     llvm::CleanupPadInst *CPI = nullptr;
-    llvm::BasicBlock *CleanupEndBB = nullptr;
     if (!EHPersonality::get(*this).usesFuncletPads()) {
       EHStack.pushTerminate();
       PushedTerminate = true;
     } else {
-      CPI = Builder.CreateCleanupPad({});
-
-      // Build a cleanupendpad to unwind through. Our insertion point should be
-      // in the cleanuppad block.
-      CleanupEndBB = createBasicBlock("ehcleanup.end");
-      CGBuilderTy(*this, CleanupEndBB).CreateCleanupEndPad(CPI, NextAction);
-      EHStack.pushPadEnd(CleanupEndBB);
-
-      // Mark that we're inside a cleanuppad to block inlining.
-      // FIXME: Remove this once the inliner knows when it's safe to do so.
-      IsCleanupPadScope = true;
+      llvm::Value *OuterScope = CurrentFuncletPad;
+      if (!OuterScope)
+        OuterScope = llvm::ConstantTokenNone::get(CGM.getLLVMContext());
+      CurrentFuncletPad = CPI = Builder.CreateCleanupPad(OuterScope);
     }
 
     // We only actually emit the cleanup code if the cleanup is either
@@ -941,17 +927,6 @@
     else
       Builder.CreateBr(NextAction);
 
-    // Insert the cleanupendpad block here, if it has any uses.
-    if (CleanupEndBB) {
-      EHStack.popPadEnd();
-      if (CleanupEndBB->hasNUsesOrMore(1)) {
-        CurFn->getBasicBlockList().insertAfter(
-            Builder.GetInsertBlock()->getIterator(), CleanupEndBB);
-      } else {
-        delete CleanupEndBB;
-      }
-    }
-
     // Leave the terminate scope.
     if (PushedTerminate)
       EHStack.popTerminate();
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -15,6 +15,7 @@
 #include "CGCall.h"
 #include "ABIInfo.h"
 #include "CGCXXABI.h"
+#include "CGCleanup.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
@@ -3427,11 +3428,22 @@
   llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
                                                      AttributeList);
 
-  llvm::BasicBlock *InvokeDest = nullptr;
-  if (!Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
-                          llvm::Attribute::NoUnwind) ||
-      currentFunctionUsesSEHTry())
-    InvokeDest = getInvokeDest();
+  bool CannotThrow;
+  if (currentFunctionUsesSEHTry()) {
+    // SEH cares about asynchronous exceptions, everything can "throw."
+    CannotThrow = false;
+  } else if (isCleanupPadScope() &&
+             &EHPersonality::get(*this) ==
+                 &EHPersonality::MSVC_CxxFrameHandler3) {
+    // The MSVC++ personality will implicitly terminate the program if an
+    // exception is thrown.  An unwind edge cannot be reached.
+    CannotThrow = true;
+  } else {
+    // Otherwise, nowunind callsites will never throw.
+    CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
+                                     llvm::Attribute::NoUnwind);
+  }
+  llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
 
   llvm::CallSite CS;
   if (!InvokeDest) {
@@ -3450,14 +3462,8 @@
         Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
                            llvm::Attribute::AlwaysInline);
 
-  // Disable inlining inside SEH __try blocks and cleanup funclets. None of the
-  // funclet EH personalities that clang supports have tables that are
-  // expressive enough to describe catching an exception inside a cleanup.
-  // __CxxFrameHandler3, for example, will terminate the program without
-  // catching it.
-  // FIXME: Move this decision to the LLVM inliner. Before we can do that, the
-  // inliner needs to know if a given call site is part of a cleanuppad.
-  if (isSEHTryScope() || isCleanupPadScope())
+  // Disable inlining inside SEH __try blocks.
+  if (isSEHTryScope())
     Attrs =
         Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
                            llvm::Attribute::NoInline);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to