[llvm] 9e4eade - [WebAssembly] Update basic EH instructions for the new spec

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 9 01:48:39 PST 2021


Author: Heejin Ahn
Date: 2021-01-09T01:48:06-08:00
New Revision: 9e4eadeb135d140b3a9e499354472170017cbe58

URL: https://github.com/llvm/llvm-project/commit/9e4eadeb135d140b3a9e499354472170017cbe58
DIFF: https://github.com/llvm/llvm-project/commit/9e4eadeb135d140b3a9e499354472170017cbe58.diff

LOG: [WebAssembly] Update basic EH instructions for the new spec

This implements basic instructions for the new spec.

- Adds new versions of instructions: `catch`, `catch_all`, and `rethrow`
- Adds support for instruction selection for the new instructions
 - `catch` needs a custom routine for the same reason `throw` needs one,
   to encode `__cpp_exception` tag symbol.
- Updates `WebAssembly::isCatch` utility function to include `catch_all`
  and Change code that compares an instruction's opcode with `catch` to
  use that function.
- LateEHPrepare
  - Previously in LateEHPrepare we added `catch` instruction to both
    `catchpad`s (for user catches) and `cleanuppad`s (for destructors).
    In the new version `catch` is generated from `llvm.catch` intrinsic
    in instruction selection phase, so we only need to add `catch_all`
    to the beginning of cleanup pads.
  - `catch` is generated from instruction selection, but we need to
    hoist the `catch` instruction to the beginning of every EH pad,
    because `catch` can be in the middle of the EH pad or even in a
    split BB from it after various code transformations.
  - Removes `addExceptionExtraction` function, which was used to
    generate `br_on_exn` before.
- CFGStackfiy: Deletes `fixUnwindMismatches` function. Running this
  function on the new instruction causes crashes, and the new version
  will be added in a later CL, whose contents will be completely
  different. So deleting the whole function will make the diff easier to
  read.
- Reenables all disabled tests in exception.ll and eh-lsda.ll and a
  single basic test in cfg-stackify-eh.ll.
- Updates existing tests to use the new assembly format. And deletes
  `br_on_exn` instructions from the tests and FileCheck lines.

Reviewed By: dschuff, tlively

Differential Revision: https://reviews.llvm.org/D94040

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
    llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyISD.def
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
    llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
    llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
    llvm/test/CodeGen/WebAssembly/eh-labels.mir
    llvm/test/CodeGen/WebAssembly/eh-lsda.ll
    llvm/test/CodeGen/WebAssembly/exception.ll
    llvm/test/MC/WebAssembly/annotations.s
    llvm/test/MC/WebAssembly/basic-assembly.s
    llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 814c4f5e9623..20e13b361cf8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1637,10 +1637,32 @@ void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
   }
 }
 
-// For wasm, there's always a single catch pad attached to a catchswitch, and
-// the control flow always stops at the single catch pad, as it does for a
-// cleanup pad. In case the exception caught is not of the types the catch pad
-// catches, it will be rethrown by a rethrow.
+// In wasm EH, even though a catchpad may not catch an exception if a tag does
+// not match, it is OK to add only the first unwind destination catchpad to the
+// successors, because there will be at least one invoke instruction within the
+// catch scope that points to the next unwind destination, if one exists, so
+// CFGSort cannot mess up with BB sorting order.
+// (All catchpads with 'catch (type)' clauses have a 'llvm.rethrow' intrinsic
+// call within them, and catchpads only consisting of 'catch (...)' have a
+// '__cxa_end_catch' call within them, both of which generate invokes in case
+// the next unwind destination exists, i.e., the next unwind destination is not
+// the caller.)
+//
+// Having at most one EH pad successor is also simpler and helps later
+// transformations.
+//
+// For example,
+// current:
+//   invoke void @foo to ... unwind label %catch.dispatch
+// catch.dispatch:
+//   %0 = catchswitch within ... [label %catch.start] unwind label %next
+// catch.start:
+//   ...
+//   ... in this BB or some other child BB dominated by this BB there will be an
+//   invoke that points to 'next' BB as an unwind destination
+//
+// next: ; We don't need to add this to 'current' BB's successor
+//   ...
 static void findWasmUnwindDestinations(
     FunctionLoweringInfo &FuncInfo, const BasicBlock *EHPadBB,
     BranchProbability Prob,

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
index 518c8db1920f..3538d6c3bb12 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -440,6 +440,18 @@ inline bool isMarker(unsigned Opc) {
   }
 }
 
