Throw the switch to convert clang to the new exception handling model!

This model uses the 'landingpad' instruction, which is pinned to the top of the
landing pad. (A landing pad is defined as the destination of the unwind branch
of an invoke instruction.) All of the information needed to generate the correct
exception handling metadata during code generation is encoded into the
landingpad instruction.

The new 'resume' instruction takes the place of the llvm.eh.resume intrinsic
call. It's lowered in much the same way as the intrinsic is.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140049 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index e711914..14a89cf 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -306,12 +306,6 @@
   return llvm::ConstantPointerNull::get(CGF.Int8PtrTy);
 }
 
-/// Returns the value to inject into a selector to indicate the
-/// presence of a cleanup.
-static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) {
-  return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
-}
-
 namespace {
   /// A cleanup to free the exception object if its initialization
   /// throws.
@@ -733,17 +727,19 @@
   llvm::BasicBlock *lpad = createBasicBlock("lpad");
   EmitBlock(lpad);
 
+  llvm::LandingPadInst *LPadInst =
+    Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL),
+                             getOpaquePersonalityFn(CGM, personality), 0);
+
+  llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);
+  Builder.CreateStore(LPadExn, getExceptionSlot());
+  llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1);
+  Builder.CreateStore(LPadSel, getEHSelectorSlot());
+
   // Save the exception pointer.  It's safe to use a single exception
   // pointer per function because EH cleanups can never have nested
   // try/catches.
-  llvm::CallInst *exn =
-    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
-  exn->setDoesNotThrow();
-  
-  // Build the selector arguments.
-  SmallVector<llvm::Value*, 8> selector;
-  selector.push_back(exn);
-  selector.push_back(getOpaquePersonalityFn(CGM, personality));
+  // Build the landingpad instruction.
 
   // Accumulate all the handlers in scope.
   bool hasCatchAll = false;
@@ -764,7 +760,7 @@
       assert(I.next() == EHStack.end() && "EH filter is not end of EH stack");
       assert(!hasCatchAll && "EH filter reached after catch-all");
 
-      // Filter scopes get added to the selector in weird ways.
+      // Filter scopes get added to the landingpad in weird ways.
       EHFilterScope &filter = cast<EHFilterScope>(*I);
       hasFilter = true;
 
@@ -800,54 +796,52 @@
       }
 
       // Check whether we already have a handler for this type.
-      if (catchTypes.insert(handler.Type)) {
-        // If not, add it directly to the selector.
-        selector.push_back(handler.Type);
-      }
+      if (catchTypes.insert(handler.Type))
+        // If not, add it directly to the landingpad.
+        LPadInst->addClause(handler.Type);
     }
   }
 
  done:
-  // If we have a catch-all, add null to the selector.
+  // If we have a catch-all, add null to the landingpad.
   assert(!(hasCatchAll && hasFilter));
   if (hasCatchAll) {
-    selector.push_back(getCatchAllValue(*this));
+    LPadInst->addClause(getCatchAllValue(*this));
 
   // If we have an EH filter, we need to add those handlers in the
-  // right place in the selector, which is to say, at the end.
+  // right place in the landingpad, which is to say, at the end.
   } else if (hasFilter) {
     // Create a filter expression: an integer constant saying how many
     // filters there are (+1 to avoid ambiguity with 0 for cleanup),
     // followed by the filter types.  The personality routine only
     // lands here if the filter doesn't match.
-    selector.push_back(Builder.getInt32(filterTypes.size() + 1));
-    selector.append(filterTypes.begin(), filterTypes.end());
+    llvm::SmallVector<llvm::Constant*, 8> Filters;
+    llvm::ArrayType *AType =
+      llvm::ArrayType::get(!filterTypes.empty() ?
+                             filterTypes[0]->getType() : Int8PtrTy,
+                           filterTypes.size());
+
+    for (unsigned i = 0, e = filterTypes.size(); i != e; ++i)
+      Filters.push_back(cast<llvm::Constant>(filterTypes[i]));
+    llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters);
+    LPadInst->addClause(FilterArray);
 
     // Also check whether we need a cleanup.