+inline bool isCatch(unsigned Opc) {
+  switch (Opc) {
+  case WebAssembly::CATCH:
+  case WebAssembly::CATCH_S:
+  case WebAssembly::CATCH_ALL:
+  case WebAssembly::CATCH_ALL_S:
+    return true;
+  default:
+    return false;
+  }
+}
+
 } // end namespace WebAssembly
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
index 5eafeb70c02a..0f4379e66ca4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp
@@ -183,8 +183,7 @@ static MachineInstr *findCatch(MachineBasicBlock *EHPad, Register &ExnReg) {
   assert(EHPad->isEHPad());
   MachineInstr *Catch = nullptr;
   for (auto &MI : *EHPad) {
-    switch (MI.getOpcode()) {
-    case WebAssembly::CATCH:
+    if (WebAssembly::isCatch(MI.getOpcode())) {
       Catch = &MI;
       ExnReg = Catch->getOperand(0).getReg();
       break;
@@ -784,11 +783,15 @@ static unsigned getCopyOpcode(const TargetRegisterClass *RC) {
 
 // When MBB is split into MBB and Split, we should unstackify defs in MBB that
 // have their uses in Split.
-static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB,
-                                         MachineBasicBlock &Split,
-                                         WebAssemblyFunctionInfo &MFI,
-                                         MachineRegisterInfo &MRI,
-                                         const WebAssemblyInstrInfo &TII) {
+// FIXME This function will be used when fixing unwind mismatches, but the old
+// version of that function was removed for the moment and the new version has
+// not yet been added. So 'LLVM_ATTRIBUTE_UNUSED' is added to suppress the
+// warning. Remove the attribute after the new functionality is added.
+LLVM_ATTRIBUTE_UNUSED static void
+unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split,
+                             WebAssemblyFunctionInfo &MFI,
+                             MachineRegisterInfo &MRI,
+                             const WebAssemblyInstrInfo &TII) {
   for (auto &MI : Split) {
     for (auto &MO : MI.explicit_uses()) {
       if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg()))
@@ -842,508 +845,8 @@ static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB,
 }
 
 bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) {
-  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
-  auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
-  MachineRegisterInfo &MRI = MF.getRegInfo();
-
-  // Linearizing the control flow by placing TRY / END_TRY markers can create
-  // mismatches in unwind destinations. There are two kinds of mismatches we
-  // try to solve here.
-
-  // 1. When an instruction may throw, but the EH pad it will unwind to can be
-  //    
diff erent from the original CFG.
-  //
-  // Example: we have the following CFG:
-  // bb0:
-  //   call @foo (if it throws, unwind to bb2)
-  // bb1:
-  //   call @bar (if it throws, unwind to bb3)
-  // bb2 (ehpad):
-  //   catch
-  //   ...
-  // bb3 (ehpad)
-  //   catch
-  //   handler body
-  //
-  // And the CFG is sorted in this order. Then after placing TRY markers, it
-  // will look like: (BB markers are omitted)
-  // try $label1
-  //   try
-  //     call @foo
-  //     call @bar   (if it throws, unwind to bb3)
-  //   catch         <- ehpad (bb2)
-  //     ...
-  //   end_try
-  // catch           <- ehpad (bb3)
-  //   handler body
-  // end_try
-  //
-  // Now if bar() throws, it is going to end up ip in bb2, not bb3, where it
-  // is supposed to end up. We solve this problem by
-  // a. Split the target unwind EH pad (here bb3) so that the handler body is
-  //    right after 'end_try', which means we extract the handler body out of
-  //    the catch block. We do this because this handler body should be
-  //    somewhere branch-eable from the inner scope.
-  // b. Wrap the call that has an incorrect unwind destination ('call @bar'
-  //    here) with a nested try/catch/end_try scope, and within the new catch
-  //    block, branches to the handler body.
-  // c. Place a branch after the newly inserted nested end_try so it can bypass
-  //    the handler body, which is now outside of a catch block.
-  //
-  // The result will like as follows. (new: a) means this instruction is newly
-  // created in the process of doing 'a' above.
-  //
-  // block $label0                 (new: placeBlockMarker)
-  //   try $label1
-  //     try
-  //       call @foo
-  //       try                     (new: b)
-  //         call @bar
-  //       catch                   (new: b)
-  //         local.set n / drop    (new: b)
-  //         br $label1            (new: b)
-  //       end_try                 (new: b)
-  //     catch                     <- ehpad (bb2)
-  //     end_try
-  //     br $label0                (new: c)
-  //   catch                       <- ehpad (bb3)
-  //   end_try                     (hoisted: a)
-  //   handler body
-  // end_block                     (new: placeBlockMarker)
-  //
-  // Note that the new wrapping block/end_block will be generated later in
-  // placeBlockMarker.
-  //
-  // TODO Currently local.set and local.gets are generated to move exnref value
-  // created by catches. That's because we don't support yielding values from a
-  // block in LLVM machine IR yet, even though it is supported by wasm. Delete
-  // unnecessary local.get/local.sets once yielding values from a block is
-  // supported. The full EH spec requires multi-value support to do this, but
-  // for C++ we don't yet need it because we only throw a single i32.
-  //
-  // ---
-  // 2. The same as 1, but in this case an instruction unwinds to a caller
-  //    function and not another EH pad.
-  //
-  // Example: we have the following CFG:
-  // bb0:
-  //   call @foo (if it throws, unwind to bb2)
-  // bb1:
-  //   call @bar (if it throws, unwind to caller)
-  // bb2 (ehpad):
-  //   catch
-  //   ...
-  //
-  // And the CFG is sorted in this order. Then after placing TRY markers, it
-  // will look like:
-  // try
-  //   call @foo
-  //   call @bar   (if it throws, unwind to caller)
-  // catch         <- ehpad (bb2)
-  //   ...
-  // end_try
-  //
-  // Now if bar() throws, it is going to end up ip in bb2, when it is supposed
-  // throw up to the caller.
-  // We solve this problem by
-  // a. Create a new 'appendix' BB at the end of the function and put a single
-  //    'rethrow' instruction (+ local.get) in there.
-  // b. Wrap the call that has an incorrect unwind destination ('call @bar'
-  //    here) with a nested try/catch/end_try scope, and within the new catch
-  //    block, branches to the new appendix block.
-  //
-  // block $label0          (new: placeBlockMarker)
-  //   try
-  //     call @foo
-  //     try                (new: b)
-  //       call @bar
-  //     catch              (new: b)
-  //       local.set n      (new: b)
-  //       br $label0       (new: b)
-  //     end_try            (new: b)
-  //   catch                <- ehpad (bb2)
-  //     ...
-  //   end_try
-  // ...
-  // end_block              (new: placeBlockMarker)
-  // local.get n            (new: a)  <- appendix block
-  // rethrow                (new: a)
-  //
-  // In case there are multiple calls in a BB that may throw to the caller, they
-  // can be wrapped together in one nested try scope. (In 1, this couldn't
-  // happen, because may-throwing instruction there had an unwind destination,
-  // i.e., it was an invoke before, and there could be only one invoke within a
-  // BB.)
-
-  SmallVector<const MachineBasicBlock *, 8> EHPadStack;
-  // Range of intructions to be wrapped in a new nested try/catch
-  using TryRange = std::pair<MachineInstr *, MachineInstr *>;
-  // In original CFG, <unwind destination BB, a vector of try ranges>
-  DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
-  // In new CFG, <destination to branch to, a vector of try ranges>
-  DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> BrDestToTryRanges;
-  // In new CFG, <destination to branch to, register containing exnref>
-  DenseMap<MachineBasicBlock *, unsigned> BrDestToExnReg;
-
-  // Destinations for branches that will be newly added, for which a new
-  // BLOCK/END_BLOCK markers are necessary.
-  SmallVector<MachineBasicBlock *, 8> BrDests;
-
-  // Gather possibly throwing calls (i.e., previously invokes) whose current
-  // unwind destination is not the same as the original CFG.
-  for (auto &MBB : reverse(MF)) {
-    bool SeenThrowableInstInBB = false;
-    for (auto &MI : reverse(MBB)) {
-      if (MI.getOpcode() == WebAssembly::TRY)
-        EHPadStack.pop_back();
-      else if (MI.getOpcode() == WebAssembly::CATCH)
-        EHPadStack.push_back(MI.getParent());
-
-      // In this loop we only gather calls that have an EH pad to unwind. So
-      // there will be at most 1 such call (= invoke) in a BB, so after we've
-      // seen one, we can skip the rest of BB. Also if MBB has no EH pad
-      // successor or MI does not throw, this is not an invoke.
-      if (SeenThrowableInstInBB || !MBB.hasEHPadSuccessor() ||
-          !WebAssembly::mayThrow(MI))
-        continue;
-      SeenThrowableInstInBB = true;
-
-      // If the EH pad on the stack top is where this instruction should unwind
-      // next, we're good.
-      MachineBasicBlock *UnwindDest = nullptr;
-      for (auto *Succ : MBB.successors()) {
-        if (Succ->isEHPad()) {
-          UnwindDest = Succ;
-          break;
-        }
-      }
-      if (EHPadStack.back() == UnwindDest)
-        continue;
-
-      // If not, record the range.
-      UnwindDestToTryRanges[UnwindDest].push_back(TryRange(&MI, &MI));
-    }
-  }
-
-  assert(EHPadStack.empty());
-
-  // Gather possibly throwing calls that are supposed to unwind up to the caller
-  // if they throw, but currently unwind to an incorrect destination. Unlike the
-  // loop above, there can be multiple calls within a BB that unwind to the
-  // caller, which we should group together in a range.
-  bool NeedAppendixBlock = false;
-  for (auto &MBB : reverse(MF)) {
-    MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr; // inclusive
-    for (auto &MI : reverse(MBB)) {
-      if (MI.getOpcode() == WebAssembly::TRY)
-        EHPadStack.pop_back();
-      else if (MI.getOpcode() == WebAssembly::CATCH)
-        EHPadStack.push_back(MI.getParent());
-
-      // If MBB has an EH pad successor, this inst does not unwind to caller.
-      if (MBB.hasEHPadSuccessor())
-        continue;
-
-      // We wrap up the current range when we see a marker even if we haven't
-      // finished a BB.
-      if (RangeEnd && WebAssembly::isMarker(MI.getOpcode())) {
-        NeedAppendixBlock = true;
-        // Record the range. nullptr here means the unwind destination is the
-        // caller.
-        UnwindDestToTryRanges[nullptr].push_back(
-            TryRange(RangeBegin, RangeEnd));
-        RangeBegin = RangeEnd = nullptr; // Reset range pointers
-      }
-
-      // If EHPadStack is empty, that means it is correctly unwind to caller if
-      // it throws, so we're good. If MI does not throw, we're good too.
-      if (EHPadStack.empty() || !WebAssembly::mayThrow(MI))
-        continue;
-
-      // We found an instruction that unwinds to the caller but currently has an
-      // incorrect unwind destination. Create a new range or increment the
-      // currently existing range.
-      if (!RangeEnd)
-        RangeBegin = RangeEnd = &MI;
-      else
-        RangeBegin = &MI;
-    }
-
-    if (RangeEnd) {
-      NeedAppendixBlock = true;
-      // Record the range. nullptr here means the unwind destination is the
-      // caller.
-      UnwindDestToTryRanges[nullptr].push_back(TryRange(RangeBegin, RangeEnd));
-      RangeBegin = RangeEnd = nullptr; // Reset range pointers
-    }
-  }
-
-  assert(EHPadStack.empty());
-  // We don't have any unwind destination mismatches to resolve.
-  if (UnwindDestToTryRanges.empty())
-    return false;
-
-  // If we found instructions that should unwind to the caller but currently
-  // have incorrect unwind destination, we create an appendix block at the end
-  // of the function with a local.get and a rethrow instruction.
-  if (NeedAppendixBlock) {
-    auto *AppendixBB = getAppendixBlock(MF);
-    Register ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
-    BuildMI(AppendixBB, DebugLoc(), TII.get(WebAssembly::RETHROW))
-        .addReg(ExnReg);
-    // These instruction ranges should branch to this appendix BB.
-    for (auto Range : UnwindDestToTryRanges[nullptr])
-      BrDestToTryRanges[AppendixBB].push_back(Range);
-    BrDestToExnReg[AppendixBB] = ExnReg;
-  }
-
-  // We loop through unwind destination EH pads that are targeted from some
-  // inner scopes. Because these EH pads are destination of more than one scope
-  // now, we split them so that the handler body is after 'end_try'.
-  // - Before
-  // ehpad:
-  //   catch
-  //   local.set n / drop
-  //   handler body
-  // ...
-  // cont:
-  //   end_try
-  //
-  // - After
-  // ehpad:
-  //   catch
-  //   local.set n / drop
-  // brdest:               (new)
-  //   end_try             (hoisted from 'cont' BB)
-  //   handler body        (taken from 'ehpad')
-  // ...
-  // cont:
-  for (auto &P : UnwindDestToTryRanges) {
-    NumUnwindMismatches += P.second.size();
-
-    // This means the destination is the appendix BB, which was separately
-    // handled above.
-    if (!P.first)
-      continue;
-
-    MachineBasicBlock *EHPad = P.first;
-    Register ExnReg = 0;
-    MachineInstr *Catch = findCatch(EHPad, ExnReg);
-    auto SplitPos = std::next(Catch->getIterator());
-
-    // Create a new BB that's gonna be the destination for branches from the
-    // inner mismatched scope.
-    MachineInstr *BeginTry = EHPadToTry[EHPad];
-    MachineInstr *EndTry = BeginToEnd[BeginTry];
-    MachineBasicBlock *Cont = EndTry->getParent();
-    auto *BrDest = MF.CreateMachineBasicBlock();
-    MF.insert(std::next(EHPad->getIterator()), BrDest);
-    // Hoist up the existing 'end_try'.
-    BrDest->insert(BrDest->end(), EndTry->removeFromParent());
-    // Take out the handler body from EH pad to the new branch destination BB.
-    BrDest->splice(BrDest->end(), EHPad, SplitPos, EHPad->end());
-    unstackifyVRegsUsedInSplitBB(*EHPad, *BrDest, MFI, MRI, TII);
-    // Fix predecessor-successor relationship.
-    BrDest->transferSuccessors(EHPad);
-    EHPad->addSuccessor(BrDest);
-
-    // All try ranges that were supposed to unwind to this EH pad now have to
-    // branch to this new branch dest BB.
-    for (auto Range : UnwindDestToTryRanges[EHPad])
-      BrDestToTryRanges[BrDest].push_back(Range);
-    BrDestToExnReg[BrDest] = ExnReg;
-
-    // In case we fall through to the continuation BB after the catch block, we
-    // now have to add a branch to it.
-    // - Before
-    // try
-    //   ...
-    //   (falls through to 'cont')
-    // catch
-    //   handler body
-    // end
-    //               <-- cont
-    //
-    // - After
-    // try
-    //   ...
-    //   br %cont    (new)
-    // catch
-    // end
-    // handler body
-    //               <-- cont
-    MachineBasicBlock *EHPadLayoutPred = &*std::prev(EHPad->getIterator());
-    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
-    SmallVector<MachineOperand, 4> Cond;
-    bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
-    if (Analyzable && !TBB && !FBB) {
-      DebugLoc DL = EHPadLayoutPred->empty()
-                        ? DebugLoc()
-                        : EHPadLayoutPred->rbegin()->getDebugLoc();
-      BuildMI(EHPadLayoutPred, DL, TII.get(WebAssembly::BR)).addMBB(Cont);
-      BrDests.push_back(Cont);
-    }
-  }
-
-  // For possibly throwing calls whose unwind destinations are currently
-  // incorrect because of CFG linearization, we wrap them with a nested
-  // try/catch/end_try, and within the new catch block, we branch to the correct
-  // handler.
-  // - Before
-  // mbb:
-  //   call @foo       <- Unwind destination mismatch!
-  // ehpad:
-  //   ...
-  //
-  // - After
-  // mbb:
-  //   try                (new)
-  //   call @foo
-  // nested-ehpad:        (new)
-  //   catch              (new)
-  //   local.set n / drop (new)
-  //   br %brdest         (new)
-  // nested-end:          (new)
-  //   end_try            (new)
-  // ehpad:
-  //   ...
-  for (auto &P : BrDestToTryRanges) {
-    MachineBasicBlock *BrDest = P.first;
-    auto &TryRanges = P.second;
-    unsigned ExnReg = BrDestToExnReg[BrDest];
-
-    for (auto Range : TryRanges) {
-      MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr;
-      std::tie(RangeBegin, RangeEnd) = Range;
-      auto *MBB = RangeBegin->getParent();
-      // Store the first function call from this range, because RangeBegin can
-      // be moved to point EH_LABEL before the call
-      MachineInstr *RangeBeginCall = RangeBegin;
-
-      // Include possible EH_LABELs in the range
-      if (RangeBegin->getIterator() != MBB->begin() &&
-          std::prev(RangeBegin->getIterator())->isEHLabel())
-        RangeBegin = &*std::prev(RangeBegin->getIterator());
-      if (std::next(RangeEnd->getIterator()) != MBB->end() &&
-          std::next(RangeEnd->getIterator())->isEHLabel())
-        RangeEnd = &*std::next(RangeEnd->getIterator());
-
-      MachineBasicBlock *EHPad = nullptr;
-      for (auto *Succ : MBB->successors()) {
-        if (Succ->isEHPad()) {
-          EHPad = Succ;
-          break;
-        }
-      }
-
-      // Local expression tree before the first call of this range should go
-      // after the nested TRY.
-      SmallPtrSet<const MachineInstr *, 4> AfterSet;
-      AfterSet.insert(RangeBegin);
-      AfterSet.insert(RangeBeginCall);
-      for (auto I = MachineBasicBlock::iterator(RangeBeginCall),
-                E = MBB->begin();
-           I != E; --I) {
-        if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
-          continue;
-        if (WebAssembly::isChild(*std::prev(I), MFI))
-          AfterSet.insert(&*std::prev(I));
-        else
-          break;
-      }
-
-      // Create the nested try instruction.
-      auto InsertPos = getLatestInsertPos(
-          MBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
-      MachineInstr *NestedTry =
-          BuildMI(*MBB, InsertPos, RangeBegin->getDebugLoc(),
-                  TII.get(WebAssembly::TRY))
-              .addImm(int64_t(WebAssembly::BlockType::Void));
-
-      // Create the nested EH pad and fill instructions in.
-      MachineBasicBlock *NestedEHPad = MF.CreateMachineBasicBlock();
-      MF.insert(std::next(MBB->getIterator()), NestedEHPad);
-      NestedEHPad->setIsEHPad();
-      NestedEHPad->setIsEHScopeEntry();
-      BuildMI(NestedEHPad, RangeEnd->getDebugLoc(), TII.get(WebAssembly::CATCH),
-              ExnReg);
-      BuildMI(NestedEHPad, RangeEnd->getDebugLoc(), TII.get(WebAssembly::BR))
-          .addMBB(BrDest);
-
-      // Create the nested continuation BB and end_try instruction.
-      MachineBasicBlock *NestedCont = MF.CreateMachineBasicBlock();
-      MF.insert(std::next(NestedEHPad->getIterator()), NestedCont);
-      MachineInstr *NestedEndTry =
-          BuildMI(*NestedCont, NestedCont->begin(), RangeEnd->getDebugLoc(),
-                  TII.get(WebAssembly::END_TRY));
-      // In case MBB has more instructions after the try range, move them to the
-      // new nested continuation BB.
-      NestedCont->splice(NestedCont->end(), MBB,
-                         std::next(RangeEnd->getIterator()), MBB->end());
-      unstackifyVRegsUsedInSplitBB(*MBB, *NestedCont, MFI, MRI, TII);
-      registerTryScope(NestedTry, NestedEndTry, NestedEHPad);
-
-      // Fix predecessor-successor relationship.
-      NestedCont->transferSuccessors(MBB);
-      if (EHPad) {
-        NestedCont->removeSuccessor(EHPad);
-        // If EHPad does not have any predecessors left after removing
-        // NextedCont predecessor, remove its successor too, because this EHPad
-        // is not reachable from the entry BB anyway. We can't remove EHPad BB
-        // itself because it can contain 'catch' or 'end', which are necessary
-        // for keeping try-catch-end structure.
-        if (EHPad->pred_empty())
-          EHPad->removeSuccessor(BrDest);
-      }
-      MBB->addSuccessor(NestedEHPad);
-      MBB->addSuccessor(NestedCont);
-      NestedEHPad->addSuccessor(BrDest);
-    }
-  }
-
-  // Renumber BBs and recalculate ScopeTop info because new BBs might have been
-  // created and inserted above.
-  MF.RenumberBlocks();
-  ScopeTops.clear();
-  ScopeTops.resize(MF.getNumBlockIDs());
-  for (auto &MBB : reverse(MF)) {
-    for (auto &MI : reverse(MBB)) {
-      if (ScopeTops[MBB.getNumber()])
-        break;
-      switch (MI.getOpcode()) {
-      case WebAssembly::END_BLOCK:
-      case WebAssembly::END_LOOP:
-      case WebAssembly::END_TRY:
-        ScopeTops[MBB.getNumber()] = EndToBegin[&MI]->getParent();
-        break;
-      case WebAssembly::CATCH:
-        ScopeTops[MBB.getNumber()] = EHPadToTry[&MBB]->getParent();
-        break;
-      }
-    }
-  }
-
-  // Recompute the dominator tree.
-  getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
-
-  // Place block markers for newly added branches, if necessary.
-
-  // If we've created an appendix BB and a branch to it, place a block/end_block
-  // marker for that. For some new branches, those branch destination BBs start
-  // with a hoisted end_try marker, so we don't need a new marker there.
-  if (AppendixBB)
-    BrDests.push_back(AppendixBB);
-
-  llvm::sort(BrDests,
-             [&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
-               auto ANum = A->getNumber();
-               auto BNum = B->getNumber();
-               return ANum < BNum;
-             });
-  for (auto *Dest : BrDests)
-    placeBlockMarker(*Dest);
-
-  return true;
+  // TODO Implement this
+  return false;
 }
 
 static unsigned

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
index 5720d3e5afb0..d75afdcefb7d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
@@ -34,6 +34,7 @@ HANDLE_NODETYPE(WIDEN_LOW_U)
 HANDLE_NODETYPE(WIDEN_HIGH_S)
 HANDLE_NODETYPE(WIDEN_HIGH_U)
 HANDLE_NODETYPE(THROW)
+HANDLE_NODETYPE(CATCH)
 HANDLE_NODETYPE(MEMORY_COPY)
 HANDLE_NODETYPE(MEMORY_FILL)
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 75f065a92825..c693bef6d325 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -267,6 +267,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
 
   // Exception handling intrinsics
   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
+  setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
   setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
 
   setMaxAtomicSizeInBitsSupported(64);
@@ -1461,6 +1462,21 @@ SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
                       MachinePointerInfo(SV));
 }
 
+static SDValue getCppExceptionSymNode(SDValue Op, unsigned TagIndex,
+                                      SelectionDAG &DAG) {
+  // We only support C++ exceptions for now
+  int Tag =
+      cast<ConstantSDNode>(Op.getOperand(TagIndex).getNode())->getZExtValue();
+  if (Tag != WebAssembly::CPP_EXCEPTION)
+    llvm_unreachable("Invalid tag: We only support C++ exceptions for now");
+  auto &MF = DAG.getMachineFunction();
+  const auto &TLI = DAG.getTargetLoweringInfo();
+  MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
+  const char *SymName = MF.createExternalSymbolName("__cpp_exception");
+  return DAG.getNode(WebAssemblyISD::Wrapper, SDLoc(Op), PtrVT,
+                     DAG.getTargetExternalSymbol(SymName, PtrVT));
+}
+
 SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
                                                   SelectionDAG &DAG) const {
   MachineFunction &MF = DAG.getMachineFunction();
@@ -1494,15 +1510,7 @@ SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
   }
 
   case Intrinsic::wasm_throw: {
-    // We only support C++ exceptions for now
-    int Tag = cast<ConstantSDNode>(Op.getOperand(2).getNode())->getZExtValue();
-    if (Tag != WebAssembly::CPP_EXCEPTION)
-      llvm_unreachable("Invalid tag!");
-    const TargetLowering &TLI = DAG.getTargetLoweringInfo();
-    MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
-    const char *SymName = MF.createExternalSymbolName("__cpp_exception");
-    SDValue SymNode = DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
-                                  DAG.getTargetExternalSymbol(SymName, PtrVT));
+    SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
     return DAG.getNode(WebAssemblyISD::THROW, DL,
                        MVT::Other, // outchain type
                        {
@@ -1512,6 +1520,19 @@ SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
                        });
   }
 