-    if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup)
-      selector.push_back(CleanupHackLevel == CHL_MandatoryCatchall
-                           ? getCatchAllValue(*this)
-                           : getCleanupValue(*this));
+    if (hasCleanup)
+      LPadInst->setCleanup(true);
 
   // Otherwise, signal that we at least have cleanups.
   } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) {
-    selector.push_back(CleanupHackLevel == CHL_MandatoryCatchall
-                         ? getCatchAllValue(*this)
-                         : getCleanupValue(*this));
+    if (CleanupHackLevel == CHL_MandatoryCatchall)
+      LPadInst->addClause(getCatchAllValue(*this));
+    else
+      LPadInst->setCleanup(true);
   }
 
-  assert(selector.size() >= 3 && "selector call has only two arguments!");
+  assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) &&
+         "landingpad instruction has no clauses!");
 
   // Tell the backend how to generate the landing pad.
-  llvm::CallInst *selectorCall =
-    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
-                       selector, "eh.selector");
-  selectorCall->setDoesNotThrow();
-
-  // Save the selector and exception pointer.
-  Builder.CreateStore(exn, getExceptionSlot());
-  Builder.CreateStore(selectorCall, getEHSelectorSlot());
-
   Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope()));
 
   // Restore the old IR generation state.
@@ -1462,19 +1456,11 @@
   Builder.SetInsertPoint(TerminateLandingPad);
 
   // Tell the backend that this is a landing pad.
-  llvm::CallInst *Exn =
-    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
-  Exn->setDoesNotThrow();
-
   const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
-  
-  // Tell the backend what the exception table should be:
-  // nothing but a catch-all.
-  llvm::Value *Args[3] = { Exn, getOpaquePersonalityFn(CGM, Personality),
-                           getCatchAllValue(*this) };
-  Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
-                     Args, "eh.selector")
-    ->setDoesNotThrow();
+  llvm::LandingPadInst *LPadInst =
+    Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL),
+                             getOpaquePersonalityFn(CGM, Personality), 0);
+  LPadInst->addClause(getCatchAllValue(*this));
 
   llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this));
   TerminateCall->setDoesNotReturn();
@@ -1538,12 +1524,21 @@
         ->setDoesNotReturn();
       break;
     case CHL_MandatoryCleanup: {
-      // In mandatory-cleanup mode, we should use llvm.eh.resume.
-      llvm::Value *Selector = getSelectorFromSlot();
-      Builder.CreateCall2(CGM.getIntrinsic(llvm::Intrinsic::eh_resume),
-                          Exn, Selector)
-        ->setDoesNotReturn();
-      break;
+      // In mandatory-cleanup mode, we should use 'resume'.
+
+      // Recreate the landingpad's return value for the 'resume' instruction.
+      llvm::Value *Exn = getExceptionFromSlot();
+      llvm::Value *Sel = getSelectorFromSlot();
+
+      llvm::Type *LPadType = llvm::StructType::get(Exn->getType(),
+                                                   Sel->getType(), NULL);
+      llvm::Value *LPadVal = llvm::UndefValue::get(LPadType);
+      LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val");
+      LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val");
+
+      Builder.CreateResume(LPadVal);
+      Builder.restoreIP(SavedIP);
+      return EHResumeBlock;
     }
     case CHL_Ideal:
       // In an idealized mode where we don't have to worry about the
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index b4b2eb1..d38a9b0 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -365,9 +365,12 @@
   for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
     for (llvm::BasicBlock::iterator
            BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
-      if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI))
+      if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI)) {
         if (!Call->doesNotThrow())
           return;
+      } else if (isa<llvm::ResumeInst>(&*BI)) {
+        return;
+      }
   F->setDoesNotThrow(true);
 }
 
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 177e647..19541a9 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -612,12 +612,12 @@
   /// EHResumeBlock - Unified block containing a call to llvm.eh.resume.
   llvm::BasicBlock *EHResumeBlock;
 
-  /// The exception slot.  All landing pads write the current
-  /// exception pointer into this alloca.
+  /// The exception slot.  All landing pads write the current exception pointer
+  /// into this alloca.
   llvm::Value *ExceptionSlot;
 
-  /// The selector slot.  Under the MandatoryCleanup model, all
-  /// landing pads write the current selector value into this alloca.
+  /// The selector slot.  Under the MandatoryCleanup model, all landing pads
+  /// write the current selector value into this alloca.
   llvm::AllocaInst *EHSelectorSlot;
 
   /// Emits a landing pad for the current EH stack.
@@ -1116,8 +1116,8 @@
 
   const LangOptions &getLangOptions() const { return CGM.getLangOptions(); }
 
-  /// Returns a pointer to the function's exception object slot, which
-  /// is assigned in every landing pad.
+  /// Returns a pointer to the function's exception object and selector slot,
+  /// which is assigned in every landing pad.
   llvm::Value *getExceptionSlot();
   llvm::Value *getEHSelectorSlot();
 
diff --git a/test/CXX/except/except.spec/p9-dynamic.cpp b/test/CXX/except/except.spec/p9-dynamic.cpp
index 3f496f2..4559e0d 100644
--- a/test/CXX/except/except.spec/p9-dynamic.cpp
+++ b/test/CXX/except/except.spec/p9-dynamic.cpp
@@ -7,5 +7,6 @@
   // CHECK: invoke void @_Z8externalv()
   external();
 }
-// CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* bitcast (i8** @_ZTIi to i8*)) nounwind
-// CHECK: call void @__cxa_call_unexpected
+// CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-NEXT:   filter [1 x i8*] [i8* bitcast (i8** @_ZTIi to i8*)]
+// CHECK:      call void @__cxa_call_unexpected
diff --git a/test/CXX/except/except.spec/p9-noexcept.cpp b/test/CXX/except/except.spec/p9-noexcept.cpp
index 76ac66c..7b2a259 100644
--- a/test/CXX/except/except.spec/p9-noexcept.cpp
+++ b/test/CXX/except/except.spec/p9-noexcept.cpp
@@ -7,7 +7,8 @@
   // CHECK: invoke void @_Z8externalv()
   external();
 }
-// CHECK:  call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* null) nounwind
+// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-NEXT:  catch i8* null
 // CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind
 // CHECK-NEXT: unreachable
 
diff --git a/test/CodeGen/exceptions.c b/test/CodeGen/exceptions.c
index 018b975..20eb706 100644
--- a/test/CodeGen/exceptions.c
+++ b/test/CodeGen/exceptions.c
@@ -14,6 +14,8 @@
   // CHECK-ARM: invoke arm_aapcscc void @test1_helper(
   test1_helper(^(int v) { x = v; });
 
-  // CHECK:     call {{.*}} @llvm.eh.selector({{.*}}, i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
-  // CHECK-ARM: call {{.*}} @llvm.eh.selector({{.*}}, i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+  // CHECK:          landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+  // CHECK-NEXT:       cleanup
+  // CHECK-ARM:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
+  // CHECK-ARM-NEXT:   cleanup
 }
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index dcb27ce..a767f42 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -308,9 +308,10 @@
     // CHECK:      ret void
     static int x = foo();
 
-    // CHECK:      call i8* @llvm.eh.exception()
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+    // CHECK-NEXT:   cleanup
     // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x)
-    // CHECK:      call void @llvm.eh.resume(
+    // CHECK:      resume { i8*, i32 }
   }
 }
 
@@ -347,9 +348,10 @@
     // CHECK:      ret void
     static A x;
 
-    // CHECK:      call i8* @llvm.eh.exception()
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+    // CHECK-NEXT:   cleanup
     // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x)
-    // CHECK:      call void @llvm.eh.resume(
+    // CHECK:      resume { i8*, i32 }
   }
 }
 
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index dc24551..d9962e6 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -356,9 +356,10 @@
   // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
   // CHECK: ret void
-  // CHECK: call i8* @llvm.eh.exception(
+  // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT: cleanup
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
-  // CHECK: call void @llvm.eh.resume(
+  // CHECK: resume { i8*, i32 }
 
   // Checked at top of file:
   // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