+  case Intrinsic::wasm_catch: {
+    SDValue SymNode = getCppExceptionSymNode(Op, 2, DAG);
+    return DAG.getNode(WebAssemblyISD::CATCH, DL,
+                       {
+                           MVT::i32,  // outchain type
+                           MVT::Other // return value
+                       },
+                       {
+                           Op.getOperand(0), // inchain
+                           SymNode           // exception symbol
+                       });
+  }
+
   case Intrinsic::wasm_shuffle: {
     // Drop in-chain and replace undefs, but otherwise pass through unchanged
     SDValue Ops[18];

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
index bc2c2d8bbd90..4c5305ecc072 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td
@@ -131,14 +131,11 @@ defm THROW : I<(outs), (ins event_op:$tag, variable_ops),
                (outs), (ins event_op:$tag),
                [(WebAssemblythrow (WebAssemblywrapper texternalsym:$tag))],
                "throw   \t$tag", "throw   \t$tag", 0x08>;
-defm RETHROW : I<(outs), (ins EXNREF:$exn), (outs), (ins), [],
-                 "rethrow \t$exn", "rethrow", 0x09>;
-// Pseudo instruction to be the lowering target of int_wasm_rethrow intrinsic.
-// Will be converted to the real rethrow instruction later.
-let isPseudo = 1 in
-defm RETHROW_IN_CATCH : NRI<(outs), (ins), [(int_wasm_rethrow)],
-                            "rethrow_in_catch", 0>;
+defm RETHROW : NRI<(outs), (ins i32imm:$depth), [], "rethrow \t$depth", 0x09>;
 } // isTerminator = 1, hasCtrlDep = 1, isBarrier = 1