@@ -386,9 +387,10 @@
   // CHECK: invoke void @_ZN5test312_GLOBAL__N_11CD1Ev(
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
   // CHECK: ret void
-  // CHECK: call i8* @llvm.eh.exception()
+  // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT: cleanup
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
-  // CHECK: call void @llvm.eh.resume(
+  // CHECK: resume { i8*, i32 }
 
   // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
diff --git a/test/CodeGenCXX/dynamic-cast.cpp b/test/CodeGenCXX/dynamic-cast.cpp
index e84bb9b..813e36e 100644
--- a/test/CodeGenCXX/dynamic-cast.cpp
+++ b/test/CodeGenCXX/dynamic-cast.cpp
@@ -11,7 +11,8 @@
     // CHECK: invoke void @__cxa_bad_cast() noreturn
     dynamic_cast<const B&>(*a);
   } catch (...) {
-    // CHECK: call i8* @llvm.eh.exception
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+    // CHECK-NEXT:   catch i8* null
   }
   return fail;
 }
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index 24807d9..e990994 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -115,9 +115,12 @@
         throw 1;
       }
 
-// CHECK:      [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception()
-// CHECK-NEXT: [[SELECTOR:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null)
+// CHECK:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
+// CHECK-NEXT:   catch i8* null
+// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
 // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]]
+// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
 // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]]
 // CHECK-NEXT: br label
 // CHECK:      [[SELECTOR:%.*]] = load i32* [[SELECTORVAR]]
@@ -134,9 +137,11 @@
         throw;
       }
     }
-// CHECK:      [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception()
-// CHECK-NEXT: [[SELECTOR:%.*]] = call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null)
+// CHECK:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+// CHECK-NEXT:   catch i8* null
+// CHECK-NEXT: [[CAUGHTEXN:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
 // CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]]
+// CHECK-NEXT: [[SELECTOR:%.*]] = extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
 // CHECK-NEXT: store i32 [[SELECTOR]], i32* [[SELECTORVAR]]
 // CHECK-NEXT: call void @__cxa_end_catch()
 // CHECK-NEXT: br label
@@ -188,8 +193,8 @@
   // CHECK:      invoke void @_ZN5test96opaqueEv()
     opaque();
   } catch (int x) {
-  // CHECK:      call i8* @llvm.eh.exception
-  // CHECK:      call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
 
   // CHECK:      call i8* @__cxa_begin_catch
   // CHECK:      invoke void @_ZN5test96opaqueEv()
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp
index 0efb355..57bf27a 100644
--- a/test/CodeGenCXX/nrvo.cpp
+++ b/test/CodeGenCXX/nrvo.cpp
@@ -68,8 +68,10 @@
   // -> %cleanup, %lpad1
 
   // %lpad: landing pad for ctor of 'y', dtor of 'y'
-  // CHECK-EH:      call i8* @llvm.eh.exception()
-  // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector
+  // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-EH-NEXT:   cleanup
+  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
+  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
   // CHECK-EH-NEXT: br label
   // -> %eh.cleanup
 
@@ -95,12 +97,11 @@
 
   // %invoke.cont17: rethrow block for %eh.cleanup.
   // This really should be elsewhere in the function.
-  // CHECK-EH:      call void @llvm.eh.resume(
-  // CHECK-EH-NEXT: unreachable
+  // CHECK-EH:      resume { i8*, i32 }
 
   // %terminate.lpad: terminate landing pad.
-  // CHECK-EH:      call i8* @llvm.eh.exception()
-  // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector
+  // CHECK-EH:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-EH-NEXT:   catch i8* null
   // CHECK-EH-NEXT: call void @_ZSt9terminatev()
   // CHECK-EH-NEXT: unreachable
 
diff --git a/test/CodeGenCXX/partial-destruction.cpp b/test/CodeGenCXX/partial-destruction.cpp
index b28c138..f232a15 100644
--- a/test/CodeGenCXX/partial-destruction.cpp
+++ b/test/CodeGenCXX/partial-destruction.cpp
@@ -50,7 +50,8 @@
   // CHECK:      ret void
 
   // Partial destroy for initialization.
-  // CHECK:      llvm.eh.selector({{.*}}, i32 0)
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   cleanup
   // CHECK:      [[PARTIAL_END:%.*]] = load [[A]]** [[ENDVAR]]
   // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[E_BEGIN]], [[PARTIAL_END]]
   // CHECK-NEXT: br i1 [[T0]],
@@ -61,7 +62,8 @@
   // CHECK-NEXT: br i1 [[T0]],
 
   // Primary EH destructor.
-  // CHECK:      llvm.eh.selector({{.*}}, i32 0)
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   cleanup
   // CHECK:      [[E0:%.*]] = getelementptr inbounds [10 x [[A]]]* [[AS]], i32 0, i32 0
   // CHECK-NEXT: [[E_END:%.*]] = getelementptr inbounds [[A]]* [[E0]], i64 10
   // CHECK-NEXT: br label
@@ -70,7 +72,8 @@
   // FIXME: There's some really bad block ordering here which causes
   // the partial destroy for the primary normal destructor to fall
   // within the primary EH destructor.
-  // CHECK:      llvm.eh.selector({{.*}}, i32 0)
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   cleanup
   // CHECK:      [[T0:%.*]] = icmp eq [[A]]* [[ED_BEGIN]], [[ED_CUR]]
   // CHECK-NEXT: br i1 [[T0]]
   // CHECK:      [[EDD_AFTER:%.*]] = phi [[A]]* [ [[ED_CUR]], {{%.*}} ], [ [[EDD_CUR:%.*]], {{%.*}} ]
@@ -111,8 +114,10 @@
   // CHECK-NEXT: ret void
 
   // FIXME: again, the block ordering is pretty bad here
-  // CHECK:      eh.selector({{.*}}, i32 0)
-  // CHECK:      eh.selector({{.*}}, i32 0)
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   cleanup
+  // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK-NEXT:   cleanup
   // CHECK:      invoke void @_ZN5test11AD1Ev([[A]]* [[Y]])
   // CHECK:      invoke void @_ZN5test11AD1Ev([[A]]* [[X]])
 }
@@ -139,7 +144,8 @@
     // CHECK-NEXT: br i1 [[DONE]],
 
     // Partial destruction landing pad.
-    // CHECK:      llvm.eh.exception()
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+    // CHECK-NEXT:   cleanup
     // CHECK:      [[EMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[CUR]]
     // CHECK-NEXT: br i1 [[EMPTY]],
     // CHECK:      [[PAST:%.*]] = phi [[A]]* [ [[CUR]], {{%.*}} ], [ [[DEL:%.*]], {{%.*}} ]
diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
index aa79a4f..769d120 100644
--- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
+++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
@@ -21,9 +21,8 @@
   throw Y();
 
   // Finally, the landing pad.
-  // CHECK: call i8* @llvm.eh.exception()
-  // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector
+  // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+  // CHECK:   cleanup
   // CHECK: call void @__cxa_guard_abort(i64* @_ZGVZ1fvE1x)
-  // CHECK: call void @llvm.eh.resume(
-  // CHECK: unreachable
+  // CHECK: resume { i8*, i32 }
 }
diff --git a/test/CodeGenCXX/typeid.cpp b/test/CodeGenCXX/typeid.cpp
index 1af9670..7ebf41c 100644
--- a/test/CodeGenCXX/typeid.cpp
+++ b/test/CodeGenCXX/typeid.cpp
@@ -13,7 +13,8 @@
     // CHECK: invoke void @__cxa_bad_typeid() noreturn
     return typeid(*static_cast<A *>(0)).name();
   } catch (...) {
-    // CHECK: call i8* @llvm.eh.exception
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+    // CHECK-NEXT:   catch i8* null
   }
 
   return 0;
diff --git a/test/CodeGenObjC/blocks-2.m b/test/CodeGenObjC/blocks-2.m
index 5d63e91..56eb8a7 100644
--- a/test/CodeGenObjC/blocks-2.m
+++ b/test/CodeGenObjC/blocks-2.m
@@ -30,8 +30,9 @@
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
   // CHECK-NEXT: ret void
 