+// For C++ support, we only rethrow the latest exception, thus always setting
+// the depth to 0.
+def : Pat<(int_wasm_rethrow), (RETHROW 0)>;
 
 // Region within which an exception is caught: try / end_try
 let Uses = [VALUE_STACK], Defs = [VALUE_STACK] in {
@@ -146,10 +143,18 @@ defm TRY     : NRI<(outs), (ins Signature:$sig), [], "try     \t$sig", 0x06>;
 defm END_TRY : NRI<(outs), (ins), [], "end_try", 0x0b>;
 } // Uses = [VALUE_STACK], Defs = [VALUE_STACK]
 
-// Catching an exception: catch / extract_exception
-let hasCtrlDep = 1, hasSideEffects = 1 in
-defm CATCH : I<(outs EXNREF:$dst), (ins), (outs), (ins), [],
-               "catch   \t$dst", "catch", 0x07>;
+// Catching an exception: catch / catch_all
+let hasCtrlDep = 1, hasSideEffects = 1 in {
+// TODO Currently 'catch' can only extract an i32, which is sufficient for C++
+// support, but according to the spec 'catch' can extract any number of values
+// based on the event type.
+defm CATCH : I<(outs I32:$dst), (ins event_op:$tag),
+               (outs), (ins event_op:$tag),
+               [(set I32:$dst,
+                 (WebAssemblycatch (WebAssemblywrapper texternalsym:$tag)))],
+               "catch   \t$dst, $tag", "catch   \t$tag", 0x07>;
+defm CATCH_ALL : NRI<(outs), (ins), [], "catch_all", 0x05>;
+}
 
 // Querying / extracing exception: br_on_exn
 // br_on_exn queries an exnref to see if it matches the corresponding exception

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 40a6545530be..dc1f3b4d4dcf 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -81,7 +81,8 @@ def SDT_WebAssemblyWrapper    : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
                                                      SDTCisPtrTy<0>]>;
 def SDT_WebAssemblyWrapperPIC : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
                                                      SDTCisPtrTy<0>]>;
-def SDT_WebAssemblyThrow      : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
+def SDT_WebAssemblyThrow      : SDTypeProfile<0, -1, []>;
+def SDT_WebAssemblyCatch      : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>;
 
 //===----------------------------------------------------------------------===//
 // WebAssembly-specific DAG Nodes.
@@ -107,6 +108,8 @@ def WebAssemblywrapperPIC  : SDNode<"WebAssemblyISD::WrapperPIC",
                                      SDT_WebAssemblyWrapperPIC>;
 def WebAssemblythrow : SDNode<"WebAssemblyISD::THROW", SDT_WebAssemblyThrow,
                               [SDNPHasChain, SDNPVariadic]>;
+def WebAssemblycatch : SDNode<"WebAssemblyISD::CATCH", SDT_WebAssemblyCatch,
+                              [SDNPHasChain, SDNPSideEffect]>;
 
 //===----------------------------------------------------------------------===//
 // WebAssembly-specific Operands.

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
index d9c2ba6a6537..5501af0b2bbd 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
@@ -33,10 +33,10 @@ class WebAssemblyLateEHPrepare final : public MachineFunctionPass {
 
   bool runOnMachineFunction(MachineFunction &MF) override;
   void recordCatchRetBBs(MachineFunction &MF);
-  bool addCatches(MachineFunction &MF);
+  bool hoistCatches(MachineFunction &MF);
+  bool addCatchAlls(MachineFunction &MF);
   bool replaceFuncletReturns(MachineFunction &MF);
   bool removeUnnecessaryUnreachables(MachineFunction &MF);
-  bool addExceptionExtraction(MachineFunction &MF);
   bool restoreStackPointer(MachineFunction &MF);
 
   MachineBasicBlock *getMatchingEHPad(MachineInstr *MI);
@@ -118,14 +118,13 @@ bool WebAssemblyLateEHPrepare::runOnMachineFunction(MachineFunction &MF) {
   bool Changed = false;
   if (MF.getFunction().hasPersonalityFn()) {
     recordCatchRetBBs(MF);
-    Changed |= addCatches(MF);
+    Changed |= hoistCatches(MF);
+    Changed |= addCatchAlls(MF);
     Changed |= replaceFuncletReturns(MF);
   }
   Changed |= removeUnnecessaryUnreachables(MF);
-  if (MF.getFunction().hasPersonalityFn()) {
-    Changed |= addExceptionExtraction(MF);
+  if (MF.getFunction().hasPersonalityFn())
     Changed |= restoreStackPointer(MF);
-  }
   return Changed;
 }
 
@@ -144,20 +143,62 @@ void WebAssemblyLateEHPrepare::recordCatchRetBBs(MachineFunction &MF) {
   }
 }
 