-  // CHECK:      call i8* @llvm.eh.exception()
+  // CHECK:      landingpad { i8*, i32 } personality
+  // CHECK-NEXT:   cleanup
   // CHECK:      [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8*
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
-  // CHECK:      call void @llvm.eh.resume(
+  // CHECK:      resume { i8*, i32 }
 }
diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m
index 7f3ae9d..8917bf3 100644
--- a/test/CodeGenObjC/gnu-exceptions.m
+++ b/test/CodeGenObjC/gnu-exceptions.m
@@ -14,9 +14,9 @@
     // CHECK: call void @log(i32 1)
 
   } @catch (C *c) {
-    // CHECK: call i8* @llvm.eh.exception()
-    // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gnu_objc_personality_v0
-    // CHECK: br i1
+    // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+    // CHECK-NEXT:   catch i8* getelementptr inbounds ([2 x i8]* @0, i64 0, i64 0)
+    // CHECK:      br i1
 
     // CHECK: call void @log(i32 0)
 
diff --git a/test/CodeGenObjC/terminate.m b/test/CodeGenObjC/terminate.m
index f04eb6a..0e01d89 100644
--- a/test/CodeGenObjC/terminate.m
+++ b/test/CodeGenObjC/terminate.m
@@ -14,8 +14,8 @@
   // CHECK-WITH:         call void @destroy(i8** [[PTR]])
   // CHECK-WITH-NEXT:    ret void
   // CHECK-WITH:         invoke void @destroy(i8** [[PTR]])
-  // CHECK-WITH:         call i8* @llvm.eh.exception()
-  // CHECK-WITH-NEXT:    @llvm.eh.selector
+  // CHECK-WITH:         landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+  // CHECK-WITH-NEXT:      catch i8* null
   // CHECK-WITH-NEXT:    call void @objc_terminate()
 
   // CHECK-WITHOUT:    define void @test0()
@@ -23,7 +23,7 @@
   // CHECK-WITHOUT:      call void @destroy(i8** [[PTR]])
   // CHECK-WITHOUT-NEXT: ret void
   // CHECK-WITHOUT:      invoke void @destroy(i8** [[PTR]])
-  // CHECK-WITHOUT:      call i8* @llvm.eh.exception()
-  // CHECK-WITHOUT-NEXT: @llvm.eh.selector
+  // CHECK-WITHOUT:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*)
+  // CHECK-WITHOUT-NEXT:   catch i8* null
   // CHECK-WITHOUT-NEXT: call void @abort()
 }
diff --git a/test/CodeGenObjCXX/catch-id-type.mm b/test/CodeGenObjCXX/catch-id-type.mm
index ece342b..b3f99b4 100644
--- a/test/CodeGenObjCXX/catch-id-type.mm
+++ b/test/CodeGenObjCXX/catch-id-type.mm
@@ -30,7 +30,10 @@
     }
     catch( id error )
     { 
-      // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gxx_personality_v0 {{.*}} @_ZTIP4INTF {{.*}} @_ZTIP11objc_object {{.*}} @_ZTIP10objc_class
+      // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+      // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP4INTF to i8*)
+      // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP11objc_object to i8*)
+      // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP10objc_class to i8*)
       error = error; 
       groups = [ns_array array]; 
     }
diff --git a/test/CodeGenObjCXX/exceptions.mm b/test/CodeGenObjCXX/exceptions.mm
index d4c0756..9f092b9 100644
--- a/test/CodeGenObjCXX/exceptions.mm
+++ b/test/CodeGenObjCXX/exceptions.mm
@@ -11,7 +11,8 @@
       // CHECK: invoke void @_Z6opaquev
       opaque();
     } catch (OCType *T) {
-      // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__objc_personality_v0 {{.*}} @"OBJC_EHTYPE_$_OCType"
+      // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
+      // CHECK-NEXT:   catch %struct._objc_typeinfo* @"OBJC_EHTYPE_$_OCType"
     }
   }
 }