-// Add catch instruction to beginning of catchpads and cleanuppads.
-bool WebAssemblyLateEHPrepare::addCatches(MachineFunction &MF) {
+// Hoist catch instructions to the beginning of their matching EH pad BBs in
+// case,
+// (1) catch instruction is not the first instruction in EH pad.
+// ehpad:
+//   some_other_instruction
+//   ...
+//   %exn = catch 0
+// (2) catch instruction is in a non-EH pad BB. For example,
+// ehpad:
+//   br bb0
+// bb0:
+//   %exn = catch 0
+bool WebAssemblyLateEHPrepare::hoistCatches(MachineFunction &MF) {
+  bool Changed = false;
+  SmallVector<MachineInstr *, 16> Catches;
+  for (auto &MBB : MF)
+    for (auto &MI : MBB)
+      if (WebAssembly::isCatch(MI.getOpcode()))
+        Catches.push_back(&MI);
+
+  for (auto *Catch : Catches) {
+    MachineBasicBlock *EHPad = getMatchingEHPad(Catch);
+    assert(EHPad && "No matching EH pad for catch");
+    auto InsertPos = EHPad->begin();
+    // Skip EH_LABELs in the beginning of an EH pad if present. We don't use
+    // these labels at the moment, but other targets also seem to have an
+    // EH_LABEL instruction in the beginning of an EH pad.
+    while (InsertPos != EHPad->end() && InsertPos->isEHLabel())
+      InsertPos++;
+    if (InsertPos == Catch)
+      continue;
+    Changed = true;
+    EHPad->insert(InsertPos, Catch->removeFromParent());
+  }
+  return Changed;
+}
+
+// Add catch_all to beginning of cleanup pads.
+bool WebAssemblyLateEHPrepare::addCatchAlls(MachineFunction &MF) {
   bool Changed = false;
   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
-  MachineRegisterInfo &MRI = MF.getRegInfo();
+
   for (auto &MBB : MF) {
-    if (MBB.isEHPad()) {
+    if (!MBB.isEHPad())
+      continue;
+    auto InsertPos = MBB.begin();
+    // Skip EH_LABELs in the beginning of an EH pad if present.
+    while (InsertPos != MBB.end() && InsertPos->isEHLabel())
+      InsertPos++;
+    // This runs after hoistCatches(), so we assume that if there is a catch,
+    // that should be the non-EH label first instruction in an EH pad.
+    if (InsertPos == MBB.end() ||
+        !WebAssembly::isCatch(InsertPos->getOpcode())) {
       Changed = true;
-      auto InsertPos = MBB.begin();
-      if (InsertPos->isEHLabel()) // EH pad starts with an EH label
-        ++InsertPos;
-      Register DstReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
-      BuildMI(MBB, InsertPos, MBB.begin()->getDebugLoc(),
-              TII.get(WebAssembly::CATCH), DstReg);
+      BuildMI(MBB, InsertPos, InsertPos->getDebugLoc(),
+              TII.get(WebAssembly::CATCH_ALL));
     }
   }
   return Changed;
@@ -184,17 +225,11 @@ bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
       Changed = true;
       break;
     }
-    case WebAssembly::CLEANUPRET:
-    case WebAssembly::RETHROW_IN_CATCH: {
-      // Replace a cleanupret/rethrow_in_catch with a rethrow
-      auto *EHPad = getMatchingEHPad(TI);
-      auto CatchPos = EHPad->begin();
-      if (CatchPos->isEHLabel()) // EH pad starts with an EH label
-        ++CatchPos;
-      MachineInstr *Catch = &*CatchPos;
-      Register ExnReg = Catch->getOperand(0).getReg();
+    case WebAssembly::CLEANUPRET: {
+      // Replace a cleanupret with a rethrow. For C++ support, currently
+      // rethrow's immediate argument is always 0 (= the latest exception).
       BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::RETHROW))
-          .addReg(ExnReg);
+          .addImm(0);
       TI->eraseFromParent();
       Changed = true;
       break;
@@ -230,156 +265,6 @@ bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(
   return Changed;
 }
 
-// Wasm uses 'br_on_exn' instruction to check the tag of an exception. It takes
-// exnref type object returned by 'catch', and branches to the destination if it
-// matches a given tag. We currently use __cpp_exception symbol to represent the
-// tag for all C++ exceptions.
-//
-// block $l (result i32)
-//   ...
-//   ;; exnref $e is on the stack at this point
-//   br_on_exn $l $e ;; branch to $l with $e's arguments
-//   ...
-// end
-// ;; Here we expect the extracted values are on top of the wasm value stack
-// ... Handle exception using values ...
-//
-// br_on_exn takes an exnref object and branches if it matches the given tag.
-// There can be multiple br_on_exn instructions if we want to match for another
-// tag, but for now we only test for __cpp_exception tag, and if it does not
-// match, i.e., it is a foreign exception, we rethrow it.
-//
-// In the destination BB that's the target of br_on_exn, extracted exception
-// values (in C++'s case a single i32, which represents an exception pointer)
-// are placed on top of the wasm stack. Because we can't model wasm stack in
-// LLVM instruction, we use 'extract_exception' pseudo instruction to retrieve
-// it. The pseudo instruction will be deleted later.
-bool WebAssemblyLateEHPrepare::addExceptionExtraction(MachineFunction &MF) {
-  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
-  MachineRegisterInfo &MRI = MF.getRegInfo();
-  auto *EHInfo = MF.getWasmEHFuncInfo();
-  SmallVector<MachineInstr *, 16> ExtractInstrs;
-  SmallVector<MachineInstr *, 8> ToDelete;
-  for (auto &MBB : MF) {
-    for (auto &MI : MBB) {
-      if (MI.getOpcode() == WebAssembly::EXTRACT_EXCEPTION_I32) {
-        if (MI.getOperand(0).isDead())
-          ToDelete.push_back(&MI);
-        else
-          ExtractInstrs.push_back(&MI);
-      }
-    }
-  }
-  bool Changed = !ToDelete.empty() || !ExtractInstrs.empty();
-  for (auto *MI : ToDelete)
-    MI->eraseFromParent();
-  if (ExtractInstrs.empty())
-    return Changed;
-
-  // Find terminate pads.
-  SmallSet<MachineBasicBlock *, 8> TerminatePads;
-  for (auto &MBB : MF) {
-    for (auto &MI : MBB) {
-      if (MI.isCall()) {
-        const MachineOperand &CalleeOp = MI.getOperand(0);
-        if (CalleeOp.isGlobal() && CalleeOp.getGlobal()->getName() ==
-                                       WebAssembly::ClangCallTerminateFn)
-          TerminatePads.insert(getMatchingEHPad(&MI));
-      }
-    }
-  }
-
-  for (auto *Extract : ExtractInstrs) {
-    MachineBasicBlock *EHPad = getMatchingEHPad(Extract);
-    assert(EHPad && "No matching EH pad for extract_exception");
-    auto CatchPos = EHPad->begin();
-    if (CatchPos->isEHLabel()) // EH pad starts with an EH label
-      ++CatchPos;
-    MachineInstr *Catch = &*CatchPos;
-
-    if (Catch->getNextNode() != Extract)
-      EHPad->insert(Catch->getNextNode(), Extract->removeFromParent());
-
-    // - Before:
-    // ehpad:
-    //   %exnref:exnref = catch
-    //   %exn:i32 = extract_exception
-    //   ... use exn ...
-    //
-    // - After:
-    // ehpad:
-    //   %exnref:exnref = catch
-    //   br_on_exn %thenbb, $__cpp_exception, %exnref
-    //   br %elsebb
-    // elsebb:
-    //   rethrow
-    // thenbb:
-    //   %exn:i32 = extract_exception
-    //   ... use exn ...
-    Register ExnReg = Catch->getOperand(0).getReg();
-    auto *ThenMBB = MF.CreateMachineBasicBlock();
-    auto *ElseMBB = MF.CreateMachineBasicBlock();
-    MF.insert(std::next(MachineFunction::iterator(EHPad)), ElseMBB);
-    MF.insert(std::next(MachineFunction::iterator(ElseMBB)), ThenMBB);
-    ThenMBB->splice(ThenMBB->end(), EHPad, Extract, EHPad->end());
-    ThenMBB->transferSuccessors(EHPad);
-    EHPad->addSuccessor(ThenMBB);
-    EHPad->addSuccessor(ElseMBB);
-
-    DebugLoc DL = Extract->getDebugLoc();
-    const char *CPPExnSymbol = MF.createExternalSymbolName("__cpp_exception");
-    BuildMI(EHPad, DL, TII.get(WebAssembly::BR_ON_EXN))
-        .addMBB(ThenMBB)
-        .addExternalSymbol(CPPExnSymbol)
-        .addReg(ExnReg);
-    BuildMI(EHPad, DL, TII.get(WebAssembly::BR)).addMBB(ElseMBB);
-
-    // When this is a terminate pad with __clang_call_terminate() call, we don't
-    // rethrow it anymore and call __clang_call_terminate() with a nullptr
-    // argument, which will call std::terminate().
-    //
-    // - Before:
-    // ehpad:
-    //   %exnref:exnref = catch
-    //   %exn:i32 = extract_exception
-    //   call @__clang_call_terminate(%exn)
-    //   unreachable
-    //
-    // - After:
-    // ehpad:
-    //   %exnref:exnref = catch
-    //   br_on_exn %thenbb, $__cpp_exception, %exnref
-    //   br %elsebb
-    // elsebb:
-    //   call @__clang_call_terminate(0)
-    //   unreachable
-    // thenbb:
-    //   %exn:i32 = extract_exception
-    //   call @__clang_call_terminate(%exn)
-    //   unreachable
-    if (TerminatePads.count(EHPad)) {
-      Function *ClangCallTerminateFn =
-          MF.getFunction().getParent()->getFunction(
-              WebAssembly::ClangCallTerminateFn);
-      assert(ClangCallTerminateFn &&
-             "There is no __clang_call_terminate() function");
-      Register Reg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
-      BuildMI(ElseMBB, DL, TII.get(WebAssembly::CONST_I32), Reg).addImm(0);
-      BuildMI(ElseMBB, DL, TII.get(WebAssembly::CALL))
-          .addGlobalAddress(ClangCallTerminateFn)
-          .addReg(Reg);
-      BuildMI(ElseMBB, DL, TII.get(WebAssembly::UNREACHABLE));
-
-    } else {
-      BuildMI(ElseMBB, DL, TII.get(WebAssembly::RETHROW)).addReg(ExnReg);
-      if (EHInfo->hasEHPadUnwindDest(EHPad))
-        ElseMBB->addSuccessor(EHInfo->getEHPadUnwindDest(EHPad));
-    }
-  }
-
-  return true;
-}
-
 // After the stack is unwound due to a thrown exception, the __stack_pointer
 // global can point to an invalid address. This inserts instructions that
 // restore __stack_pointer global.
@@ -404,7 +289,7 @@ bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) {
     auto InsertPos = MBB.begin();
     if (InsertPos->isEHLabel()) // EH pad starts with an EH label
       ++InsertPos;
-    if (InsertPos->getOpcode() == WebAssembly::CATCH)
+    if (WebAssembly::isCatch(InsertPos->getOpcode()))
       ++InsertPos;
     FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF, MBB,
                                    InsertPos, MBB.begin()->getDebugLoc());

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index 3943148f138e..6e3bdbf82bd1 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -359,10 +359,9 @@ static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
   if (NextI == Insert)
     return true;
 
-  // 'catch' and 'extract_exception' should be the first instruction of a BB and
-  // cannot move.
-  if (DefI->getOpcode() == WebAssembly::CATCH ||
-      DefI->getOpcode() == WebAssembly::EXTRACT_EXCEPTION_I32)
+  // 'catch' and 'catch_all' should be the first instruction of a BB and cannot
+  // move.
+  if (WebAssembly::isCatch(DefI->getOpcode()))
     return false;
 
   // Check for register dependencies.

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index af16d799d1dc..135055a43afc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -446,7 +446,8 @@ void WebAssemblyPassConfig::addPreEmitPass() {
 
   // Do various transformations for exception handling.
   // Every CFG-changing optimizations should come before this.
-  addPass(createWebAssemblyLateEHPrepare());
+  if (TM->Options.ExceptionModel == ExceptionHandling::Wasm)
+    addPass(createWebAssemblyLateEHPrepare());
 
   // Now that we have a prologue and epilogue and all frame indices are
   // rewritten, eliminate SP and FP. This allows them to be stackified,

diff  --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
index f455d5bcfd4a..f55e23a4d7c4 100644
--- a/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
+++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
@@ -1,15 +1,12 @@
 ; REQUIRES: asserts
 ; TODO Reenable disabled lines after updating the backend to the new spec
 ; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
-; R UN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling
+; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling
 ; R UN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -exception-model=wasm -mattr=+exception-handling | FileCheck %s --check-prefix=NOOPT
 ; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT
 ; R UN: llc < %s -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT-LOCALS
 ; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort -stats 2>&1 | FileCheck %s --check-prefix=NOSORT-STAT
 
-; FIXME A temporary RUN line to make the test pass. Remove this later.
-; RUN: true
-
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 

diff  --git a/llvm/test/CodeGen/WebAssembly/eh-labels.mir b/llvm/test/CodeGen/WebAssembly/eh-labels.mir
index 673d34869b73..105b21acc4f7 100644
--- a/llvm/test/CodeGen/WebAssembly/eh-labels.mir
+++ b/llvm/test/CodeGen/WebAssembly/eh-labels.mir
@@ -34,11 +34,10 @@ body: |
   bb.1 (landing-pad):
   ; predecessors: %bb.0
     successors: %bb.2
-    ; CATCH should be after an EH_LABEL at the beginning of an EH pad
+    ; CATCH_ALL should be after an EH_LABEL at the beginning of an EH pad
     ; CHECK:      EH_LABEL
-    ; CHECK-NEXT: CATCH
+    ; CHECK-NEXT: CATCH_ALL
     EH_LABEL <mcsymbol .Ltmp2>
-    dead %0:i32 = EXTRACT_EXCEPTION_I32 implicit-def dead $arguments
     CATCHRET %bb.2, %bb.0, implicit-def dead $arguments
 
   bb.2:

diff  --git a/llvm/test/CodeGen/WebAssembly/eh-lsda.ll b/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
index 38a2fe4a8d67..c34c76b4d644 100644
--- a/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
+++ b/llvm/test/CodeGen/WebAssembly/eh-lsda.ll
@@ -1,8 +1,4 @@
-; TODO Reenable disabled lines after updating the backend to the new spec
-; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s
-
-; FIXME A temporary RUN line to make the test pass. Remove this later.
-; RUN: true
+; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"

diff  --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll
index f16fe37cd0a1..14eba86c5edd 100644
--- a/llvm/test/CodeGen/WebAssembly/exception.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception.ll
@@ -1,9 +1,5 @@
-; TODO Reenable disabled lines after updating the backend to the new spec
-; R UN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck -allow-deprecated-dag-overlap %s
-; R UN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling
-
-; FIXME A temporary RUN line to make the test pass. Remove this later.
-; RUN: true
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs | FileCheck -allow-deprecated-dag-overlap %s
+; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling
 
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
@@ -34,15 +30,9 @@ define void @test_throw(i8* %p) {
 ; CHECK:     global.get  ${{.+}}=, __stack_pointer
 ; CHECK:     try
 ; CHECK:       call      foo
-; CHECK:     catch     $[[EXNREF:[0-9]+]]=
+; CHECK:     catch     $[[EXN:[0-9]+]]=, __cpp_exception
 ; CHECK:       global.set  __stack_pointer
-; CHECK:       block i32
-; CHECK:         br_on_exn 0, __cpp_exception, $[[EXNREF]]
-; CHECK:         rethrow   $[[EXNREF]]
-; CHECK:       end_block
-; CHECK:       extract_exception $[[EXN:[0-9]+]]=
-; CHECK-DAG:   i32.store  __wasm_lpad_context
-; CHECK-DAG:   i32.store  __wasm_lpad_context{{.+}}
+; CHECK:       i32.{{store|const}} {{.*}} __wasm_lpad_context
 ; CHECK:       call       $drop=, _Unwind_CallPersonality, $[[EXN]]
 ; CHECK:       block
 ; CHECK:         br_if     0
@@ -50,7 +40,7 @@ define void @test_throw(i8* %p) {
 ; CHECK:         call      __cxa_end_catch
 ; CHECK:         br        1
 ; CHECK:       end_block
-; CHECK:       rethrow   $[[EXNREF]]
+; CHECK:       rethrow   0
 ; CHECK:     end_try
 define void @test_catch() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
 entry:
@@ -95,10 +85,10 @@ try.cont:                                         ; preds = %catch, %entry
 ; CHECK-LABEL: test_cleanup:
 ; CHECK: try
 ; CHECK:   call      foo
-; CHECK: catch     $[[EXNREF:[0-9]+]]=
+; CHECK: catch_all
 ; CHECK:   global.set  __stack_pointer
 ; CHECK:   call      $drop=, _ZN4TempD2Ev
-; CHECK:   rethrow   $[[EXNREF]]
+; CHECK:   rethrow   0
 ; CHECK: end_try
 define void @test_cleanup() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
 entry:
@@ -135,17 +125,11 @@ ehcleanup:                                        ; preds = %entry
 ; CHECK:   call      $drop=, __cxa_begin_catch
 ; CHECK:   try
 ; CHECK:     call      foo
-; CHECK:   catch
+; CHECK:   catch_all
 ; CHECK:     try
 ; CHECK:       call      __cxa_end_catch
-; CHECK:     catch
-; CHECK:       block     i32
-; CHECK:         br_on_exn   0, __cpp_exception
-; CHECK:         i32.const  ${{.*}}=, 0
-; CHECK:         call      __clang_call_terminate
-; CHECK:         unreachable
-; CHECK:       end_block
-; CHECK:       call      __clang_call_terminate
+; CHECK:     catch     $[[EXN:[0-9]+]]=, __cpp_exception
+; CHECK:       call      __clang_call_terminate, $[[EXN]]
 ; CHECK:       unreachable
 ; CHECK:     end_try
 ; CHECK:     rethrow

diff  --git a/llvm/test/MC/WebAssembly/annotations.s b/llvm/test/MC/WebAssembly/annotations.s
index c663567f4c7f..f2636ec45bee 100644
--- a/llvm/test/MC/WebAssembly/annotations.s
+++ b/llvm/test/MC/WebAssembly/annotations.s
@@ -11,7 +11,7 @@ test_annotation:
   .eventtype  __cpp_exception i32
   try
   br        0
-  catch
+  catch     __cpp_exception
   block
   br_if     0
   loop
@@ -19,21 +19,16 @@ test_annotation:
   end_loop
   end_block
   try
-  rethrow
-  catch
+  rethrow   0
+  catch     __cpp_exception
   block
   try
   br        0
-  catch
+  catch     __cpp_exception
   local.set 0
-  block    i32
-  local.get 0
-  br_on_exn 0, __cpp_exception
-  rethrow
-  end_block
   end_try
   end_block
-  rethrow
+  rethrow   0
   end_try
   end_try
   end_function
@@ -42,7 +37,7 @@ test_annotation:
 # CHECK:      test_annotation:
 # CHECK:        try
 # CHECK-NEXT:   br        0               # 0: down to label0
-# CHECK-NEXT:   catch                     # catch0:
+# CHECK-NEXT:   catch     __cpp_exception # catch0:
 # CHECK-NEXT:   block
 # CHECK-NEXT:   br_if     0               # 0: down to label1
 # CHECK-NEXT:   loop                      # label2:
@@ -50,21 +45,16 @@ test_annotation:
 # CHECK-NEXT:   end_loop
 # CHECK-NEXT:   end_block                 # label1:
 # CHECK-NEXT:   try
-# CHECK-NEXT:   rethrow                   # down to catch1
-# CHECK-NEXT:   catch                     # catch1:
+# CHECK-NEXT:   rethrow   0               # down to catch1
+# CHECK-NEXT:   catch     __cpp_exception # catch1:
 # CHECK-NEXT:   block
 # CHECK-NEXT:   try
 # CHECK-NEXT:   br        0               # 0: down to label5
-# CHECK-NEXT:   catch                     # catch2:
+# CHECK-NEXT:   catch     __cpp_exception # catch2:
 # CHECK-NEXT:   local.set 0
-# CHECK-NEXT:   block    i32
-# CHECK-NEXT:   local.get 0
-# CHECK-NEXT:   br_on_exn 0, __cpp_exception # 0: down to label6
-# CHECK-NEXT:   rethrow                   # to caller
-# CHECK-NEXT:   end_block                 # label6:
 # CHECK-NEXT:   end_try                   # label5:
 # CHECK-NEXT:   end_block                 # label4:
-# CHECK-NEXT:   rethrow                   # to caller
+# CHECK-NEXT:   rethrow   0               # to caller
 # CHECK-NEXT:   end_try                   # label3:
 # CHECK-NEXT:   end_try                   # label0:
 # CHECK-NEXT:   end_function

diff  --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s
index d45b10d45b0f..786100d91e5c 100644
--- a/llvm/test/MC/WebAssembly/basic-assembly.s
+++ b/llvm/test/MC/WebAssembly/basic-assembly.s
@@ -81,24 +81,18 @@ test0:
     # TODO: enable once instruction has been added.
     #i32x4.trunc_sat_f32x4_s
     i32.trunc_f32_s
-    try         exnref
+    try
     i32.atomic.load 0
     memory.atomic.notify 0
 .LBB0_3:
-    catch
+    catch       __cpp_exception
     local.set   0
-    block       i32
-    local.get   0
-    br_on_exn   0, __cpp_exception
-    rethrow
-.LBB0_4:
-    end_block
     end_try
     i32.const   .L.str
     i32.load8_u .L.str+2
     i32.load16_u .L.str:p2align=0
     throw 0
-.LBB0_5:
+.LBB0_4:
     #i32.trunc_sat_f32_s
     global.get  __stack_pointer
     end_function
@@ -199,24 +193,18 @@ empty_fref_table:
 # CHECK-NEXT:      end_if
 # CHECK-NEXT:      f32x4.add
 # CHECK-NEXT:      i32.trunc_f32_s
-# CHECK-NEXT:      try         exnref
+# CHECK-NEXT:      try
 # CHECK-NEXT:      i32.atomic.load 0
 # CHECK-NEXT:      memory.atomic.notify 0
 # CHECK-NEXT:  .LBB0_3:
-# CHECK-NEXT:      catch
+# CHECK-NEXT:      catch       __cpp_exception
 # CHECK-NEXT:      local.set   0
-# CHECK-NEXT:      block       i32
-# CHECK-NEXT:      local.get   0
-# CHECK-NEXT:      br_on_exn   0, __cpp_exception
-# CHECK-NEXT:      rethrow
-# CHECK-NEXT:  .LBB0_4:
-# CHECK-NEXT:      end_block
 # CHECK-NEXT:      end_try
 # CHECK-NEXT:      i32.const   .L.str
 # CHECK-NEXT:      i32.load8_u .L.str+2
 # CHECK-NEXT:      i32.load16_u .L.str:p2align=0
 # CHECK-NEXT:      throw       0
-# CHECK-NEXT:  .LBB0_5:
+# CHECK-NEXT:  .LBB0_4:
 # CHECK-NEXT:      global.get  __stack_pointer
 # CHECK-NEXT:      end_function
 

diff  --git a/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp b/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp
index a8f6d883028d..c63328a278f7 100644
--- a/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp
+++ b/llvm/unittests/Target/WebAssembly/WebAssemblyExceptionInfoTest.cpp
@@ -100,14 +100,14 @@ body: |
   ; predecessors: %bb.0
     successors: %bb.3, %bb.9
     liveins: $value_stack
-    %0:exnref = CATCH implicit-def $arguments
-    CLEANUPRET implicit-def dead $arguments
+    CATCH_ALL implicit-def $arguments
+    RETHROW 0, implicit-def dead $arguments
 
   bb.3 (landing-pad):
   ; predecessors: %bb.2
     successors: %bb.4, %bb.6
     liveins: $value_stack
-    %1:exnref = CATCH implicit-def $arguments
+    %1:i32 = CATCH &__cpp_exception, implicit-def $arguments
     BR_IF %bb.4, %58:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
     BR %bb.6, implicit-def $arguments
 
@@ -121,7 +121,7 @@ body: |
   ; predecessors: %bb.4
     successors: %bb.7
     liveins: $value_stack
-    CATCHRET %bb.7, %bb.0, implicit-def dead $arguments
+    BR %bb.7, implicit-def dead $arguments
 
   bb.6:
   ; predecessors: %bb.3
@@ -138,14 +138,14 @@ body: |
   ; predecessors: %bb.4
     successors: %bb.9
     liveins: $value_stack
-    %2:exnref = CATCH implicit-def $arguments
-    CLEANUPRET implicit-def dead $arguments
+    CATCH_ALL implicit-def $arguments
+    RETHROW 0, implicit-def dead $arguments
 
   bb.9 (landing-pad):
   ; predecessors: %bb.2, %bb.6, %bb.8
     liveins: $value_stack
-    %3:exnref = CATCH implicit-def $arguments
-    CLEANUPRET implicit-def dead $arguments
+    CATCH_ALL implicit-def $arguments
+    RETHROW 0, implicit-def dead $arguments
 
   bb.10:
   ; predecessors: %bb.6
@@ -257,7 +257,7 @@ body: |
   ; predecessors: %bb.0
     successors: %bb.2, %bb.8
     liveins: $value_stack
-    %0:exnref = CATCH implicit-def $arguments
+    %0:i32 = CATCH &__cpp_exception, implicit-def $arguments
     BR_IF %bb.2, %32:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
     BR %bb.8, implicit-def $arguments
 
@@ -271,7 +271,7 @@ body: |
   ; predecessors: %bb.2
     successors: %bb.4, %bb.6
     liveins: $value_stack
-    %1:exnref = CATCH implicit-def $arguments
+    %1:i32 = CATCH &__cpp_exception, implicit-def $arguments
     BR_IF %bb.4, %43:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
     BR %bb.6, implicit-def $arguments
 
@@ -285,7 +285,7 @@ body: |
   ; predecessors: %bb.4
     successors: %bb.7(0x80000000); %bb.7(200.00%)
     liveins: $value_stack
-    CATCHRET %bb.7, %bb.1, implicit-def dead $arguments
+    BR %bb.7, implicit-def dead $arguments
 
   bb.6:
   ; predecessors: %bb.3
@@ -297,7 +297,7 @@ body: |
   ; predecessors: %bb.2, %bb.5
     successors: %bb.9(0x80000000); %bb.9(200.00%)
     liveins: $value_stack
-    CATCHRET %bb.9, %bb.0, implicit-def dead $arguments
+    BR %bb.9, implicit-def dead $arguments
 
   bb.8:
   ; predecessors: %bb.1
@@ -313,14 +313,14 @@ body: |
   ; predecessors: %bb.4
     successors: %bb.11
     liveins: $value_stack
-    %2:exnref = CATCH implicit-def $arguments
-    CLEANUPRET implicit-def dead $arguments
+    CATCH_ALL implicit-def $arguments
+    RETHROW 0, implicit-def dead $arguments
 
   bb.11 (landing-pad):
   ; predecessors: %bb.2, %bb.6, %bb.10
     liveins: $value_stack
-    %3:exnref = CATCH implicit-def $arguments
-    CLEANUPRET implicit-def dead $arguments
+    CATCH_ALL implicit-def $arguments
+    RETHROW 0, implicit-def dead $arguments
 
   bb.12:
   ; predecessors: %bb.6


        


More information about the llvm-commits mailing list