[llvm] r255422 - [IR] Reformulate LLVM's EH funclet IR

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 11 21:38:58 PST 2015


Author: majnemer
Date: Fri Dec 11 23:38:55 2015
New Revision: 255422

URL: http://llvm.org/viewvc/llvm-project?rev=255422&view=rev
Log:
[IR] Reformulate LLVM's EH funclet IR

While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
  but they are difficult to explain to others, even to seasoned LLVM
  experts.
- catchendpad and cleanupendpad are optimization barriers.  They cannot
  be split and force all potentially throwing call-sites to be invokes.
  This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
  It is unsplittable, starts a funclet, and has control flow to other
  funclets.
- The nesting relationship between funclets is currently a property of
  control flow edges.  Because of this, we are forced to carefully
  analyze the flow graph to see if there might potentially exist illegal
  nesting among funclets.  While we have logic to clone funclets when
  they are illegally nested, it would be nicer if we had a
  representation which forbade them upfront.

Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
  flow, just a bunch of simple operands;  catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
  the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
  the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad.  Their presence can be inferred
  implicitly using coloring information.

N.B.  The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for.  An expert should take a
look to make sure the results are reasonable.

Reviewers: rnk, JosephTremoulet, andrew.w.kaylor

Differential Revision: http://reviews.llvm.org/D15139

Added:
    llvm/trunk/test/CodeGen/X86/win-catchpad-nested-cxx.ll
    llvm/trunk/test/CodeGen/X86/win32-seh-nested-finally.ll
      - copied, changed from r255418, llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll
    llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll
      - copied, changed from r255418, llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll
    llvm/trunk/test/CodeGen/X86/wineh-exceptionpointer.ll
      - copied, changed from r255418, llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll
    llvm/trunk/test/Transforms/LoopUnswitch/cleanuppad.ll
    llvm/trunk/test/Transforms/Sink/catchswitch.ll
    llvm/trunk/test/Verifier/invalid-eh.ll
Removed:
    llvm/trunk/test/Assembler/invalid-OperatorConstraint.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll
    llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll
Modified:
    llvm/trunk/docs/ExceptionHandling.rst
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm-c/Core.h
    llvm/trunk/include/llvm/Analysis/EHPersonalities.h
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
    llvm/trunk/include/llvm/IR/IRBuilder.h
    llvm/trunk/include/llvm/IR/InstVisitor.h
    llvm/trunk/include/llvm/IR/InstrTypes.h
    llvm/trunk/include/llvm/IR/Instruction.def
    llvm/trunk/include/llvm/IR/Instruction.h
    llvm/trunk/include/llvm/IR/Instructions.h
    llvm/trunk/include/llvm/Transforms/Utils/Local.h
    llvm/trunk/lib/Analysis/CaptureTracking.cpp
    llvm/trunk/lib/Analysis/EHPersonalities.cpp
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/lib/Analysis/LoopInfo.cpp
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLParser.h
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
    llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/IR/Dominators.cpp
    llvm/trunk/lib/IR/Instruction.cpp
    llvm/trunk/lib/IR/Instructions.cpp
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/lib/Target/X86/X86WinEHState.cpp
    llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp
    llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
    llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
    llvm/trunk/lib/Transforms/Scalar/Sink.cpp
    llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
    llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
    llvm/trunk/lib/Transforms/Utils/Local.cpp
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/trunk/test/Bitcode/compatibility.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-cloning.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-intrinsics.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-no-demotion.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll
    llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering.ll
    llvm/trunk/test/CodeGen/X86/branchfolding-catchpads.ll
    llvm/trunk/test/CodeGen/X86/catchpad-realign-savexmm.ll
    llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll
    llvm/trunk/test/CodeGen/X86/catchpad-weight.ll
    llvm/trunk/test/CodeGen/X86/catchret-empty-fallthrough.ll
    llvm/trunk/test/CodeGen/X86/catchret-fallthrough.ll
    llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll
    llvm/trunk/test/CodeGen/X86/cleanuppad-large-codemodel.ll
    llvm/trunk/test/CodeGen/X86/cleanuppad-realign.ll
    llvm/trunk/test/CodeGen/X86/funclet-layout.ll
    llvm/trunk/test/CodeGen/X86/late-address-taken.ll
    llvm/trunk/test/CodeGen/X86/seh-catch-all-win32.ll
    llvm/trunk/test/CodeGen/X86/seh-catch-all.ll
    llvm/trunk/test/CodeGen/X86/seh-catchpad.ll
    llvm/trunk/test/CodeGen/X86/seh-except-finally.ll
    llvm/trunk/test/CodeGen/X86/seh-exception-code.ll
    llvm/trunk/test/CodeGen/X86/seh-finally.ll
    llvm/trunk/test/CodeGen/X86/seh-safe-div-win32.ll
    llvm/trunk/test/CodeGen/X86/seh-safe-div.ll
    llvm/trunk/test/CodeGen/X86/seh-stack-realign.ll
    llvm/trunk/test/CodeGen/X86/tail-dup-catchret.ll
    llvm/trunk/test/CodeGen/X86/tail-merge-wineh.ll
    llvm/trunk/test/CodeGen/X86/win-catchpad-csrs.ll
    llvm/trunk/test/CodeGen/X86/win-catchpad-nested.ll
    llvm/trunk/test/CodeGen/X86/win-catchpad-varargs.ll
    llvm/trunk/test/CodeGen/X86/win-catchpad.ll
    llvm/trunk/test/CodeGen/X86/win-cleanuppad.ll
    llvm/trunk/test/CodeGen/X86/win-funclet-cfi.ll
    llvm/trunk/test/CodeGen/X86/win-mixed-ehpersonality.ll
    llvm/trunk/test/CodeGen/X86/win32-eh-states.ll
    llvm/trunk/test/CodeGen/X86/win32-eh.ll
    llvm/trunk/test/CodeGen/X86/win32-seh-catchpad-realign.ll
    llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll
    llvm/trunk/test/Feature/exception.ll
    llvm/trunk/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll
    llvm/trunk/test/Transforms/GVN/funclet.ll
    llvm/trunk/test/Transforms/GVN/pre-load.ll
    llvm/trunk/test/Transforms/Inline/PR25155.ll
    llvm/trunk/test/Transforms/InstCombine/token.ll
    llvm/trunk/test/Transforms/LoopStrengthReduce/funclet.ll
    llvm/trunk/test/Transforms/LoopStrengthReduce/pr25541.ll
    llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll
    llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll
    llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp

Modified: llvm/trunk/docs/ExceptionHandling.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ExceptionHandling.rst?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/docs/ExceptionHandling.rst (original)
+++ llvm/trunk/docs/ExceptionHandling.rst Fri Dec 11 23:38:55 2015
@@ -522,16 +522,12 @@ table.
 Exception Handling using the Windows Runtime
 =================================================
 
-(Note: Windows C++ exception handling support is a work in progress and is not
-yet fully implemented.  The text below describes how it will work when
-completed.)
-
 Background on Windows exceptions
 ---------------------------------
 
-Interacting with exceptions on Windows is significantly more complicated than on
-Itanium C++ ABI platforms. The fundamental difference between the two models is
-that Itanium EH is designed around the idea of "successive unwinding," while
+Interacting with exceptions on Windows is significantly more complicated than
+on Itanium C++ ABI platforms. The fundamental difference between the two models
+is that Itanium EH is designed around the idea of "successive unwinding," while
 Windows EH is not.
 
 Under Itanium, throwing an exception typically involes allocating thread local
@@ -618,10 +614,11 @@ purposes.
 
 The following new instructions are considered "exception handling pads", in that
 they must be the first non-phi instruction of a basic block that may be the
-unwind destination of an invoke: ``catchpad``, ``cleanuppad``, and
-``terminatepad``. As with landingpads, when entering a try scope, if the
+unwind destination of an EH flow edge:
+``catchswitch``, ``catchpad``, ``cleanuppad``, and ``terminatepad``.
+As with landingpads, when entering a try scope, if the
 frontend encounters a call site that may throw an exception, it should emit an
-invoke that unwinds to a ``catchpad`` block. Similarly, inside the scope of a
+invoke that unwinds to a ``catchswitch`` block. Similarly, inside the scope of a
 C++ object with a destructor, invokes should unwind to a ``cleanuppad``. The
 ``terminatepad`` instruction exists to represent ``noexcept`` and throw
 specifications with one combined instruction. All potentially throwing calls in
@@ -634,26 +631,20 @@ generated funclet).  A catch handler whi
 executes a ``catchret`` instruction, which is a terminator indicating where in
 the function control is returned to.  A cleanup handler which reaches its end
 by normal execution executes a ``cleanupret`` instruction, which is a terminator
-indicating where the active exception will unwind to next.  A catch or cleanup
-handler which is exited by another exception being raised during its execution will
-unwind through a ``catchendpad`` or ``cleanuupendpad`` (respectively).  The
-``catchendpad`` and ``cleanupendpad`` instructions are considered "exception
-handling pads" in the same sense that ``catchpad``, ``cleanuppad``, and
-``terminatepad`` are.
-
-Each of these new EH pad instructions has a way to identify which
-action should be considered after this action. The ``catchpad`` and
-``terminatepad`` instructions are terminators, and have a label operand considered
-to be an unwind destination analogous to the unwind destination of an invoke. The
-``cleanuppad`` instruction is different from the other two in that it is not a
-terminator. The code inside a cleanuppad runs before transferring control to the
-next action, so the ``cleanupret`` and ``cleanupendpad`` instructions are the
-instructions that hold a label operand and unwind to the next EH pad. All of
-these "unwind edges" may refer to a basic block that contains an EH pad instruction,
-or they may simply unwind to the caller. Unwinding to the caller has roughly the
-same semantics as the ``resume`` instruction in the ``landingpad`` model. When
-inlining through an invoke, instructions that unwind to the caller are hooked
-up to unwind to the unwind destination of the call site.
+indicating where the active exception will unwind to next.
+
+Each of these new EH pad instructions has a way to identify which action should
+be considered after this action. The ``catchswitch`` and ``terminatepad``
+instructions are terminators, and have a unwind destination operand analogous
+to the unwind destination of an invoke.  The ``cleanuppad`` instruction is not
+a terminator, so the unwind destination is stored on the ``cleanupret``
+instruction instead. Successfully executing a catch handler should resume
+normal control flow, so neither ``catchpad`` nor ``catchret`` instructions can
+unwind. All of these "unwind edges" may refer to a basic block that contains an
+EH pad instruction, or they may unwind to the caller.  Unwinding to the caller
+has roughly the same semantics as the ``resume`` instruction in the landingpad
+model. When inlining through an invoke, instructions that unwind to the caller
+are hooked up to unwind to the unwind destination of the call site.
 
 Putting things together, here is a hypothetical lowering of some C++ that uses
 all of the new IR instructions:
@@ -694,33 +685,95 @@ all of the new IR instructions:
     call void @"\01??_DCleanup@@QEAA at XZ"(%struct.Cleanup* nonnull %obj) nounwind
     br label %return
 
-  return:                                           ; preds = %invoke.cont.2, %invoke.cont.3
-    %retval.0 = phi i32 [ 0, %invoke.cont.2 ], [ %9, %catch ]
+  return:                                           ; preds = %invoke.cont.3, %invoke.cont.2
+    %retval.0 = phi i32 [ 0, %invoke.cont.2 ], [ %3, %invoke.cont.3 ]
     ret i32 %retval.0
 
-  ; EH scope code, ordered innermost to outermost:
-
-  lpad.cleanup:                                     ; preds = %invoke.cont
-    %cleanup = cleanuppad []
-    call void @"\01??_DCleanup@@QEAA at XZ"(%struct.Cleanup* nonnull %obj) nounwind
-    cleanupret %cleanup unwind label %lpad.catch
+  lpad.cleanup:                                     ; preds = %invoke.cont.2
+    %0 = cleanuppad within none []
+    call void @"\01??1Cleanup@@QEAA at XZ"(%struct.Cleanup* nonnull %obj) nounwind
+    cleanupret %0 unwind label %lpad.catch
 
-  lpad.catch:                                       ; preds = %entry, %lpad.cleanup
-    %catch = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i32* %e]
-            to label %catch.body unwind label %catchend
+  lpad.catch:                                       ; preds = %lpad.cleanup, %entry
+    %1 = catchswitch within none [label %catch.body] unwind label %lpad.terminate
 
   catch.body:                                       ; preds = %lpad.catch
+    %catch = catchpad within %1 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i32* %e]
     invoke void @"\01?may_throw@@YAXXZ"()
-            to label %invoke.cont.3 unwind label %catchend
+            to label %invoke.cont.3 unwind label %lpad.terminate
 
   invoke.cont.3:                                    ; preds = %catch.body
-    %9 = load i32, i32* %e, align 4
-    catchret %catch to label %return
+    %3 = load i32, i32* %e, align 4
+    catchret from %catch to label %return
 
-  catchend:                                         ; preds = %lpad.catch, %catch.body
-    catchendpad unwind label %lpad.terminate
+  lpad.terminate:                                   ; preds = %catch.body, %lpad.catch
+    terminatepad within none [void ()* @"\01?terminate@@YAXXZ"] unwind to caller
+  }
+
+Funclet parent tokens
+-----------------------
 
-  lpad.terminate:                                   ; preds = %catchend
-    terminatepad [void ()* @"\01?terminate@@YAXXZ"]
-            unwind to caller
+In order to produce tables for EH personalities that use funclets, it is
+necessary to recover the nesting that was present in the source. This funclet
+parent relationship is encoded in the IR using tokens produced by the new "pad"
+instructions. The token operand of a "pad" or "ret" instruction indicates which
+funclet it is in, or "none" if it is not nested within another funclet.
+
+The ``catchpad`` and ``cleanuppad`` instructions establish new funclets, and
+their tokens are consumed by other "pad" instructions to establish membership.
+The ``catchswitch`` instruction does not create a funclet, but it produces a
+token that is always consumed by its immediate successor ``catchpad``
+instructions. This ensures that every catch handler modelled by a ``catchpad``
+belongs to exactly one ``catchswitch``, which models the dispatch point after a
+C++ try. The ``terminatepad`` instruction cannot contain lexically nested
+funclets inside the termination action, so it does not produce a token.
+
+Here is an example of what this nesting looks like using some hypothetical
+C++ code:
+
+.. code-block:: c
+
+  void f() {
+    try {
+      throw;
+    } catch (...) {
+      try {
+        throw;
+      } catch (...) {
+      }
+    }
   }
+
+.. code-block:: llvm
+  define void @f() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+  entry:
+    invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
+            to label %unreachable unwind label %catch.dispatch
+
+  catch.dispatch:                                   ; preds = %entry
+    %0 = catchswitch within none [label %catch] unwind to caller
+
+  catch:                                            ; preds = %catch.dispatch
+    %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+    invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
+            to label %unreachable unwind label %catch.dispatch2
+
+  catch.dispatch2:                                  ; preds = %catch
+    %2 = catchswitch within %1 [label %catch3] unwind to caller
+
+  catch3:                                           ; preds = %catch.dispatch2
+    %3 = catchpad within %2 [i8* null, i32 64, i8* null]
+    catchret from %3 to label %try.cont
+
+  try.cont:                                         ; preds = %catch3
+    catchret from %1 to label %try.cont6
+
+  try.cont6:                                        ; preds = %try.cont
+    ret void
+
+  unreachable:                                      ; preds = %catch, %entry
+    unreachable
+  }
+
+The "inner" ``catchswitch`` consumes ``%1`` which is produced by the outer
+catchswitch.

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Fri Dec 11 23:38:55 2015
@@ -5001,10 +5001,8 @@ control flow, not values (the one except
 The terminator instructions are: ':ref:`ret <i_ret>`',
 ':ref:`br <i_br>`', ':ref:`switch <i_switch>`',
 ':ref:`indirectbr <i_indirectbr>`', ':ref:`invoke <i_invoke>`',
-':ref:`resume <i_resume>`', ':ref:`catchpad <i_catchpad>`',
-':ref:`catchendpad <i_catchendpad>`',
+':ref:`resume <i_resume>`', ':ref:`catchswitch <i_catchswitch>`',
 ':ref:`catchret <i_catchret>`',
-':ref:`cleanupendpad <i_cleanupendpad>`',
 ':ref:`cleanupret <i_cleanupret>`',
 ':ref:`terminatepad <i_terminatepad>`',
 and ':ref:`unreachable <i_unreachable>`'.
@@ -5362,9 +5360,9 @@ Example:
 
       resume { i8*, i32 } %exn
 
-.. _i_catchpad:
+.. _i_catchswitch:
 
-'``catchpad``' Instruction
+'``catchswitch``' Instruction
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Syntax:
@@ -5372,155 +5370,125 @@ Syntax:
 
 ::
 
-      <resultval> = catchpad [<args>*]
-          to label <normal label> unwind label <exception label>
+      <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind to caller
+      <resultval> = catchswitch within <parent> [ label <handler1>, label <handler2>, ... ] unwind label <default>
 
 Overview:
 """""""""
 
-The '``catchpad``' instruction is used by `LLVM's exception handling
-system <ExceptionHandling.html#overview>`_ to specify that a basic block
-is a catch block --- one where a personality routine attempts to transfer
-control to catch an exception.
-The ``args`` correspond to whatever information the personality
-routine requires to know if this is an appropriate place to catch the
-exception. Control is transfered to the ``exception`` label if the
-``catchpad`` is not an appropriate handler for the in-flight exception.
-The ``normal`` label should contain the code found in the ``catch``
-portion of a ``try``/``catch`` sequence. The ``resultval`` has the type
-:ref:`token <t_token>` and is used to match the ``catchpad`` to
-corresponding :ref:`catchrets <i_catchret>`.
+The '``catchswitch``' instruction is used by `LLVM's exception handling system
+<ExceptionHandling.html#overview>`_ to describe the set of possible catch handlers
+that may be executed by the :ref:`EH personality routine <personalityfn>`.
 
 Arguments:
 """"""""""
 
-The instruction takes a list of arbitrary values which are interpreted
-by the :ref:`personality function <personalityfn>`.
+The ``parent`` argument is the token of the funclet that contains the
+``catchswitch`` instruction. If the ``catchswitch`` is not inside a funclet,
+this operand may be the token ``none``.
 
-The ``catchpad`` must be provided a ``normal`` label to transfer control
-to if the ``catchpad`` matches the exception and an ``exception``
-label to transfer control to if it doesn't.
+The ``default`` argument is the label of another basic block beginning with a
+"pad" instruction, one of ``cleanuppad``, ``terminatepad``, or
+``catchswitch``.
+
+The ``handlers`` are a list of successor blocks that each begin with a
+:ref:`catchpad <i_catchpad>` instruction.
 
 Semantics:
 """"""""""
 
-When the call stack is being unwound due to an exception being thrown,
-the exception is compared against the ``args``. If it doesn't match,
-then control is transfered to the ``exception`` basic block.
-As with calling conventions, how the personality function results are
-represented in LLVM IR is target specific.
+Executing this instruction transfers control to one of the successors in
+``handlers``, if appropriate, or continues to unwind via the unwind label if
+present.
 
-The ``catchpad`` instruction has several restrictions:
-
--  A catch block is a basic block which is the unwind destination of
-   an exceptional instruction.
--  A catch block must have a '``catchpad``' instruction as its
-   first non-PHI instruction.
--  A catch block's ``exception`` edge must refer to a catch block or a
-   catch-end block.
--  There can be only one '``catchpad``' instruction within the
-   catch block.
--  A basic block that is not a catch block may not include a
-   '``catchpad``' instruction.
--  A catch block which has another catch block as a predecessor may not have
-   any other predecessors.
--  It is undefined behavior for control to transfer from a ``catchpad`` to a
-   ``ret`` without first executing a ``catchret`` that consumes the
-   ``catchpad`` or unwinding through its ``catchendpad``.
--  It is undefined behavior for control to transfer from a ``catchpad`` to
-   itself without first executing a ``catchret`` that consumes the
-   ``catchpad`` or unwinding through its ``catchendpad``.
+The ``catchswitch`` is both a terminator and a "pad" instruction, meaning that
+it must be both the first non-phi instruction and last instruction in the basic
+block. Therefore, it must be the only non-phi instruction in the block.
 
 Example:
 """"""""
 
 .. code-block:: llvm
 
-      ;; A catch block which can catch an integer.
-      %tok = catchpad [i8** @_ZTIi]
-        to label %int.handler unwind label %terminate
+    dispatch1:
+      %cs1 = catchswitch within none [label %handler0, label %handler1] unwind to caller
+    dispatch2:
+      %cs2 = catchswitch within %parenthandler [label %handler0] unwind label %cleanup
 
-.. _i_catchendpad:
+.. _i_catchpad:
 
-'``catchendpad``' Instruction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+'``catchpad``' Instruction
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Syntax:
 """""""
 
 ::
 
-      catchendpad unwind label <nextaction>
-      catchendpad unwind to caller
+      <resultval> = catchpad within <catchswitch> [<args>*]
 
 Overview:
 """""""""
 
-The '``catchendpad``' instruction is used by `LLVM's exception handling
-system <ExceptionHandling.html#overview>`_ to communicate to the
-:ref:`personality function <personalityfn>` which invokes are associated
-with a chain of :ref:`catchpad <i_catchpad>` instructions; propagating an
-exception out of a catch handler is represented by unwinding through its
-``catchendpad``.  Unwinding to the outer scope when a chain of catch handlers
-do not handle an exception is also represented by unwinding through their
-``catchendpad``.
-
-The ``nextaction`` label indicates where control should transfer to if
-none of the ``catchpad`` instructions are suitable for catching the
-in-flight exception.
-
-If a ``nextaction`` label is not present, the instruction unwinds out of
-its parent function. The
-:ref:`personality function <personalityfn>` will continue processing
-exception handling actions in the caller.
+The '``catchpad``' instruction is used by `LLVM's exception handling
+system <ExceptionHandling.html#overview>`_ to specify that a basic block
+begins a catch handler --- one where a personality routine attempts to transfer
+control to catch an exception.
 
 Arguments:
 """"""""""
 
-The instruction optionally takes a label, ``nextaction``, indicating
-where control should transfer to if none of the preceding
-``catchpad`` instructions are suitable for the in-flight exception.
+The ``catchswitch`` operand must always be a token produced by a
+:ref:`catchswitch <i_catchswitch>` instruction in a predecessor block. This
+ensures that each ``catchpad`` has exactly one predecessor block, and it always
+terminates in a ``catchswitch``.
+
+The ``args`` correspond to whatever information the personality routine
+requires to know if this is an appropriate handler for the exception. Control
+will transfer to the ``catchpad`` if this is the first appropriate handler for
+the exception.
+
+The ``resultval`` has the type :ref:`token <t_token>` and is used to match the
+``catchpad`` to corresponding :ref:`catchrets <i_catchret>` and other nested EH
+pads.
 
 Semantics:
 """"""""""
 
-When the call stack is being unwound due to an exception being thrown
-and none of the constituent ``catchpad`` instructions match, then
-control is transfered to ``nextaction`` if it is present. If it is not
-present, control is transfered to the caller.
+When the call stack is being unwound due to an exception being thrown, the
+exception is compared against the ``args``. If it doesn't match, control will
+not reach the ``catchpad`` instruction.  The representation of ``args`` is
+entirely target and personality function-specific.
 
-The ``catchendpad`` instruction has several restrictions:
+Like the :ref:`landingpad <i_landingpad>` instruction, the ``catchpad``
+instruction must be the first non-phi of its parent basic block.
 
--  A catch-end block is a basic block which is the unwind destination of
-   an exceptional instruction.
--  A catch-end block must have a '``catchendpad``' instruction as its
-   first non-PHI instruction.
--  There can be only one '``catchendpad``' instruction within the
-   catch-end block.
--  A basic block that is not a catch-end block may not include a
-   '``catchendpad``' instruction.
--  Exactly one catch block may unwind to a ``catchendpad``.
-- It is undefined behavior to execute a ``catchendpad`` if none of the
-  '``catchpad``'s chained to it have been executed.
-- It is undefined behavior to execute a ``catchendpad`` twice without an
-  intervening execution of one or more of the '``catchpad``'s chained to it.
-- It is undefined behavior to execute a ``catchendpad`` if, after the most
-  recent execution of the normal successor edge of any ``catchpad`` chained
-  to it, some ``catchret`` consuming that ``catchpad`` has already been
-  executed.
-- It is undefined behavior to execute a ``catchendpad`` if, after the most
-  recent execution of the normal successor edge of any ``catchpad`` chained
-  to it, any other ``catchpad`` or ``cleanuppad`` has been executed but has
-  not had a corresponding
-  ``catchret``/``cleanupret``/``catchendpad``/``cleanupendpad`` executed.
+The meaning of the tokens produced and consumed by ``catchpad`` and other "pad"
+instructions is described in the
+`Windows exception handling documentation <ExceptionHandling.html#wineh>`.
+
+Executing a ``catchpad`` instruction constitutes "entering" that pad.
+The pad may then be "exited" in one of three ways:
+1)  explicitly via a ``catchret`` that consumes it.  Executing such a ``catchret``
+    is undefined behavior if any descendant pads have been entered but not yet
+    exited.
+2)  implicitly via a call (which unwinds all the way to the current function's caller),
+    or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
+3)  implicitly via an unwind edge whose destination EH pad isn't a descendant of
+    the ``catchpad``.  When the ``catchpad`` is exited in this manner, it is
+    undefined behavior if the destination EH pad has a parent which is not an
+    ancestor of the ``catchpad`` being exited.
 
 Example:
 """"""""
 
 .. code-block:: llvm
 
-      catchendpad unwind label %terminate
-      catchendpad unwind to caller
+    dispatch:
+      %cs = catchswitch within none [label %handler0] unwind to caller
+      ;; A catch block which can catch an integer.
+    handler0:
+      %tok = catchpad within %cs [i8** @_ZTIi]
 
 .. _i_catchret:
 
@@ -5532,7 +5500,7 @@ Syntax:
 
 ::
 
-      catchret <value> to label <normal>
+      catchret from <token> to label <normal>
 
 Overview:
 """""""""
@@ -5552,105 +5520,24 @@ transfer to next.
 Semantics:
 """"""""""
 
-The '``catchret``' instruction ends the existing (in-flight) exception
-whose unwinding was interrupted with a
-:ref:`catchpad <i_catchpad>` instruction.
-The :ref:`personality function <personalityfn>` gets a chance to execute
-arbitrary code to, for example, run a C++ destructor.
-Control then transfers to ``normal``.
-It may be passed an optional, personality specific, value.
-
-It is undefined behavior to execute a ``catchret`` whose ``catchpad`` has
-not been executed.
+The '``catchret``' instruction ends an existing (in-flight) exception whose
+unwinding was interrupted with a :ref:`catchpad <i_catchpad>` instruction.  The
+:ref:`personality function <personalityfn>` gets a chance to execute arbitrary
+code to, for example, destroy the active exception.  Control then transfers to
+``normal``.
 
-It is undefined behavior to execute a ``catchret`` if, after the most recent
-execution of its ``catchpad``, some ``catchret`` or ``catchendpad`` linked
-to the same ``catchpad`` has already been executed.
-
-It is undefined behavior to execute a ``catchret`` if, after the most recent
-execution of its ``catchpad``, any other ``catchpad`` or ``cleanuppad`` has
-been executed but has not had a corresponding
-``catchret``/``cleanupret``/``catchendpad``/``cleanupendpad`` executed.
+The ``token`` argument must be a token produced by a dominating ``catchpad``
+instruction. The ``catchret`` destroys the physical frame established by
+``catchpad``, so executing multiple returns on the same token without
+re-executing the ``catchpad`` will result in undefined behavior.
+See :ref:`catchpad <i_catchpad>` for more details.
 
 Example:
 """"""""
 
 .. code-block:: llvm
 
-      catchret %catch label %continue
-
-.. _i_cleanupendpad:
-
-'``cleanupendpad``' Instruction
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Syntax:
-"""""""
-
-::
-
-      cleanupendpad <value> unwind label <nextaction>
-      cleanupendpad <value> unwind to caller
-
-Overview:
-"""""""""
-
-The '``cleanupendpad``' instruction is used by `LLVM's exception handling
-system <ExceptionHandling.html#overview>`_ to communicate to the
-:ref:`personality function <personalityfn>` which invokes are associated
-with a :ref:`cleanuppad <i_cleanuppad>` instructions; propagating an exception
-out of a cleanup is represented by unwinding through its ``cleanupendpad``.
-
-The ``nextaction`` label indicates where control should unwind to next, in the
-event that a cleanup is exited by means of an(other) exception being raised.
-
-If a ``nextaction`` label is not present, the instruction unwinds out of
-its parent function. The
-:ref:`personality function <personalityfn>` will continue processing
-exception handling actions in the caller.
-
-Arguments:
-""""""""""
-
-The '``cleanupendpad``' instruction requires one argument, which indicates
-which ``cleanuppad`` it exits, and must be a :ref:`cleanuppad <i_cleanuppad>`.
-It also has an optional successor, ``nextaction``, indicating where control
-should transfer to.
-
-Semantics:
-""""""""""
-
-When and exception propagates to a ``cleanupendpad``, control is transfered to
-``nextaction`` if it is present. If it is not present, control is transfered to
-the caller.
-
-The ``cleanupendpad`` instruction has several restrictions:
-
--  A cleanup-end block is a basic block which is the unwind destination of
-   an exceptional instruction.
--  A cleanup-end block must have a '``cleanupendpad``' instruction as its
-   first non-PHI instruction.
--  There can be only one '``cleanupendpad``' instruction within the
-   cleanup-end block.
--  A basic block that is not a cleanup-end block may not include a
-   '``cleanupendpad``' instruction.
-- It is undefined behavior to execute a ``cleanupendpad`` whose ``cleanuppad``
-  has not been executed.
-- It is undefined behavior to execute a ``cleanupendpad`` if, after the most
-  recent execution of its ``cleanuppad``, some ``cleanupret`` or ``cleanupendpad``
-  consuming the same ``cleanuppad`` has already been executed.
-- It is undefined behavior to execute a ``cleanupendpad`` if, after the most
-  recent execution of its ``cleanuppad``, any other ``cleanuppad`` or
-  ``catchpad`` has been executed but has not had a corresponding
-  ``cleanupret``/``catchret``/``cleanupendpad``/``catchendpad`` executed.
-
-Example:
-""""""""
-
-.. code-block:: llvm
-
-      cleanupendpad %cleanup unwind label %terminate
-      cleanupendpad %cleanup unwind to caller
+      catchret from %catch label %continue
 
 .. _i_cleanupret:
 
@@ -5662,8 +5549,8 @@ Syntax:
 
 ::
 
-      cleanupret <value> unwind label <continue>
-      cleanupret <value> unwind to caller
+      cleanupret from <value> unwind label <continue>
+      cleanupret from <value> unwind to caller
 
 Overview:
 """""""""
@@ -5687,25 +5574,20 @@ The '``cleanupret``' instruction indicat
 :ref:`cleanuppad <i_cleanuppad>` it transferred control to has ended.
 It transfers control to ``continue`` or unwinds out of the function.
 
-It is undefined behavior to execute a ``cleanupret`` whose ``cleanuppad`` has
-not been executed.
-
-It is undefined behavior to execute a ``cleanupret`` if, after the most recent
-execution of its ``cleanuppad``, some ``cleanupret`` or ``cleanupendpad``
-consuming the same ``cleanuppad`` has already been executed.
-
-It is undefined behavior to execute a ``cleanupret`` if, after the most recent
-execution of its ``cleanuppad``, any other ``cleanuppad`` or ``catchpad`` has
-been executed but has not had a corresponding
-``cleanupret``/``catchret``/``cleanupendpad``/``catchendpad`` executed.
+The unwind destination ``continue``, if present, must be an EH pad
+whose parent is either ``none`` or an ancestor of the ``cleanuppad``
+being returned from.  This constitutes an exceptional exit from all
+ancestors of the completed ``cleanuppad``, up to but not including
+the parent of ``continue``.
+See :ref:`cleanuppad <i_cleanuppad>` for more details.
 
 Example:
 """"""""
 
 .. code-block:: llvm
 
-      cleanupret %cleanup unwind to caller
-      cleanupret %cleanup unwind label %continue
+      cleanupret from %cleanup unwind to caller
+      cleanupret from %cleanup unwind label %continue
 
 .. _i_terminatepad:
 
@@ -5717,8 +5599,8 @@ Syntax:
 
 ::
 
-      terminatepad [<args>*] unwind label <exception label>
-      terminatepad [<args>*] unwind to caller
+      terminatepad within <token> [<args>*] unwind label <exception label>
+      terminatepad within <token> [<args>*] unwind to caller
 
 Overview:
 """""""""
@@ -5752,16 +5634,8 @@ the program is terminated via personalit
 the first argument to ``terminatepad`` specifies what function the
 personality should defer to in order to terminate the program.
 
-The ``terminatepad`` instruction has several restrictions:
-
--  A terminate block is a basic block which is the unwind destination of
-   an exceptional instruction.
--  A terminate block must have a '``terminatepad``' instruction as its
-   first non-PHI instruction.
--  There can be only one '``terminatepad``' instruction within the
-   terminate block.
--  A basic block that is not a terminate block may not include a
-   '``terminatepad``' instruction.
+The ``terminatepad`` instruction is both a terminator and a "pad" instruction,
+meaning that is always the only non-phi instruction in the basic block.
 
 Example:
 """"""""
@@ -5769,7 +5643,7 @@ Example:
 .. code-block:: llvm
 
       ;; A terminate block which only permits integers.
-      terminatepad [i8** @_ZTIi] unwind label %continue
+      terminatepad within none [i8** @_ZTIi] unwind label %continue
 
 .. _i_unreachable:
 
@@ -8762,7 +8636,7 @@ Syntax:
 
 ::
 
-      <resultval> = cleanuppad [<args>*]
+      <resultval> = cleanuppad within <parent> [<args>*]
 
 Overview:
 """""""""
@@ -8775,8 +8649,10 @@ The ``args`` correspond to whatever addi
 information the :ref:`personality function <personalityfn>` requires to
 execute the cleanup.
 The ``resultval`` has the type :ref:`token <t_token>` and is used to
-match the ``cleanuppad`` to corresponding :ref:`cleanuprets <i_cleanupret>`
-and :ref:`cleanupendpads <i_cleanupendpad>`.
+match the ``cleanuppad`` to corresponding :ref:`cleanuprets <i_cleanupret>`.
+The ``parent`` argument is the token of the funclet that contains the
+``cleanuppad`` instruction. If the ``cleanuppad`` is not inside a funclet,
+this operand may be the token ``none``.
 
 Arguments:
 """"""""""
@@ -8803,21 +8679,29 @@ The ``cleanuppad`` instruction has sever
    cleanup block.
 -  A basic block that is not a cleanup block may not include a
    '``cleanuppad``' instruction.
--  All '``cleanupret``'s and '``cleanupendpad``'s which consume a ``cleanuppad``
-   must have the same exceptional successor.
--  It is undefined behavior for control to transfer from a ``cleanuppad`` to a
-   ``ret`` without first executing a ``cleanupret`` or ``cleanupendpad`` that
-   consumes the ``cleanuppad``.
--  It is undefined behavior for control to transfer from a ``cleanuppad`` to
-   itself without first executing a ``cleanupret`` or ``cleanupendpad`` that
-   consumes the ``cleanuppad``.
+
+Executing a ``cleanuppad`` instruction constitutes "entering" that pad.
+The pad may then be "exited" in one of three ways:
+1)  explicitly via a ``cleanupret`` that consumes it.  Executing such a ``cleanupret``
+    is undefined behavior if any descendant pads have been entered but not yet
+    exited.
+2)  implicitly via a call (which unwinds all the way to the current function's caller),
+    or via a ``catchswitch``, ``cleanupret``, or ``terminatepad`` that unwinds to caller.
+3)  implicitly via an unwind edge whose destination EH pad isn't a descendant of
+    the ``cleanuppad``.  When the ``cleanuppad`` is exited in this manner, it is
+    undefined behavior if the destination EH pad has a parent which is not an
+    ancestor of the ``cleanuppad`` being exited.
+
+It is undefined behavior for the ``cleanuppad`` to exit via an unwind edge which
+does not transitively unwind to the same destination as a constituent
+``cleanupret``.
 
 Example:
 """"""""
 
 .. code-block:: llvm
 
-      %tok = cleanuppad []
+      %tok = cleanuppad within %cs []
 
 .. _intrinsics:
 

Modified: llvm/trunk/include/llvm-c/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm-c/Core.h (original)
+++ llvm/trunk/include/llvm-c/Core.h Fri Dec 11 23:38:55 2015
@@ -254,8 +254,7 @@ typedef enum {
   LLVMCatchPad       = 63,
   LLVMTerminatePad   = 64,
   LLVMCleanupPad     = 65,
-  LLVMCatchEndPad    = 66,
-  LLVMCleanupEndPad  = 67
+  LLVMCatchSwitch    = 66
 } LLVMOpcode;
 
 typedef enum {
@@ -1211,7 +1210,6 @@ LLVMTypeRef LLVMX86MMXType(void);
       macro(InsertElementInst)              \
       macro(InsertValueInst)                \
       macro(LandingPadInst)                 \
-      macro(CleanupPadInst)                 \
       macro(PHINode)                        \
       macro(SelectInst)                     \
       macro(ShuffleVectorInst)              \
@@ -1226,10 +1224,10 @@ LLVMTypeRef LLVMX86MMXType(void);
         macro(ResumeInst)                   \
         macro(CleanupReturnInst)            \
         macro(CatchReturnInst)              \
-        macro(CatchPadInst)                 \
         macro(TerminatePadInst)             \
-        macro(CatchEndPadInst)              \
-        macro(CleanupEndPadInst)            \
+      macro(FuncletPadInst)                 \
+        macro(CatchPadInst)                 \
+        macro(CleanupPadInst)               \
       macro(UnaryInstruction)               \
         macro(AllocaInst)                   \
         macro(CastInst)                     \

Modified: llvm/trunk/include/llvm/Analysis/EHPersonalities.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/EHPersonalities.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/EHPersonalities.h (original)
+++ llvm/trunk/include/llvm/Analysis/EHPersonalities.h Fri Dec 11 23:38:55 2015
@@ -10,9 +10,12 @@
 #ifndef LLVM_ANALYSIS_EHPERSONALITIES_H
 #define LLVM_ANALYSIS_EHPERSONALITIES_H
 
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/ErrorHandling.h"
 
 namespace llvm {
+class BasicBlock;
 class Function;
 class Value;
 
@@ -78,6 +81,14 @@ inline bool isNoOpWithoutInvoke(EHPerson
 
 bool canSimplifyInvokeNoUnwind(const Function *F);
 
+typedef TinyPtrVector<BasicBlock *> ColorVector;
+
+/// \brief If an EH funclet personality is in use (see isFuncletEHPersonality),
+/// this will recompute which blocks are in which funclet. It is possible that
+/// some blocks are in multiple funclets. Consider this analysis to be
+/// expensive.
+DenseMap<BasicBlock *, ColorVector> colorEHFunclets(Function &F);
+
 } // end namespace llvm
 
 #endif

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Fri Dec 11 23:38:55 2015
@@ -423,9 +423,8 @@ enum { BITCODE_CURRENT_EPOCH = 0 };
     FUNC_CODE_INST_CATCHPAD  = 50, // CATCHPAD: [bb#,bb#,num,args...]
     FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...]
     FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...]
-    FUNC_CODE_INST_CATCHENDPAD = 53, // CATCHENDPAD: [] or [bb#]
-    FUNC_CODE_INST_CLEANUPENDPAD = 54, // CLEANUPENDPAD: [val] or [val,bb#]
-
+    FUNC_CODE_INST_CATCHSWITCH = 53, // CATCHSWITCH: [num,args...] or [num,args...,bb]
+    // 54 is unused.
     FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...]
   };
 

Modified: llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h Fri Dec 11 23:38:55 2015
@@ -89,9 +89,11 @@ struct ClrEHUnwindMapEntry {
 
 struct WinEHFuncInfo {
   DenseMap<const Instruction *, int> EHPadStateMap;
+  DenseMap<const FuncletPadInst *, int> FuncletBaseStateMap;
+  DenseMap<const InvokeInst *, int> InvokeStateMap;
   DenseMap<const CatchReturnInst *, const BasicBlock *>
       CatchRetSuccessorColorMap;
-  DenseMap<MCSymbol *, std::pair<int, MCSymbol *>> InvokeToStateMap;
+  DenseMap<MCSymbol *, std::pair<int, MCSymbol *>> LabelToStateMap;
   SmallVector<CxxUnwindMapEntry, 4> CxxUnwindMap;
   SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
   SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap;
@@ -101,7 +103,7 @@ struct WinEHFuncInfo {
 
   int getLastStateNumber() const { return CxxUnwindMap.size() - 1; }
 
-  void addIPToStateRange(const BasicBlock *PadBB, MCSymbol *InvokeBegin,
+  void addIPToStateRange(const InvokeInst *II, MCSymbol *InvokeBegin,
                          MCSymbol *InvokeEnd);
 
   int EHRegNodeFrameIndex = INT_MAX;

Modified: llvm/trunk/include/llvm/IR/IRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IRBuilder.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IRBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/IRBuilder.h Fri Dec 11 23:38:55 2015
@@ -708,29 +708,29 @@ public:
     return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB));
   }
 
-  CleanupEndPadInst *CreateCleanupEndPad(CleanupPadInst *CleanupPad,
-                                         BasicBlock *UnwindBB = nullptr) {
-    return Insert(CleanupEndPadInst::Create(CleanupPad, UnwindBB));
+  CatchSwitchInst *CreateCatchSwitch(Value *ParentPad, BasicBlock *UnwindBB,
+                                     unsigned NumHandlers,
+                                     const Twine &Name = "") {
+    return Insert(CatchSwitchInst::Create(ParentPad, UnwindBB, NumHandlers),
+                  Name);
   }
 
-  CatchPadInst *CreateCatchPad(BasicBlock *NormalDest, BasicBlock *UnwindDest,
-                               ArrayRef<Value *> Args, const Twine &Name = "") {
-    return Insert(CatchPadInst::Create(NormalDest, UnwindDest, Args), Name);
+  CatchPadInst *CreateCatchPad(Value *ParentPad, ArrayRef<Value *> Args,
+                               const Twine &Name = "") {
+    return Insert(CatchPadInst::Create(ParentPad, Args), Name);
   }
 
-  CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) {
-    return Insert(CatchEndPadInst::Create(Context, UnwindBB));
-  }
-
-  TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr,
-                                       ArrayRef<Value *> Args = {},
+  TerminatePadInst *CreateTerminatePad(Value *ParentPad,
+                                       BasicBlock *UnwindBB = nullptr,
+                                       ArrayRef<Value *> Args = None,
                                        const Twine &Name = "") {
-    return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name);
+    return Insert(TerminatePadInst::Create(ParentPad, UnwindBB, Args), Name);
   }
 
-  CleanupPadInst *CreateCleanupPad(ArrayRef<Value *> Args,
+  CleanupPadInst *CreateCleanupPad(Value *ParentPad,
+                                   ArrayRef<Value *> Args = None,
                                    const Twine &Name = "") {
-    return Insert(CleanupPadInst::Create(Context, Args), Name);
+    return Insert(CleanupPadInst::Create(ParentPad, Args), Name);
   }
 
   CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) {

Modified: llvm/trunk/include/llvm/IR/InstVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstVisitor.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InstVisitor.h (original)
+++ llvm/trunk/include/llvm/IR/InstVisitor.h Fri Dec 11 23:38:55 2015
@@ -170,10 +170,8 @@ public:
   RetTy visitResumeInst(ResumeInst &I)            { DELEGATE(TerminatorInst);}
   RetTy visitUnreachableInst(UnreachableInst &I)  { DELEGATE(TerminatorInst);}
   RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);}
-  RetTy visitCleanupEndPadInst(CleanupEndPadInst &I) { DELEGATE(TerminatorInst); }
   RetTy visitCatchReturnInst(CatchReturnInst &I)  { DELEGATE(TerminatorInst); }
-  RetTy visitCatchPadInst(CatchPadInst &I)    { DELEGATE(TerminatorInst);}
-  RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(TerminatorInst); }
+  RetTy visitCatchSwitchInst(CatchSwitchInst &I)  { DELEGATE(TerminatorInst);}
   RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);}
   RetTy visitICmpInst(ICmpInst &I)                { DELEGATE(CmpInst);}
   RetTy visitFCmpInst(FCmpInst &I)                { DELEGATE(CmpInst);}
@@ -206,7 +204,9 @@ public:
   RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);}
   RetTy visitInsertValueInst(InsertValueInst &I)  { DELEGATE(Instruction); }
   RetTy visitLandingPadInst(LandingPadInst &I)    { DELEGATE(Instruction); }
-  RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(Instruction); }
+  RetTy visitFuncletPadInst(FuncletPadInst &I) { DELEGATE(Instruction); }
+  RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(FuncletPadInst); }
+  RetTy visitCatchPadInst(CatchPadInst &I)     { DELEGATE(FuncletPadInst); }
 
   // Handle the special instrinsic instruction classes.
   RetTy visitDbgDeclareInst(DbgDeclareInst &I)    { DELEGATE(DbgInfoIntrinsic);}

Modified: llvm/trunk/include/llvm/IR/InstrTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/InstrTypes.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/InstrTypes.h (original)
+++ llvm/trunk/include/llvm/IR/InstrTypes.h Fri Dec 11 23:38:55 2015
@@ -82,10 +82,8 @@ public:
   // \brief Returns true if this terminator relates to exception handling.
   bool isExceptional() const {
     switch (getOpcode()) {
-    case Instruction::CatchPad:
-    case Instruction::CatchEndPad:
+    case Instruction::CatchSwitch:
     case Instruction::CatchRet:
-    case Instruction::CleanupEndPad:
     case Instruction::CleanupRet:
     case Instruction::Invoke:
     case Instruction::Resume:
@@ -1112,6 +1110,75 @@ struct OperandTraits<CmpInst> : public F
 
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value)
 
+//===----------------------------------------------------------------------===//
+//                           FuncletPadInst Class
+//===----------------------------------------------------------------------===//
+class FuncletPadInst : public Instruction {
+private:
+  void init(Value *ParentPad, ArrayRef<Value *> Args, const Twine &NameStr);
+
+  FuncletPadInst(const FuncletPadInst &CPI);
+
+  explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+                          ArrayRef<Value *> Args, unsigned Values,
+                          const Twine &NameStr, Instruction *InsertBefore);
+  explicit FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+                          ArrayRef<Value *> Args, unsigned Values,
+                          const Twine &NameStr, BasicBlock *InsertAtEnd);
+
+protected:
+  // Note: Instruction needs to be a friend here to call cloneImpl.
+  friend class Instruction;
+  friend class CatchPadInst;
+  friend class CleanupPadInst;
+  FuncletPadInst *cloneImpl() const;
+
+public:
+  /// Provide fast operand accessors
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+  /// getNumArgOperands - Return the number of funcletpad arguments.
+  ///
+  unsigned getNumArgOperands() const { return getNumOperands() - 1; }
+
+  /// Convenience accessors
+
+  /// \brief Return the outer EH-pad this funclet is nested within.
+  ///
+  /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst
+  /// is a CatchPadInst.
+  Value *getParentPad() const { return Op<-1>(); }
+  void setParentPad(Value *ParentPad) {
+    assert(ParentPad);
+    Op<-1>() = ParentPad;
+  }
+
+  /// getArgOperand/setArgOperand - Return/set the i-th funcletpad argument.
+  ///
+  Value *getArgOperand(unsigned i) const { return getOperand(i); }
+  void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
+
+  /// arg_operands - iteration adapter for range-for loops.
+  op_range arg_operands() { return op_range(op_begin(), op_end() - 1); }
+
+  /// arg_operands - iteration adapter for range-for loops.
+  const_op_range arg_operands() const {
+    return const_op_range(op_begin(), op_end() - 1);
+  }
+
+  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Instruction *I) { return I->isFuncletPad(); }
+  static inline bool classof(const Value *V) {
+    return isa<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
+
+template <>
+struct OperandTraits<FuncletPadInst>
+    : public VariadicOperandTraits<FuncletPadInst, /*MINARITY=*/1> {};
+
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value)
+
 /// \brief A lightweight accessor for an operand bundle meant to be passed
 /// around by value.
 struct OperandBundleUse {

Modified: llvm/trunk/include/llvm/IR/Instruction.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instruction.def?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instruction.def (original)
+++ llvm/trunk/include/llvm/IR/Instruction.def Fri Dec 11 23:38:55 2015
@@ -74,6 +74,20 @@
 #define LAST_CAST_INST(num)
 #endif
 
+#ifndef FIRST_FUNCLETPAD_INST
+#define FIRST_FUNCLETPAD_INST(num)
+#endif
+#ifndef HANDLE_FUNCLETPAD_INST
+#ifndef HANDLE_INST
+#define HANDLE_FUNCLETPAD_INST(num, opcode, Class)
+#else
+#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
+#endif
+#endif
+#ifndef LAST_FUNCLETPAD_INST
+#define LAST_FUNCLETPAD_INST(num)
+#endif
+
 #ifndef FIRST_OTHER_INST
 #define FIRST_OTHER_INST(num)
 #endif
@@ -102,65 +116,68 @@ HANDLE_TERM_INST  ( 6, Resume        , R
 HANDLE_TERM_INST  ( 7, Unreachable   , UnreachableInst)
 HANDLE_TERM_INST  ( 8, CleanupRet    , CleanupReturnInst)
 HANDLE_TERM_INST  ( 9, CatchRet      , CatchReturnInst)
-HANDLE_TERM_INST  (10, CatchPad      , CatchPadInst)
+HANDLE_TERM_INST  (10, CatchSwitch   , CatchSwitchInst)
 HANDLE_TERM_INST  (11, TerminatePad  , TerminatePadInst)
-HANDLE_TERM_INST  (12, CatchEndPad   , CatchEndPadInst)
-HANDLE_TERM_INST  (13, CleanupEndPad , CleanupEndPadInst)
-  LAST_TERM_INST  (13)
+  LAST_TERM_INST  (11)
 
 // Standard binary operators...
- FIRST_BINARY_INST(14)
-HANDLE_BINARY_INST(14, Add  , BinaryOperator)
-HANDLE_BINARY_INST(15, FAdd , BinaryOperator)
-HANDLE_BINARY_INST(16, Sub  , BinaryOperator)
-HANDLE_BINARY_INST(17, FSub , BinaryOperator)
-HANDLE_BINARY_INST(18, Mul  , BinaryOperator)
-HANDLE_BINARY_INST(19, FMul , BinaryOperator)
-HANDLE_BINARY_INST(20, UDiv , BinaryOperator)
-HANDLE_BINARY_INST(21, SDiv , BinaryOperator)
-HANDLE_BINARY_INST(22, FDiv , BinaryOperator)
-HANDLE_BINARY_INST(23, URem , BinaryOperator)
-HANDLE_BINARY_INST(24, SRem , BinaryOperator)
-HANDLE_BINARY_INST(25, FRem , BinaryOperator)
+ FIRST_BINARY_INST(12)
+HANDLE_BINARY_INST(12, Add  , BinaryOperator)
+HANDLE_BINARY_INST(13, FAdd , BinaryOperator)
+HANDLE_BINARY_INST(14, Sub  , BinaryOperator)
+HANDLE_BINARY_INST(15, FSub , BinaryOperator)
+HANDLE_BINARY_INST(16, Mul  , BinaryOperator)
+HANDLE_BINARY_INST(17, FMul , BinaryOperator)
+HANDLE_BINARY_INST(18, UDiv , BinaryOperator)
+HANDLE_BINARY_INST(19, SDiv , BinaryOperator)
+HANDLE_BINARY_INST(20, FDiv , BinaryOperator)
+HANDLE_BINARY_INST(21, URem , BinaryOperator)
+HANDLE_BINARY_INST(22, SRem , BinaryOperator)
+HANDLE_BINARY_INST(23, FRem , BinaryOperator)
 
 // Logical operators (integer operands)
-HANDLE_BINARY_INST(26, Shl  , BinaryOperator) // Shift left  (logical)
-HANDLE_BINARY_INST(27, LShr , BinaryOperator) // Shift right (logical)
-HANDLE_BINARY_INST(28, AShr , BinaryOperator) // Shift right (arithmetic)
-HANDLE_BINARY_INST(29, And  , BinaryOperator)
-HANDLE_BINARY_INST(30, Or   , BinaryOperator)
-HANDLE_BINARY_INST(31, Xor  , BinaryOperator)
-  LAST_BINARY_INST(31)
+HANDLE_BINARY_INST(24, Shl  , BinaryOperator) // Shift left  (logical)
+HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical)
+HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic)
+HANDLE_BINARY_INST(27, And  , BinaryOperator)
+HANDLE_BINARY_INST(28, Or   , BinaryOperator)
+HANDLE_BINARY_INST(29, Xor  , BinaryOperator)
+  LAST_BINARY_INST(29)
 
 // Memory operators...
- FIRST_MEMORY_INST(32)
-HANDLE_MEMORY_INST(32, Alloca, AllocaInst)  // Stack management
-HANDLE_MEMORY_INST(33, Load  , LoadInst  )  // Memory manipulation instrs
-HANDLE_MEMORY_INST(34, Store , StoreInst )
-HANDLE_MEMORY_INST(35, GetElementPtr, GetElementPtrInst)
-HANDLE_MEMORY_INST(36, Fence , FenceInst )
-HANDLE_MEMORY_INST(37, AtomicCmpXchg , AtomicCmpXchgInst )
-HANDLE_MEMORY_INST(38, AtomicRMW , AtomicRMWInst )
-  LAST_MEMORY_INST(38)
+ FIRST_MEMORY_INST(30)
+HANDLE_MEMORY_INST(30, Alloca, AllocaInst)  // Stack management
+HANDLE_MEMORY_INST(31, Load  , LoadInst  )  // Memory manipulation instrs
+HANDLE_MEMORY_INST(32, Store , StoreInst )
+HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst)
+HANDLE_MEMORY_INST(34, Fence , FenceInst )
+HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst )
+HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst )
+  LAST_MEMORY_INST(36)
 
 // Cast operators ...
 // NOTE: The order matters here because CastInst::isEliminableCastPair
 // NOTE: (see Instructions.cpp) encodes a table based on this ordering.
- FIRST_CAST_INST(39)
-HANDLE_CAST_INST(39, Trunc   , TruncInst   )  // Truncate integers
-HANDLE_CAST_INST(40, ZExt    , ZExtInst    )  // Zero extend integers
-HANDLE_CAST_INST(41, SExt    , SExtInst    )  // Sign extend integers
-HANDLE_CAST_INST(42, FPToUI  , FPToUIInst  )  // floating point -> UInt
-HANDLE_CAST_INST(43, FPToSI  , FPToSIInst  )  // floating point -> SInt
-HANDLE_CAST_INST(44, UIToFP  , UIToFPInst  )  // UInt -> floating point
-HANDLE_CAST_INST(45, SIToFP  , SIToFPInst  )  // SInt -> floating point
-HANDLE_CAST_INST(46, FPTrunc , FPTruncInst )  // Truncate floating point
-HANDLE_CAST_INST(47, FPExt   , FPExtInst   )  // Extend floating point
-HANDLE_CAST_INST(48, PtrToInt, PtrToIntInst)  // Pointer -> Integer
-HANDLE_CAST_INST(49, IntToPtr, IntToPtrInst)  // Integer -> Pointer
-HANDLE_CAST_INST(50, BitCast , BitCastInst )  // Type cast
-HANDLE_CAST_INST(51, AddrSpaceCast, AddrSpaceCastInst)  // addrspace cast
-  LAST_CAST_INST(51)
+ FIRST_CAST_INST(37)
+HANDLE_CAST_INST(37, Trunc   , TruncInst   )  // Truncate integers
+HANDLE_CAST_INST(38, ZExt    , ZExtInst    )  // Zero extend integers
+HANDLE_CAST_INST(39, SExt    , SExtInst    )  // Sign extend integers
+HANDLE_CAST_INST(40, FPToUI  , FPToUIInst  )  // floating point -> UInt
+HANDLE_CAST_INST(41, FPToSI  , FPToSIInst  )  // floating point -> SInt
+HANDLE_CAST_INST(42, UIToFP  , UIToFPInst  )  // UInt -> floating point
+HANDLE_CAST_INST(43, SIToFP  , SIToFPInst  )  // SInt -> floating point
+HANDLE_CAST_INST(44, FPTrunc , FPTruncInst )  // Truncate floating point
+HANDLE_CAST_INST(45, FPExt   , FPExtInst   )  // Extend floating point
+HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst)  // Pointer -> Integer
+HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst)  // Integer -> Pointer
+HANDLE_CAST_INST(48, BitCast , BitCastInst )  // Type cast
+HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst)  // addrspace cast
+  LAST_CAST_INST(49)
+
+ FIRST_FUNCLETPAD_INST(50)
+HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst)
+HANDLE_FUNCLETPAD_INST(51, CatchPad  , CatchPadInst)
+  LAST_FUNCLETPAD_INST(51)
 
 // Other operators...
  FIRST_OTHER_INST(52)
@@ -178,8 +195,7 @@ HANDLE_OTHER_INST(62, ShuffleVector, Shu
 HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate
 HANDLE_OTHER_INST(64, InsertValue, InsertValueInst)  // insert into aggregate
 HANDLE_OTHER_INST(65, LandingPad, LandingPadInst)  // Landing pad instruction.
-HANDLE_OTHER_INST(66, CleanupPad, CleanupPadInst)
-  LAST_OTHER_INST(66)
+  LAST_OTHER_INST(65)
 
 #undef  FIRST_TERM_INST
 #undef HANDLE_TERM_INST
@@ -197,6 +213,10 @@ HANDLE_OTHER_INST(66, CleanupPad, Cleanu
 #undef HANDLE_CAST_INST
 #undef   LAST_CAST_INST
 
+#undef  FIRST_FUNCLETPAD_INST
+#undef HANDLE_FUNCLETPAD_INST
+#undef   LAST_FUNCLETPAD_INST
+
 #undef  FIRST_OTHER_INST
 #undef HANDLE_OTHER_INST
 #undef   LAST_OTHER_INST

Modified: llvm/trunk/include/llvm/IR/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instruction.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instruction.h (original)
+++ llvm/trunk/include/llvm/IR/Instruction.h Fri Dec 11 23:38:55 2015
@@ -109,6 +109,7 @@ public:
   bool isBinaryOp() const { return isBinaryOp(getOpcode()); }
   bool isShift() { return isShift(getOpcode()); }
   bool isCast() const { return isCast(getOpcode()); }
+  bool isFuncletPad() const { return isFuncletPad(getOpcode()); }
 
   static const char* getOpcodeName(unsigned OpCode);
 
@@ -141,6 +142,11 @@ public:
     return OpCode >= CastOpsBegin && OpCode < CastOpsEnd;
   }
 
+  /// @brief Determine if the OpCode is one of the FuncletPadInst instructions.
+  static inline bool isFuncletPad(unsigned OpCode) {
+    return OpCode >= FuncletPadOpsBegin && OpCode < FuncletPadOpsEnd;
+  }
+
   //===--------------------------------------------------------------------===//
   // Metadata manipulation.
   //===--------------------------------------------------------------------===//
@@ -386,10 +392,9 @@ public:
   /// \brief Return true if the instruction is a variety of EH-block.
   bool isEHPad() const {
     switch (getOpcode()) {
+    case Instruction::CatchSwitch:
     case Instruction::CatchPad:
-    case Instruction::CatchEndPad:
     case Instruction::CleanupPad:
-    case Instruction::CleanupEndPad:
     case Instruction::LandingPad:
     case Instruction::TerminatePad:
       return true;
@@ -478,6 +483,13 @@ public:
 #include "llvm/IR/Instruction.def"
   };
 
+  enum FuncletPadOps {
+#define  FIRST_FUNCLETPAD_INST(N)             FuncletPadOpsBegin = N,
+#define HANDLE_FUNCLETPAD_INST(N, OPC, CLASS) OPC = N,
+#define   LAST_FUNCLETPAD_INST(N)             FuncletPadOpsEnd = N+1
+#include "llvm/IR/Instruction.def"
+  };
+
   enum OtherOps {
 #define  FIRST_OTHER_INST(N)             OtherOpsBegin = N,
 #define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N,

Modified: llvm/trunk/include/llvm/IR/Instructions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Instructions.h (original)
+++ llvm/trunk/include/llvm/IR/Instructions.h Fri Dec 11 23:38:55 2015
@@ -18,6 +18,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/CallingConv.h"
@@ -3819,181 +3820,176 @@ struct OperandTraits<ResumeInst> :
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
 
 //===----------------------------------------------------------------------===//
-//                               CatchEndPadInst Class
+//                         CatchSwitchInst Class
 //===----------------------------------------------------------------------===//
+class CatchSwitchInst : public TerminatorInst {
+  void *operator new(size_t, unsigned) = delete;
+  /// ReservedSpace - The number of operands actually allocated.  NumOperands is
+  /// the number actually in use.
+  unsigned ReservedSpace;
+  // Operand[0] = Outer scope
+  // Operand[1] = Unwind block destination
+  // Operand[n] = BasicBlock to go to on match
+  CatchSwitchInst(const CatchSwitchInst &CSI);
+  void init(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReserved);
+  void growOperands(unsigned Size);
+  // allocate space for exactly zero operands
+  void *operator new(size_t s) { return User::operator new(s); }
+  /// CatchSwitchInst ctor - Create a new switch instruction, specifying a
+  /// default destination.  The number of additional handlers can be specified
+  /// here to make memory allocation more efficient.
+  /// This constructor can also autoinsert before another instruction.
+  CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+                  unsigned NumHandlers, const Twine &NameStr,
+                  Instruction *InsertBefore);
 
-class CatchEndPadInst : public TerminatorInst {
-private:
-  CatchEndPadInst(const CatchEndPadInst &RI);
-
-  void init(BasicBlock *UnwindBB);
-  CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
-                  Instruction *InsertBefore = nullptr);
-  CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values,
+  /// CatchSwitchInst ctor - Create a new switch instruction, specifying a
+  /// default destination.  The number of additional handlers can be specified
+  /// here to make memory allocation more efficient.
+  /// This constructor also autoinserts at the end of the specified BasicBlock.
+  CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+                  unsigned NumHandlers, const Twine &NameStr,
                   BasicBlock *InsertAtEnd);
 
 protected:
   // Note: Instruction needs to be a friend here to call cloneImpl.
   friend class Instruction;
-  CatchEndPadInst *cloneImpl() const;
+  CatchSwitchInst *cloneImpl() const;
 
 public:
-  static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB = nullptr,
+  static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
+                                 unsigned NumHandlers,
+                                 const Twine &NameStr = "",
                                  Instruction *InsertBefore = nullptr) {
-    unsigned Values = UnwindBB ? 1 : 0;
-    return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore);
+    return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr,
+                               InsertBefore);
   }
-  static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB,
+  static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
+                                 unsigned NumHandlers, const Twine &NameStr,
                                  BasicBlock *InsertAtEnd) {
-    unsigned Values = UnwindBB ? 1 : 0;
-    return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd);
+    return new CatchSwitchInst(ParentPad, UnwindDest, NumHandlers, NameStr,
+                               InsertAtEnd);
   }
 
   /// Provide fast operand accessors
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
+  // Accessor Methods for CatchSwitch stmt
+  Value *getParentPad() const { return getOperand(0); }
+  void setParentPad(Value *ParentPad) { setOperand(0, ParentPad); }
+
+  // Accessor Methods for CatchSwitch stmt
   bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
   bool unwindsToCaller() const { return !hasUnwindDest(); }
-
-  /// Convenience accessor. Returns null if there is no return value.
-  unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
   BasicBlock *getUnwindDest() const {
-    return hasUnwindDest() ? cast<BasicBlock>(Op<-1>()) : nullptr;
+    if (hasUnwindDest())
+      return cast<BasicBlock>(getOperand(1));
+    return nullptr;
   }
-  void setUnwindDest(BasicBlock *NewDest) {
-    assert(NewDest);
-    Op<-1>() = NewDest;
+  void setUnwindDest(BasicBlock *UnwindDest) {
+    assert(UnwindDest);
+    assert(hasUnwindDest());
+    setOperand(1, UnwindDest);
   }
 
-  // Methods for support type inquiry through isa, cast, and dyn_cast:
-  static inline bool classof(const Instruction *I) {
-    return (I->getOpcode() == Instruction::CatchEndPad);
-  }
-  static inline bool classof(const Value *V) {
-    return isa<Instruction>(V) && classof(cast<Instruction>(V));
+  /// getNumHandlers - return the number of 'handlers' in this catchswitch
+  /// instruction, except the default handler
+  unsigned getNumHandlers() const {
+    if (hasUnwindDest())
+      return getNumOperands() - 2;
+    return getNumOperands() - 1;
   }
 
 private:
-  BasicBlock *getSuccessorV(unsigned Idx) const override;
-  unsigned getNumSuccessorsV() const override;
-  void setSuccessorV(unsigned Idx, BasicBlock *B) override;
-
-  // Shadow Instruction::setInstructionSubclassData with a private forwarding
-  // method so that subclasses cannot accidentally use it.
-  void setInstructionSubclassData(unsigned short D) {
-    Instruction::setInstructionSubclassData(D);
+  static BasicBlock *handler_helper(Value *V) { return cast<BasicBlock>(V); }
+  static const BasicBlock *handler_helper(const Value *V) {
+    return cast<BasicBlock>(V);
   }
-};
-
-template <>
-struct OperandTraits<CatchEndPadInst>
-    : public VariadicOperandTraits<CatchEndPadInst> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value)
-
-//===----------------------------------------------------------------------===//
-//                           CatchPadInst Class
-//===----------------------------------------------------------------------===//
-
-class CatchPadInst : public TerminatorInst {
-private:
-  void init(BasicBlock *IfNormal, BasicBlock *IfException,
-            ArrayRef<Value *> Args, const Twine &NameStr);
-
-  CatchPadInst(const CatchPadInst &CPI);
-
-  explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
-                        ArrayRef<Value *> Args, unsigned Values,
-                        const Twine &NameStr, Instruction *InsertBefore);
-  explicit CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
-                        ArrayRef<Value *> Args, unsigned Values,
-                        const Twine &NameStr, BasicBlock *InsertAtEnd);
-
-protected:
-  // Note: Instruction needs to be a friend here to call cloneImpl.
-  friend class Instruction;
-  CatchPadInst *cloneImpl() const;
 
 public:
-  static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
-                              ArrayRef<Value *> Args, const Twine &NameStr = "",
-                              Instruction *InsertBefore = nullptr) {
-    unsigned Values = unsigned(Args.size()) + 2;
-    return new (Values) CatchPadInst(IfNormal, IfException, Args, Values,
-                                     NameStr, InsertBefore);
-  }
-  static CatchPadInst *Create(BasicBlock *IfNormal, BasicBlock *IfException,
-                              ArrayRef<Value *> Args, const Twine &NameStr,
-                              BasicBlock *InsertAtEnd) {
-    unsigned Values = unsigned(Args.size()) + 2;
-    return new (Values)
-        CatchPadInst(IfNormal, IfException, Args, Values, NameStr, InsertAtEnd);
-  }
+  typedef std::pointer_to_unary_function<Value *, BasicBlock *> DerefFnTy;
+  typedef mapped_iterator<op_iterator, DerefFnTy> handler_iterator;
+  typedef iterator_range<handler_iterator> handler_range;
 
-  /// Provide fast operand accessors
-  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
-  /// getNumArgOperands - Return the number of catchpad arguments.
-  ///
-  unsigned getNumArgOperands() const { return getNumOperands() - 2; }
-
-  /// getArgOperand/setArgOperand - Return/set the i-th catchpad argument.
-  ///
-  Value *getArgOperand(unsigned i) const { return getOperand(i); }
-  void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
-
-  /// arg_operands - iteration adapter for range-for loops.
-  iterator_range<op_iterator> arg_operands() {
-    return make_range(op_begin(), op_end() - 2);
+  typedef std::pointer_to_unary_function<const Value *, const BasicBlock *>
+      ConstDerefFnTy;
+  typedef mapped_iterator<const_op_iterator, ConstDerefFnTy> const_handler_iterator;
+  typedef iterator_range<const_handler_iterator> const_handler_range;
+
+  /// Returns an iterator that points to the first handler in CatchSwitchInst.
+  handler_iterator handler_begin() {
+    op_iterator It = op_begin() + 1;
+    if (hasUnwindDest())
+      ++It;
+    return handler_iterator(It, DerefFnTy(handler_helper));
   }
-
-  /// arg_operands - iteration adapter for range-for loops.
-  iterator_range<const_op_iterator> arg_operands() const {
-    return make_range(op_begin(), op_end() - 2);
+  /// Returns an iterator that points to the first handler in the
+  /// CatchSwitchInst.
+  const_handler_iterator handler_begin() const {
+    const_op_iterator It = op_begin() + 1;
+    if (hasUnwindDest())
+      ++It;
+    return const_handler_iterator(It, ConstDerefFnTy(handler_helper));
   }
 
-  /// \brief Wrappers for getting the \c Use of a catchpad argument.
-  const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); }
-  Use &getArgOperandUse(unsigned i) { return getOperandUse(i); }
-
-  // get*Dest - Return the destination basic blocks...
-  BasicBlock *getNormalDest() const { return cast<BasicBlock>(Op<-2>()); }
-  BasicBlock *getUnwindDest() const { return cast<BasicBlock>(Op<-1>()); }
-  void setNormalDest(BasicBlock *B) { Op<-2>() = B; }
-  void setUnwindDest(BasicBlock *B) { Op<-1>() = B; }
+  /// Returns a read-only iterator that points one past the last
+  /// handler in the CatchSwitchInst.
+  handler_iterator handler_end() {
+    return handler_iterator(op_end(), DerefFnTy(handler_helper));
+  }
+  /// Returns an iterator that points one past the last handler in the
+  /// CatchSwitchInst.
+  const_handler_iterator handler_end() const {
+    return const_handler_iterator(op_end(), ConstDerefFnTy(handler_helper));
+  }
 
-  BasicBlock *getSuccessor(unsigned i) const {
-    assert(i < 2 && "Successor # out of range for catchpad!");
-    return i == 0 ? getNormalDest() : getUnwindDest();
+  /// handlers - iteration adapter for range-for loops.
+  handler_range handlers() {
+    return make_range(handler_begin(), handler_end());
   }
 
-  void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
-    assert(idx < 2 && "Successor # out of range for catchpad!");
-    *(&Op<-2>() + idx) = NewSucc;
+  /// handlers - iteration adapter for range-for loops.
+  const_handler_range handlers() const {
+    return make_range(handler_begin(), handler_end());
   }
 
-  unsigned getNumSuccessors() const { return 2; }
+  /// addHandler - Add an entry to the switch instruction...
+  /// Note:
+  /// This action invalidates handler_end(). Old handler_end() iterator will
+  /// point to the added handler.
+  void addHandler(BasicBlock *Dest);
+
+  unsigned getNumSuccessors() const { return getNumOperands() - 1; }
+  BasicBlock *getSuccessor(unsigned Idx) const {
+    assert(Idx < getNumSuccessors() &&
+           "Successor # out of range for catchswitch!");
+    return cast<BasicBlock>(getOperand(Idx + 1));
+  }
+  void setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
+    assert(Idx < getNumSuccessors() &&
+           "Successor # out of range for catchswitch!");
+    setOperand(Idx + 1, NewSucc);
+  }
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Instruction *I) {
-    return I->getOpcode() == Instruction::CatchPad;
+    return I->getOpcode() == Instruction::CatchSwitch;
   }
   static inline bool classof(const Value *V) {
     return isa<Instruction>(V) && classof(cast<Instruction>(V));
   }
 
 private:
-  BasicBlock *getSuccessorV(unsigned idx) const override;
+  BasicBlock *getSuccessorV(unsigned Idx) const override;
   unsigned getNumSuccessorsV() const override;
-  void setSuccessorV(unsigned idx, BasicBlock *B) override;
+  void setSuccessorV(unsigned Idx, BasicBlock *B) override;
 };
 
 template <>
-struct OperandTraits<CatchPadInst>
-    : public VariadicOperandTraits<CatchPadInst, /*MINARITY=*/2> {};
+struct OperandTraits<CatchSwitchInst> : public HungoffOperandTraits<2> {};
 
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value)
+DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchSwitchInst, Value)
 
 //===----------------------------------------------------------------------===//
 //                           TerminatePadInst Class
@@ -4001,14 +3997,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Cat
 
 class TerminatePadInst : public TerminatorInst {
 private:
-  void init(BasicBlock *BB, ArrayRef<Value *> Args);
+  void init(Value *ParentPad, BasicBlock *BB, ArrayRef<Value *> Args);
 
   TerminatePadInst(const TerminatePadInst &TPI);
 
-  explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+  explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
                             ArrayRef<Value *> Args, unsigned Values,
                             Instruction *InsertBefore);
-  explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+  explicit TerminatePadInst(Value *ParentPad, BasicBlock *BB,
                             ArrayRef<Value *> Args, unsigned Values,
                             BasicBlock *InsertAtEnd);
 
@@ -4018,21 +4014,23 @@ protected:
   TerminatePadInst *cloneImpl() const;
 
 public:
-  static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr,
+  static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB = nullptr,
                                   ArrayRef<Value *> Args = None,
                                   Instruction *InsertBefore = nullptr) {
-    unsigned Values = unsigned(Args.size());
+    unsigned Values = unsigned(Args.size()) + 1;
     if (BB)
       ++Values;
-    return new (Values) TerminatePadInst(C, BB, Args, Values, InsertBefore);
+    return new (Values)
+        TerminatePadInst(ParentPad, BB, Args, Values, InsertBefore);
   }
-  static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB,
+  static TerminatePadInst *Create(Value *ParentPad, BasicBlock *BB,
                                   ArrayRef<Value *> Args,
                                   BasicBlock *InsertAtEnd) {
-    unsigned Values = unsigned(Args.size());
+    unsigned Values = unsigned(Args.size()) + 1;
     if (BB)
       ++Values;
-    return new (Values) TerminatePadInst(C, BB, Args, Values, InsertAtEnd);
+    return new (Values)
+        TerminatePadInst(ParentPad, BB, Args, Values, InsertAtEnd);
   }
 
   /// Provide fast operand accessors
@@ -4046,8 +4044,15 @@ public:
   unsigned getNumArgOperands() const {
     unsigned NumOperands = getNumOperands();
     if (hasUnwindDest())
-      return NumOperands - 1;
-    return NumOperands;
+      return NumOperands - 2;
+    return NumOperands - 1;
+  }
+
+  /// Convenience accessors
+  Value *getParentPad() const { return Op<-1>(); }
+  void setParentPad(Value *ParentPad) {
+    assert(ParentPad);
+    Op<-1>() = ParentPad;
   }
 
   /// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument.
@@ -4055,26 +4060,29 @@ public:
   Value *getArgOperand(unsigned i) const { return getOperand(i); }
   void setArgOperand(unsigned i, Value *v) { setOperand(i, v); }
 
+  const_op_iterator arg_begin() const { return op_begin(); }
+  op_iterator arg_begin() { return op_begin(); }
+
   const_op_iterator arg_end() const {
     if (hasUnwindDest())
-      return op_end() - 1;
-    return op_end();
+      return op_end() - 2;
+    return op_end() - 1;
   }
 
   op_iterator arg_end() {
     if (hasUnwindDest())
-      return op_end() - 1;
-    return op_end();
+      return op_end() - 2;
+    return op_end() - 1;
   }
 
   /// arg_operands - iteration adapter for range-for loops.
   iterator_range<op_iterator> arg_operands() {
-    return make_range(op_begin(), arg_end());
+    return make_range(arg_begin(), arg_end());
   }
 
   /// arg_operands - iteration adapter for range-for loops.
   iterator_range<const_op_iterator> arg_operands() const {
-    return make_range(op_begin(), arg_end());
+    return make_range(arg_begin(), arg_end());
   }
 
   /// \brief Wrappers for getting the \c Use of a terminatepad argument.
@@ -4085,11 +4093,11 @@ public:
   BasicBlock *getUnwindDest() const {
     if (!hasUnwindDest())
       return nullptr;
-    return cast<BasicBlock>(Op<-1>());
+    return cast<BasicBlock>(Op<-2>());
   }
   void setUnwindDest(BasicBlock *B) {
     assert(B && hasUnwindDest());
-    Op<-1>() = B;
+    Op<-2>() = B;
   }
 
   unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
@@ -4121,40 +4129,37 @@ struct OperandTraits<TerminatePadInst>
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value)
 
 //===----------------------------------------------------------------------===//
-//                           CleanupPadInst Class
+//                               CleanupPadInst Class
 //===----------------------------------------------------------------------===//
-
-class CleanupPadInst : public Instruction {
+class CleanupPadInst : public FuncletPadInst {
 private:
-  void init(ArrayRef<Value *> Args, const Twine &NameStr);
-
-  CleanupPadInst(const CleanupPadInst &CPI);
-
-  explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
-                          const Twine &NameStr, Instruction *InsertBefore);
-  explicit CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
-                          const Twine &NameStr, BasicBlock *InsertAtEnd);
-
-protected:
-  // Note: Instruction needs to be a friend here to call cloneImpl.
-  friend class Instruction;
-  CleanupPadInst *cloneImpl() const;
+  explicit CleanupPadInst(Value *ParentPad, ArrayRef<Value *> Args,
+                          unsigned Values, const Twine &NameStr,
+                          Instruction *InsertBefore)
+      : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values,
+                       NameStr, InsertBefore) {}
+  explicit CleanupPadInst(Value *ParentPad, ArrayRef<Value *> Args,
+                          unsigned Values, const Twine &NameStr,
+                          BasicBlock *InsertAtEnd)
+      : FuncletPadInst(Instruction::CleanupPad, ParentPad, Args, Values,
+                       NameStr, InsertAtEnd) {}
 
 public:
-  static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
+  static CleanupPadInst *Create(Value *ParentPad, ArrayRef<Value *> Args = None,
                                 const Twine &NameStr = "",
                                 Instruction *InsertBefore = nullptr) {
-    return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertBefore);
+    unsigned Values = 1 + Args.size();
+    return new (Values)
+        CleanupPadInst(ParentPad, Args, Values, NameStr, InsertBefore);
   }
-  static CleanupPadInst *Create(LLVMContext &C, ArrayRef<Value *> Args,
+  static CleanupPadInst *Create(Value *ParentPad, ArrayRef<Value *> Args,
                                 const Twine &NameStr, BasicBlock *InsertAtEnd) {
-    return new (Args.size()) CleanupPadInst(C, Args, NameStr, InsertAtEnd);
+    unsigned Values = 1 + Args.size();
+    return new (Values)
+        CleanupPadInst(ParentPad, Args, Values, NameStr, InsertAtEnd);
   }
 
-  /// Provide fast operand accessors
-  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
-  // Methods for support type inquiry through isa, cast, and dyn_cast:
+  /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Instruction *I) {
     return I->getOpcode() == Instruction::CleanupPad;
   }
@@ -4163,11 +4168,54 @@ public:
   }
 };
 
-template <>
-struct OperandTraits<CleanupPadInst>
-    : public VariadicOperandTraits<CleanupPadInst, /*MINARITY=*/0> {};
+//===----------------------------------------------------------------------===//
+//                               CatchPadInst Class
+//===----------------------------------------------------------------------===//
+class CatchPadInst : public FuncletPadInst {
+private:
+  explicit CatchPadInst(Value *CatchSwitch, ArrayRef<Value *> Args,
+                        unsigned Values, const Twine &NameStr,
+                        Instruction *InsertBefore)
+      : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values,
+                       NameStr, InsertBefore) {}
+  explicit CatchPadInst(Value *CatchSwitch, ArrayRef<Value *> Args,
+                        unsigned Values, const Twine &NameStr,
+                        BasicBlock *InsertAtEnd)
+      : FuncletPadInst(Instruction::CatchPad, CatchSwitch, Args, Values,
+                       NameStr, InsertAtEnd) {}
+
+public:
+  static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
+                              const Twine &NameStr = "",
+                              Instruction *InsertBefore = nullptr) {
+    unsigned Values = 1 + Args.size();
+    return new (Values)
+        CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertBefore);
+  }
+  static CatchPadInst *Create(Value *CatchSwitch, ArrayRef<Value *> Args,
+                              const Twine &NameStr, BasicBlock *InsertAtEnd) {
+    unsigned Values = 1 + Args.size();
+    return new (Values)
+        CatchPadInst(CatchSwitch, Args, Values, NameStr, InsertAtEnd);
+  }
+
+  /// Convenience accessors
+  CatchSwitchInst *getCatchSwitch() const {
+    return cast<CatchSwitchInst>(Op<-1>());
+  }
+  void setCatchSwitch(Value *CatchSwitch) {
+    assert(CatchSwitch);
+    Op<-1>() = CatchSwitch;
+  }
 
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value)
+  /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const Instruction *I) {
+    return I->getOpcode() == Instruction::CatchPad;
+  }
+  static inline bool classof(const Value *V) {
+    return isa<Instruction>(V) && classof(cast<Instruction>(V));
+  }
+};
 
 //===----------------------------------------------------------------------===//
 //                               CatchReturnInst Class
@@ -4176,11 +4224,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Cle
 class CatchReturnInst : public TerminatorInst {
   CatchReturnInst(const CatchReturnInst &RI);
 
-  void init(CatchPadInst *CatchPad, BasicBlock *BB);
-  CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
-                  Instruction *InsertBefore);
-  CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
-                  BasicBlock *InsertAtEnd);
+  void init(Value *CatchPad, BasicBlock *BB);
+  CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore);
+  CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd);
 
 protected:
   // Note: Instruction needs to be a friend here to call cloneImpl.
@@ -4188,13 +4234,13 @@ protected:
   CatchReturnInst *cloneImpl() const;
 
 public:
-  static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
+  static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
                                  Instruction *InsertBefore = nullptr) {
     assert(CatchPad);
     assert(BB);
     return new (2) CatchReturnInst(CatchPad, BB, InsertBefore);
   }
-  static CatchReturnInst *Create(CatchPadInst *CatchPad, BasicBlock *BB,
+  static CatchReturnInst *Create(Value *CatchPad, BasicBlock *BB,
                                  BasicBlock *InsertAtEnd) {
     assert(CatchPad);
     assert(BB);
@@ -4218,6 +4264,10 @@ public:
   }
   unsigned getNumSuccessors() const { return 1; }
 
+  Value *getParentPad() const {
+    return getCatchPad()->getCatchSwitch()->getParentPad();
+  }
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Instruction *I) {
     return (I->getOpcode() == Instruction::CatchRet);
@@ -4239,93 +4289,6 @@ struct OperandTraits<CatchReturnInst>
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
 
 //===----------------------------------------------------------------------===//
-//                               CleanupEndPadInst Class
-//===----------------------------------------------------------------------===//
-
-class CleanupEndPadInst : public TerminatorInst {
-private:
-  CleanupEndPadInst(const CleanupEndPadInst &CEPI);
-
-  void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB);
-  CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
-                    unsigned Values, Instruction *InsertBefore = nullptr);
-  CleanupEndPadInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
-                    unsigned Values, BasicBlock *InsertAtEnd);
-
-protected:
-  // Note: Instruction needs to be a friend here to call cloneImpl.
-  friend class Instruction;
-  CleanupEndPadInst *cloneImpl() const;
-
-public:
-  static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad,
-                                   BasicBlock *UnwindBB = nullptr,
-                                   Instruction *InsertBefore = nullptr) {
-    unsigned Values = UnwindBB ? 2 : 1;
-    return new (Values)
-        CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertBefore);
-  }
-  static CleanupEndPadInst *Create(CleanupPadInst *CleanupPad,
-                                   BasicBlock *UnwindBB,
-                                   BasicBlock *InsertAtEnd) {
-    unsigned Values = UnwindBB ? 2 : 1;
-    return new (Values)
-        CleanupEndPadInst(CleanupPad, UnwindBB, Values, InsertAtEnd);
-  }
-
-  /// Provide fast operand accessors
-  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
-
-  bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; }
-  bool unwindsToCaller() const { return !hasUnwindDest(); }
-
-  unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
-
-  /// Convenience accessors
-  CleanupPadInst *getCleanupPad() const {
-    return cast<CleanupPadInst>(Op<-1>());
-  }
-  void setCleanupPad(CleanupPadInst *CleanupPad) {
-    assert(CleanupPad);
-    Op<-1>() = CleanupPad;
-  }
-
-  BasicBlock *getUnwindDest() const {
-    return hasUnwindDest() ? cast<BasicBlock>(Op<-2>()) : nullptr;
-  }
-  void setUnwindDest(BasicBlock *NewDest) {
-    assert(hasUnwindDest());
-    assert(NewDest);
-    Op<-2>() = NewDest;
-  }
-
-  // Methods for support type inquiry through isa, cast, and dyn_cast:
-  static inline bool classof(const Instruction *I) {
-    return (I->getOpcode() == Instruction::CleanupEndPad);
-  }
-  static inline bool classof(const Value *V) {
-    return isa<Instruction>(V) && classof(cast<Instruction>(V));
-  }
-
-private:
-  BasicBlock *getSuccessorV(unsigned Idx) const override;
-  unsigned getNumSuccessorsV() const override;
-  void setSuccessorV(unsigned Idx, BasicBlock *B) override;
-
-  // Shadow Instruction::setInstructionSubclassData with a private forwarding
-  // method so that subclasses cannot accidentally use it.
-  void setInstructionSubclassData(unsigned short D) {
-    Instruction::setInstructionSubclassData(D);
-  }
-};
-
-template <>
-struct OperandTraits<CleanupEndPadInst>
-    : public VariadicOperandTraits<CleanupEndPadInst, /*MINARITY=*/1> {};
-
-DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupEndPadInst, Value)
-
-//===----------------------------------------------------------------------===//
 //                               CleanupReturnInst Class
 //===----------------------------------------------------------------------===//
 
@@ -4333,11 +4296,11 @@ class CleanupReturnInst : public Termina
 private:
   CleanupReturnInst(const CleanupReturnInst &RI);
 
-  void init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB);
-  CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
-                    unsigned Values, Instruction *InsertBefore = nullptr);
-  CleanupReturnInst(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB,
-                    unsigned Values, BasicBlock *InsertAtEnd);
+  void init(Value *CleanupPad, BasicBlock *UnwindBB);
+  CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
+                    Instruction *InsertBefore = nullptr);
+  CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
+                    BasicBlock *InsertAtEnd);
 
 protected:
   // Note: Instruction needs to be a friend here to call cloneImpl.
@@ -4345,7 +4308,7 @@ protected:
   CleanupReturnInst *cloneImpl() const;
 
 public:
-  static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
+  static CleanupReturnInst *Create(Value *CleanupPad,
                                    BasicBlock *UnwindBB = nullptr,
                                    Instruction *InsertBefore = nullptr) {
     assert(CleanupPad);
@@ -4355,8 +4318,7 @@ public:
     return new (Values)
         CleanupReturnInst(CleanupPad, UnwindBB, Values, InsertBefore);
   }
-  static CleanupReturnInst *Create(CleanupPadInst *CleanupPad,
-                                   BasicBlock *UnwindBB,
+  static CleanupReturnInst *Create(Value *CleanupPad, BasicBlock *UnwindBB,
                                    BasicBlock *InsertAtEnd) {
     assert(CleanupPad);
     unsigned Values = 1;
@@ -4374,22 +4336,22 @@ public:
 
   /// Convenience accessor.
   CleanupPadInst *getCleanupPad() const {
-    return cast<CleanupPadInst>(Op<-1>());
+    return cast<CleanupPadInst>(Op<0>());
   }
   void setCleanupPad(CleanupPadInst *CleanupPad) {
     assert(CleanupPad);
-    Op<-1>() = CleanupPad;
+    Op<0>() = CleanupPad;
   }
 
   unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; }
 
   BasicBlock *getUnwindDest() const {
-    return hasUnwindDest() ? cast<BasicBlock>(Op<-2>()) : nullptr;
+    return hasUnwindDest() ? cast<BasicBlock>(Op<1>()) : nullptr;
   }
   void setUnwindDest(BasicBlock *NewDest) {
     assert(NewDest);
     assert(hasUnwindDest());
-    Op<-2>() = NewDest;
+    Op<1>() = NewDest;
   }
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:

Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Fri Dec 11 23:38:55 2015
@@ -289,8 +289,8 @@ bool replaceDbgDeclareForAlloca(AllocaIn
                                 DIBuilder &Builder, bool Deref, int Offset = 0);
 
 /// Replace 'BB's terminator with one that does not have an unwind successor
-/// block.  Rewrites `invoke` to `call`, `catchendpad unwind label %foo` to
-/// `catchendpad unwind to caller`, etc.  Updates any PHIs in unwind successor.
+/// block.  Rewrites `invoke` to `call`, `terminatepad unwind label %foo` to
+/// `terminatepad unwind to caller`, etc.  Updates any PHIs in unwind successor.
 ///
 /// \param BB  Block whose terminator will be replaced.  Its terminator must
 ///            have an unwind successor.

Modified: llvm/trunk/lib/Analysis/CaptureTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CaptureTracking.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CaptureTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/CaptureTracking.cpp Fri Dec 11 23:38:55 2015
@@ -80,12 +80,11 @@ namespace {
       if (BB == BeforeHere->getParent()) {
         // 'I' dominates 'BeforeHere' => not safe to prune.
         //
-        // The value defined by an invoke/catchpad dominates an instruction only
+        // The value defined by an invoke dominates an instruction only
         // if it dominates every instruction in UseBB. A PHI is dominated only
         // if the instruction dominates every possible use in the UseBB. Since
         // UseBB == BB, avoid pruning.
-        if (isa<InvokeInst>(BeforeHere) || isa<CatchPadInst>(BeforeHere) ||
-            isa<PHINode>(I) || I == BeforeHere)
+        if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I == BeforeHere)
           return false;
         if (!OrderedBB->dominates(BeforeHere, I))
           return false;

Modified: llvm/trunk/lib/Analysis/EHPersonalities.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/EHPersonalities.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/EHPersonalities.cpp (original)
+++ llvm/trunk/lib/Analysis/EHPersonalities.cpp Fri Dec 11 23:38:55 2015
@@ -9,7 +9,11 @@
 
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Support/Debug.h"
 using namespace llvm;
 
 /// See if the given exception handling personality function is one that we
@@ -39,3 +43,64 @@ bool llvm::canSimplifyInvokeNoUnwind(con
   // implies that the function does not throw synchronous exceptions.
   return !isAsynchronousEHPersonality(Personality);
 }
+
+DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
+  SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
+  BasicBlock *EntryBlock = &F.getEntryBlock();
+  DenseMap<BasicBlock *, ColorVector> BlockColors;
+
+  // Build up the color map, which maps each block to its set of 'colors'.
+  // For any block B the "colors" of B are the set of funclets F (possibly
+  // including a root "funclet" representing the main function) such that
+  // F will need to directly contain B or a copy of B (where the term "directly
+  // contain" is used to distinguish from being "transitively contained" in
+  // a nested funclet).
+  //
+  // Note: Despite not being funclets in the truest sense, terminatepad and
+  // catchswitch are considered to belong to their own funclet for the purposes
+  // of coloring.
+
+  DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
+                                                  << F.getName() << "\n");
+
+  Worklist.push_back({EntryBlock, EntryBlock});
+
+  while (!Worklist.empty()) {
+    BasicBlock *Visiting;
+    BasicBlock *Color;
+    std::tie(Visiting, Color) = Worklist.pop_back_val();
+    DEBUG_WITH_TYPE("winehprepare-coloring",
+                    dbgs() << "Visiting " << Visiting->getName() << ", "
+                           << Color->getName() << "\n");
+    Instruction *VisitingHead = Visiting->getFirstNonPHI();
+    if (VisitingHead->isEHPad()) {
+      // Mark this funclet head as a member of itself.
+      Color = Visiting;
+    }
+    // Note that this is a member of the given color.
+    ColorVector &Colors = BlockColors[Visiting];
+    if (std::find(Colors.begin(), Colors.end(), Color) == Colors.end())
+      Colors.push_back(Color);
+    else
+      continue;
+
+    DEBUG_WITH_TYPE("winehprepare-coloring",
+                    dbgs() << "  Assigned color \'" << Color->getName()
+                           << "\' to block \'" << Visiting->getName()
+                           << "\'.\n");
+
+    BasicBlock *SuccColor = Color;
+    TerminatorInst *Terminator = Visiting->getTerminator();
+    if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
+      Value *ParentPad = CatchRet->getParentPad();
+      if (isa<ConstantTokenNone>(ParentPad))
+        SuccColor = EntryBlock;
+      else
+        SuccColor = cast<Instruction>(ParentPad)->getParent();
+    }
+
+    for (BasicBlock *Succ : successors(Visiting))
+      Worklist.push_back({Succ, SuccColor});
+  }
+  return BlockColors;
+}

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Fri Dec 11 23:38:55 2015
@@ -122,10 +122,10 @@ static bool ValueDominatesPHI(Value *V,
     return DT->dominates(I, P);
   }
 
-  // Otherwise, if the instruction is in the entry block, and is not an invoke,
-  // and is not a catchpad, then it obviously dominates all phi nodes.
+  // Otherwise, if the instruction is in the entry block and is not an invoke,
+  // then it obviously dominates all phi nodes.
   if (I->getParent() == &I->getParent()->getParent()->getEntryBlock() &&
-      !isa<InvokeInst>(I) && !isa<CatchPadInst>(I))
+      !isa<InvokeInst>(I))
     return true;
 
   return false;

Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LoopInfo.cpp Fri Dec 11 23:38:55 2015
@@ -227,9 +227,15 @@ bool Loop::isSafeToClone() const {
     if (isa<IndirectBrInst>((*I)->getTerminator()))
       return false;
 
-    if (const InvokeInst *II = dyn_cast<InvokeInst>((*I)->getTerminator()))
+    if (const InvokeInst *II = dyn_cast<InvokeInst>((*I)->getTerminator())) {
       if (II->cannotDuplicate())
         return false;
+      // Return false if any loop blocks contain invokes to EH-pads other than
+      // landingpads;  we don't know how to split those edges yet.
+      auto *FirstNonPHI = II->getUnwindDest()->getFirstNonPHI();
+      if (FirstNonPHI->isEHPad() && !isa<LandingPadInst>(FirstNonPHI))
+        return false;
+    }
 
     for (BasicBlock::iterator BI = (*I)->begin(), BE = (*I)->end(); BI != BE; ++BI) {
       if (const CallInst *CI = dyn_cast<CallInst>(BI)) {

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Fri Dec 11 23:38:55 2015
@@ -91,22 +91,16 @@ static BasicBlock::iterator findInsertPo
   BasicBlock::iterator IP = ++I->getIterator();
   if (auto *II = dyn_cast<InvokeInst>(I))
     IP = II->getNormalDest()->begin();
-  if (auto *CPI = dyn_cast<CatchPadInst>(I))
-    IP = CPI->getNormalDest()->begin();
 
   while (isa<PHINode>(IP))
     ++IP;
 
   while (IP->isEHPad()) {
-    if (isa<LandingPadInst>(IP) || isa<CleanupPadInst>(IP)) {
+    if (isa<FuncletPadInst>(IP) || isa<LandingPadInst>(IP)) {
       ++IP;
     } else if (auto *TPI = dyn_cast<TerminatePadInst>(IP)) {
       IP = TPI->getUnwindDest()->getFirstNonPHI()->getIterator();
-    } else if (auto *CEPI = dyn_cast<CatchEndPadInst>(IP)) {
-      IP = CEPI->getUnwindDest()->getFirstNonPHI()->getIterator();
-    } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(IP)) {
-      IP = CEPI->getUnwindDest()->getFirstNonPHI()->getIterator();
-    } else if (isa<CatchPadInst>(IP)) {
+    } else if (isa<CatchSwitchInst>(IP)) {
       IP = MustDominate->getFirstInsertionPt();
     } else {
       llvm_unreachable("unexpected eh pad!");

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Fri Dec 11 23:38:55 2015
@@ -3431,11 +3431,10 @@ bool llvm::isSafeToSpeculativelyExecute(
   case Instruction::AtomicCmpXchg:
   case Instruction::LandingPad:
   case Instruction::Resume:
+  case Instruction::CatchSwitch:
   case Instruction::CatchPad:
-  case Instruction::CatchEndPad:
   case Instruction::CatchRet:
   case Instruction::CleanupPad:
-  case Instruction::CleanupEndPad:
   case Instruction::CleanupRet:
   case Instruction::TerminatePad:
     return false; // Misc instructions which have effects

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Fri Dec 11 23:38:55 2015
@@ -526,6 +526,8 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(none);
   KEYWORD(to);
   KEYWORD(caller);
+  KEYWORD(within);
+  KEYWORD(from);
   KEYWORD(tail);
   KEYWORD(musttail);
   KEYWORD(notail);
@@ -759,11 +761,10 @@ lltok::Kind LLLexer::LexIdentifier() {
   INSTKEYWORD(landingpad,     LandingPad);
   INSTKEYWORD(cleanupret,     CleanupRet);
   INSTKEYWORD(catchret,       CatchRet);
+  INSTKEYWORD(catchswitch,  CatchSwitch);
   INSTKEYWORD(catchpad,     CatchPad);
   INSTKEYWORD(terminatepad, TerminatePad);
   INSTKEYWORD(cleanuppad,   CleanupPad);
-  INSTKEYWORD(catchendpad,  CatchEndPad);
-  INSTKEYWORD(cleanupendpad, CleanupEndPad);
 #undef INSTKEYWORD
 
 #define DWKEYWORD(TYPE, TOKEN)                                                 \

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Fri Dec 11 23:38:55 2015
@@ -2315,7 +2315,7 @@ bool LLParser::PerFunctionState::FinishF
 /// forward reference record if needed.  This can return null if the value
 /// exists but does not have the right type.
 Value *LLParser::PerFunctionState::GetVal(const std::string &Name, Type *Ty,
-                                          LocTy Loc, OperatorConstraint OC) {
+                                          LocTy Loc) {
   // Look this name up in the normal function symbol table.
   Value *Val = F.getValueSymbolTable().lookup(Name);
 
@@ -2329,24 +2329,6 @@ Value *LLParser::PerFunctionState::GetVa
 
   // If we have the value in the symbol table or fwd-ref table, return it.
   if (Val) {
-    // Check operator constraints.
-    switch (OC) {
-    case OC_None:
-      // no constraint
-      break;
-    case OC_CatchPad:
-      if (!isa<CatchPadInst>(Val)) {
-        P.Error(Loc, "'%" + Name + "' is not a catchpad");
-        return nullptr;
-      }
-      break;
-    case OC_CleanupPad:
-      if (!isa<CleanupPadInst>(Val)) {
-        P.Error(Loc, "'%" + Name + "' is not a cleanuppad");
-        return nullptr;
-      }
-      break;
-    }
     if (Val->getType() == Ty) return Val;
     if (Ty->isLabelTy())
       P.Error(Loc, "'%" + Name + "' is not a basic block");
@@ -2365,30 +2347,16 @@ Value *LLParser::PerFunctionState::GetVa
   // Otherwise, create a new forward reference for this value and remember it.
   Value *FwdVal;
   if (Ty->isLabelTy()) {
-    assert(!OC);
     FwdVal = BasicBlock::Create(F.getContext(), Name, &F);
-  } else if (!OC) {
-    FwdVal = new Argument(Ty, Name);
   } else {
-    switch (OC) {
-    case OC_CatchPad:
-      FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {},
-                                    Name);
-      break;
-    case OC_CleanupPad:
-      FwdVal = CleanupPadInst::Create(F.getContext(), {}, Name);
-      break;
-    default:
-      llvm_unreachable("unexpected constraint");
-    }
+    FwdVal = new Argument(Ty, Name);
   }
 
   ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
   return FwdVal;
 }
 
-Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc,
-                                          OperatorConstraint OC) {
+Value *LLParser::PerFunctionState::GetVal(unsigned ID, Type *Ty, LocTy Loc) {
   // Look this name up in the normal function symbol table.
   Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr;
 
@@ -2402,24 +2370,6 @@ Value *LLParser::PerFunctionState::GetVa
 
   // If we have the value in the symbol table or fwd-ref table, return it.
   if (Val) {
-    // Check operator constraint.
-    switch (OC) {
-    case OC_None:
-      // no constraint
-      break;
-    case OC_CatchPad:
-      if (!isa<CatchPadInst>(Val)) {
-        P.Error(Loc, "'%" + Twine(ID) + "' is not a catchpad");
-        return nullptr;
-      }
-      break;
-    case OC_CleanupPad:
-      if (!isa<CleanupPadInst>(Val)) {
-        P.Error(Loc, "'%" + Twine(ID) + "' is not a cleanuppad");
-        return nullptr;
-      }
-      break;
-    }
     if (Val->getType() == Ty) return Val;
     if (Ty->isLabelTy())
       P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block");
@@ -2437,21 +2387,9 @@ Value *LLParser::PerFunctionState::GetVa
   // Otherwise, create a new forward reference for this value and remember it.
   Value *FwdVal;
   if (Ty->isLabelTy()) {
-    assert(!OC);
     FwdVal = BasicBlock::Create(F.getContext(), "", &F);
-  } else if (!OC) {
-    FwdVal = new Argument(Ty);
   } else {
-    switch (OC) {
-    case OC_CatchPad:
-      FwdVal = CatchPadInst::Create(&F.getEntryBlock(), &F.getEntryBlock(), {});
-      break;
-    case OC_CleanupPad:
-      FwdVal = CleanupPadInst::Create(F.getContext(), {});
-      break;
-    default:
-      llvm_unreachable("unexpected constraint");
-    }
+    FwdVal = new Argument(Ty);
   }
 
   ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
@@ -2487,17 +2425,6 @@ bool LLParser::PerFunctionState::SetInst
       if (Sentinel->getType() != Inst->getType())
         return P.Error(NameLoc, "instruction forward referenced with type '" +
                        getTypeString(FI->second.first->getType()) + "'");
-      // Check operator constraints.  We only put cleanuppads or catchpads in
-      // the forward value map if the value is constrained to match.
-      if (isa<CatchPadInst>(Sentinel)) {
-        if (!isa<CatchPadInst>(Inst))
-          return P.Error(FI->second.second,
-                         "'%" + Twine(NameID) + "' is not a catchpad");
-      } else if (isa<CleanupPadInst>(Sentinel)) {
-        if (!isa<CleanupPadInst>(Inst))
-          return P.Error(FI->second.second,
-                         "'%" + Twine(NameID) + "' is not a cleanuppad");
-      }
 
       Sentinel->replaceAllUsesWith(Inst);
       delete Sentinel;
@@ -2515,17 +2442,6 @@ bool LLParser::PerFunctionState::SetInst
     if (Sentinel->getType() != Inst->getType())
       return P.Error(NameLoc, "instruction forward referenced with type '" +
                      getTypeString(FI->second.first->getType()) + "'");
-    // Check operator constraints.  We only put cleanuppads or catchpads in
-    // the forward value map if the value is constrained to match.
-    if (isa<CatchPadInst>(Sentinel)) {
-      if (!isa<CatchPadInst>(Inst))
-        return P.Error(FI->second.second,
-                       "'%" + NameStr + "' is not a catchpad");
-    } else if (isa<CleanupPadInst>(Sentinel)) {
-      if (!isa<CleanupPadInst>(Inst))
-        return P.Error(FI->second.second,
-                       "'%" + NameStr + "' is not a cleanuppad");
-    }
 
     Sentinel->replaceAllUsesWith(Inst);
     delete Sentinel;
@@ -4235,30 +4151,18 @@ bool LLParser::ParseMetadata(Metadata *&
 //===----------------------------------------------------------------------===//
 
 bool LLParser::ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
-                                   PerFunctionState *PFS,
-                                   OperatorConstraint OC) {
+                                   PerFunctionState *PFS) {
   if (Ty->isFunctionTy())
     return Error(ID.Loc, "functions are not values, refer to them as pointers");
 
-  if (OC && ID.Kind != ValID::t_LocalID && ID.Kind != ValID::t_LocalName) {
-    switch (OC) {
-    case OC_CatchPad:
-      return Error(ID.Loc, "Catchpad value required in this position");
-    case OC_CleanupPad:
-      return Error(ID.Loc, "Cleanuppad value required in this position");
-    default:
-      llvm_unreachable("Unexpected constraint kind");
-    }
-  }
-
   switch (ID.Kind) {
   case ValID::t_LocalID:
     if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
-    V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc, OC);
+    V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc);
     return V == nullptr;
   case ValID::t_LocalName:
     if (!PFS) return Error(ID.Loc, "invalid use of function-local name");
-    V = PFS->GetVal(ID.StrVal, Ty, ID.Loc, OC);
+    V = PFS->GetVal(ID.StrVal, Ty, ID.Loc);
     return V == nullptr;
   case ValID::t_InlineAsm: {
     if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2))
@@ -4385,11 +4289,10 @@ bool LLParser::parseConstantValue(Type *
   }
 }
 
-bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
-                          OperatorConstraint OC) {
+bool LLParser::ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
   V = nullptr;
   ValID ID;
-  return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS, OC);
+  return ParseValID(ID, PFS) || ConvertValIDToValue(Ty, ID, V, PFS);
 }
 
 bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
@@ -4818,11 +4721,10 @@ int LLParser::ParseInstruction(Instructi
   case lltok::kw_resume:      return ParseResume(Inst, PFS);
   case lltok::kw_cleanupret:  return ParseCleanupRet(Inst, PFS);
   case lltok::kw_catchret:    return ParseCatchRet(Inst, PFS);
-  case lltok::kw_catchpad:  return ParseCatchPad(Inst, PFS);
-  case lltok::kw_terminatepad: return ParseTerminatePad(Inst, PFS);
-  case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS);
-  case lltok::kw_catchendpad: return ParseCatchEndPad(Inst, PFS);
-  case lltok::kw_cleanupendpad: return ParseCleanupEndPad(Inst, PFS);
+  case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS);
+  case lltok::kw_catchpad:    return ParseCatchPad(Inst, PFS);
+  case lltok::kw_terminatepad:return ParseTerminatePad(Inst, PFS);
+  case lltok::kw_cleanuppad:  return ParseCleanupPad(Inst, PFS);
   // Binary Operators.
   case lltok::kw_add:
   case lltok::kw_sub:
@@ -5262,11 +5164,14 @@ bool LLParser::ParseExceptionArgs(SmallV
 }
 
 /// ParseCleanupRet
-///   ::= 'cleanupret' Value unwind ('to' 'caller' | TypeAndValue)
+///   ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue)
 bool LLParser::ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) {
   Value *CleanupPad = nullptr;
 
-  if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+  if (ParseToken(lltok::kw_from, "expected 'from' after cleanupret"))
+    return true;
+
+  if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS))
     return true;
 
   if (ParseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret"))
@@ -5283,16 +5188,19 @@ bool LLParser::ParseCleanupRet(Instructi
     }
   }
 
-  Inst = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+  Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB);
   return false;
 }
 
 /// ParseCatchRet
-///   ::= 'catchret' Value 'to' TypeAndValue
+///   ::= 'catchret' from Parent Value 'to' TypeAndValue
 bool LLParser::ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS) {
   Value *CatchPad = nullptr;
 
-  if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS, OC_CatchPad))
+  if (ParseToken(lltok::kw_from, "expected 'from' after catchret"))
+    return true;
+
+  if (ParseValue(Type::getTokenTy(Context), CatchPad, PFS))
     return true;
 
   BasicBlock *BB;
@@ -5300,114 +5208,140 @@ bool LLParser::ParseCatchRet(Instruction
       ParseTypeAndBasicBlock(BB, PFS))
       return true;
 
-  Inst = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
+  Inst = CatchReturnInst::Create(CatchPad, BB);
   return false;
 }
 
-/// ParseCatchPad
-///   ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
-bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
-  SmallVector<Value *, 8> Args;
-  if (ParseExceptionArgs(Args, PFS))
+/// ParseCatchSwitch
+///   ::= 'catchswitch' within Parent
+bool LLParser::ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS) {
+  Value *ParentPad;
+  LocTy BBLoc;
+
+  if (ParseToken(lltok::kw_within, "expected 'within' after catchswitch"))
     return true;
 
-  BasicBlock *NormalBB, *UnwindBB;
-  if (ParseToken(lltok::kw_to, "expected 'to' in catchpad") ||
-      ParseTypeAndBasicBlock(NormalBB, PFS) ||
-      ParseToken(lltok::kw_unwind, "expected 'unwind' in catchpad") ||
-      ParseTypeAndBasicBlock(UnwindBB, PFS))
+  if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+      Lex.getKind() != lltok::LocalVarID)
+    return TokError("expected scope value for catchswitch");
+
+  if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
     return true;
 
-  Inst = CatchPadInst::Create(NormalBB, UnwindBB, Args);
-  return false;
-}
+  if (ParseToken(lltok::lsquare, "expected '[' with catchswitch labels"))
+    return true;
 
-/// ParseTerminatePad
-///   ::= 'terminatepad' ParamList 'to' TypeAndValue
-bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
-  SmallVector<Value *, 8> Args;
-  if (ParseExceptionArgs(Args, PFS))
+  SmallVector<BasicBlock *, 32> Table;
+  do {
+    BasicBlock *DestBB;
+    if (ParseTypeAndBasicBlock(DestBB, PFS))
+      return true;
+    Table.push_back(DestBB);
+  } while (EatIfPresent(lltok::comma));
+
+  if (ParseToken(lltok::rsquare, "expected ']' after catchswitch labels"))
     return true;
 
-  if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
+  if (ParseToken(lltok::kw_unwind,
+                 "expected 'unwind' after catchswitch scope"))
     return true;
 
   BasicBlock *UnwindBB = nullptr;
-  if (Lex.getKind() == lltok::kw_to) {
-    Lex.Lex();
-    if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
+  if (EatIfPresent(lltok::kw_to)) {
+    if (ParseToken(lltok::kw_caller, "expected 'caller' in catchswitch"))
       return true;
   } else {
-    if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
+    if (ParseTypeAndBasicBlock(UnwindBB, PFS))
       return true;
-    }
   }
 
-  Inst = TerminatePadInst::Create(Context, UnwindBB, Args);
+  auto *CatchSwitch =
+      CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size());
+  for (BasicBlock *DestBB : Table)
+    CatchSwitch->addHandler(DestBB);
+  Inst = CatchSwitch;
   return false;
 }
 
-/// ParseCleanupPad
-///   ::= 'cleanuppad' ParamList
-bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+/// ParseCatchPad
+///   ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue
+bool LLParser::ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS) {
+  Value *CatchSwitch = nullptr;
+
+  if (ParseToken(lltok::kw_within, "expected 'within' after catchpad"))
+    return true;
+
+  if (Lex.getKind() != lltok::LocalVar && Lex.getKind() != lltok::LocalVarID)
+    return TokError("expected scope value for catchpad");
+
+  if (ParseValue(Type::getTokenTy(Context), CatchSwitch, PFS))
+    return true;
+
   SmallVector<Value *, 8> Args;
   if (ParseExceptionArgs(Args, PFS))
     return true;
 
-  Inst = CleanupPadInst::Create(Context, Args);
+  Inst = CatchPadInst::Create(CatchSwitch, Args);
   return false;
 }
 
-/// ParseCatchEndPad
-///   ::= 'catchendpad' unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS) {
-  if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+/// ParseTerminatePad
+///   ::= 'terminatepad' within Parent ParamList 'to' TypeAndValue
+bool LLParser::ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS) {
+  Value *ParentPad = nullptr;
+
+  if (ParseToken(lltok::kw_within, "expected 'within' after terminatepad"))
+    return true;
+
+  if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+      Lex.getKind() != lltok::LocalVarID)
+    return TokError("expected scope value for terminatepad");
+
+  if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
+    return true;
+
+  SmallVector<Value *, 8> Args;
+  if (ParseExceptionArgs(Args, PFS))
+    return true;
+
+  if (ParseToken(lltok::kw_unwind, "expected 'unwind' in terminatepad"))
     return true;
 
   BasicBlock *UnwindBB = nullptr;
   if (Lex.getKind() == lltok::kw_to) {
     Lex.Lex();
-    if (Lex.getKind() == lltok::kw_caller) {
-      Lex.Lex();
-    } else {
+    if (ParseToken(lltok::kw_caller, "expected 'caller' in terminatepad"))
       return true;
-    }
   } else {
     if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
       return true;
     }
   }
 
-  Inst = CatchEndPadInst::Create(Context, UnwindBB);
+  Inst = TerminatePadInst::Create(ParentPad, UnwindBB, Args);
   return false;
 }
 
-/// ParseCatchEndPad
-///   ::= 'cleanupendpad' Value unwind ('to' 'caller' | TypeAndValue)
-bool LLParser::ParseCleanupEndPad(Instruction *&Inst, PerFunctionState &PFS) {
-  Value *CleanupPad = nullptr;
+/// ParseCleanupPad
+///   ::= 'cleanuppad' within Parent ParamList
+bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) {
+  Value *ParentPad = nullptr;
 
-  if (ParseValue(Type::getTokenTy(Context), CleanupPad, PFS, OC_CleanupPad))
+  if (ParseToken(lltok::kw_within, "expected 'within' after cleanuppad"))
     return true;
 
-  if (ParseToken(lltok::kw_unwind, "expected 'unwind' in catchendpad"))
+  if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar &&
+      Lex.getKind() != lltok::LocalVarID)
+    return TokError("expected scope value for cleanuppad");
+
+  if (ParseValue(Type::getTokenTy(Context), ParentPad, PFS))
     return true;
 
-  BasicBlock *UnwindBB = nullptr;
-  if (Lex.getKind() == lltok::kw_to) {
-    Lex.Lex();
-    if (Lex.getKind() == lltok::kw_caller) {
-      Lex.Lex();
-    } else {
-      return true;
-    }
-  } else {
-    if (ParseTypeAndBasicBlock(UnwindBB, PFS)) {
-      return true;
-    }
-  }
+  SmallVector<Value *, 8> Args;
+  if (ParseExceptionArgs(Args, PFS))
+    return true;
 
-  Inst = CleanupEndPadInst::Create(cast<CleanupPadInst>(CleanupPad), UnwindBB);
+  Inst = CleanupPadInst::Create(ParentPad, Args);
   return false;
 }
 

Modified: llvm/trunk/lib/AsmParser/LLParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Fri Dec 11 23:38:55 2015
@@ -108,14 +108,6 @@ namespace llvm {
       unsigned MDKind, MDSlot;
     };
 
-    /// Indicates which operator an operand allows (for the few operands that
-    /// may only reference a certain operator).
-    enum OperatorConstraint {
-      OC_None = 0,  // No constraint
-      OC_CatchPad,  // Must be CatchPadInst
-      OC_CleanupPad // Must be CleanupPadInst
-    };
-
     SmallVector<Instruction*, 64> InstsWithTBAATag;
 
     // Type resolution handling data structures.  The location is set when we
@@ -337,10 +329,8 @@ namespace llvm {
       /// GetVal - Get a value with the specified name or ID, creating a
       /// forward reference record if needed.  This can return null if the value
       /// exists but does not have the right type.
-      Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc,
-                    OperatorConstraint OC = OC_None);
-      Value *GetVal(unsigned ID, Type *Ty, LocTy Loc,
-                    OperatorConstraint OC = OC_None);
+      Value *GetVal(const std::string &Name, Type *Ty, LocTy Loc);
+      Value *GetVal(unsigned ID, Type *Ty, LocTy Loc);
 
       /// SetInstName - After an instruction is parsed and inserted into its
       /// basic block, this installs its name.
@@ -362,16 +352,14 @@ namespace llvm {
     };
 
     bool ConvertValIDToValue(Type *Ty, ValID &ID, Value *&V,
-                             PerFunctionState *PFS,
-                             OperatorConstraint OC = OC_None);
+                             PerFunctionState *PFS);
 
     bool parseConstantValue(Type *Ty, Constant *&C);
-    bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS,
-                    OperatorConstraint OC = OC_None);
-    bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS,
-                    OperatorConstraint OC = OC_None) {
-      return ParseValue(Ty, V, &PFS, OC);
+    bool ParseValue(Type *Ty, Value *&V, PerFunctionState *PFS);
+    bool ParseValue(Type *Ty, Value *&V, PerFunctionState &PFS) {
+      return ParseValue(Ty, V, &PFS);
     }
+
     bool ParseValue(Type *Ty, Value *&V, LocTy &Loc,
                     PerFunctionState &PFS) {
       Loc = Lex.getLoc();
@@ -475,11 +463,10 @@ namespace llvm {
     bool ParseResume(Instruction *&Inst, PerFunctionState &PFS);
     bool ParseCleanupRet(Instruction *&Inst, PerFunctionState &PFS);
     bool ParseCatchRet(Instruction *&Inst, PerFunctionState &PFS);
+    bool ParseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS);
     bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS);
     bool ParseTerminatePad(Instruction *&Inst, PerFunctionState &PFS);
     bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS);
-    bool ParseCatchEndPad(Instruction *&Inst, PerFunctionState &PFS);
-    bool ParseCleanupEndPad(Instruction *&Inst, PerFunctionState &PFS);
 
     bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc,
                          unsigned OperandType);

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Fri Dec 11 23:38:55 2015
@@ -52,6 +52,8 @@ namespace lltok {
     kw_undef, kw_null, kw_none,
     kw_to,
     kw_caller,
+    kw_within,
+    kw_from,
     kw_tail,
     kw_musttail,
     kw_notail,
@@ -182,8 +184,8 @@ namespace lltok {
     kw_landingpad, kw_personality, kw_cleanup, kw_catch, kw_filter,
 
     kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_resume,
-    kw_unreachable, kw_cleanupret, kw_catchret, kw_catchpad,
-    kw_terminatepad, kw_cleanuppad, kw_catchendpad, kw_cleanupendpad,
+    kw_unreachable, kw_cleanupret, kw_catchswitch, kw_catchret, kw_catchpad,
+    kw_terminatepad, kw_cleanuppad,
 
     kw_alloca, kw_load, kw_store, kw_fence, kw_cmpxchg, kw_atomicrmw,
     kw_getelementptr,

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Fri Dec 11 23:38:55 2015
@@ -42,14 +42,6 @@ enum {
   SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
 };
 
-/// Indicates which operator an operand allows (for the few operands that may
-/// only reference a certain operator).
-enum OperatorConstraint {
-  OC_None = 0,  // No constraint
-  OC_CatchPad,  // Must be CatchPadInst
-  OC_CleanupPad // Must be CleanupPadInst
-};
-
 class BitcodeReaderValueList {
   std::vector<WeakVH> ValuePtrs;
 
@@ -93,10 +85,9 @@ public:
   }
 
   Constant *getConstantFwdRef(unsigned Idx, Type *Ty);
-  Value *getValueFwdRef(unsigned Idx, Type *Ty,
-                        OperatorConstraint OC = OC_None);
+  Value *getValueFwdRef(unsigned Idx, Type *Ty);
 
-  bool assignValue(Value *V, unsigned Idx);
+  void assignValue(Value *V, unsigned Idx);
 
   /// Once all constants are read, this method bulk resolves any forward
   /// references.
@@ -297,11 +288,10 @@ private:
   StructType *createIdentifiedStructType(LLVMContext &Context);
 
   Type *getTypeByID(unsigned ID);
-  Value *getFnValueByID(unsigned ID, Type *Ty,
-                        OperatorConstraint OC = OC_None) {
+  Value *getFnValueByID(unsigned ID, Type *Ty) {
     if (Ty && Ty->isMetadataTy())
       return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
-    return ValueList.getValueFwdRef(ID, Ty, OC);
+    return ValueList.getValueFwdRef(ID, Ty);
   }
   Metadata *getFnMetadataByID(unsigned ID) {
     return MDValueList.getValueFwdRef(ID);
@@ -344,9 +334,8 @@ private:
   /// past the number of slots used by the value in the record. Return true if
   /// there is an error.
   bool popValue(SmallVectorImpl<uint64_t> &Record, unsigned &Slot,
-                unsigned InstNum, Type *Ty, Value *&ResVal,
-                OperatorConstraint OC = OC_None) {
-    if (getValue(Record, Slot, InstNum, Ty, ResVal, OC))
+                unsigned InstNum, Type *Ty, Value *&ResVal) {
+    if (getValue(Record, Slot, InstNum, Ty, ResVal))
       return true;
     // All values currently take a single record slot.
     ++Slot;
@@ -355,34 +344,32 @@ private:
 
   /// Like popValue, but does not increment the Slot number.
   bool getValue(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
-                unsigned InstNum, Type *Ty, Value *&ResVal,
-                OperatorConstraint OC = OC_None) {
-    ResVal = getValue(Record, Slot, InstNum, Ty, OC);
+                unsigned InstNum, Type *Ty, Value *&ResVal) {
+    ResVal = getValue(Record, Slot, InstNum, Ty);
     return ResVal == nullptr;
   }
 
   /// Version of getValue that returns ResVal directly, or 0 if there is an
   /// error.
   Value *getValue(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
-                  unsigned InstNum, Type *Ty, OperatorConstraint OC = OC_None) {
+                  unsigned InstNum, Type *Ty) {
     if (Slot == Record.size()) return nullptr;
     unsigned ValNo = (unsigned)Record[Slot];
     // Adjust the ValNo, if it was encoded relative to the InstNum.
     if (UseRelativeIDs)
       ValNo = InstNum - ValNo;
-    return getFnValueByID(ValNo, Ty, OC);
+    return getFnValueByID(ValNo, Ty);
   }
 
   /// Like getValue, but decodes signed VBRs.
   Value *getValueSigned(SmallVectorImpl<uint64_t> &Record, unsigned Slot,
-                        unsigned InstNum, Type *Ty,
-                        OperatorConstraint OC = OC_None) {
+                        unsigned InstNum, Type *Ty) {
     if (Slot == Record.size()) return nullptr;
     unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]);
     // Adjust the ValNo, if it was encoded relative to the InstNum.
     if (UseRelativeIDs)
       ValNo = InstNum - ValNo;
-    return getFnValueByID(ValNo, Ty, OC);
+    return getFnValueByID(ValNo, Ty);
   }
 
   /// Converts alignment exponent (i.e. power of two (or zero)) to the
@@ -898,10 +885,10 @@ struct OperandTraits<ConstantPlaceHolder
 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
 }
 
-bool BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
+void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
   if (Idx == size()) {
     push_back(V);
-    return false;
+    return;
   }
 
   if (Idx >= size())
@@ -910,7 +897,7 @@ bool BitcodeReaderValueList::assignValue
   WeakVH &OldV = ValuePtrs[Idx];
   if (!OldV) {
     OldV = V;
-    return false;
+    return;
   }
 
   // Handle constants and non-constants (e.g. instrs) differently for
@@ -921,26 +908,11 @@ bool BitcodeReaderValueList::assignValue
   } else {
     // If there was a forward reference to this value, replace it.
     Value *PrevVal = OldV;
-    // Check operator constraints.  We only put cleanuppads or catchpads in
-    // the forward value map if the value is constrained to match.
-    if (CatchPadInst *CatchPad = dyn_cast<CatchPadInst>(PrevVal)) {
-      if (!isa<CatchPadInst>(V))
-        return true;
-      // Delete the dummy basic block that was created with the sentinel
-      // catchpad.
-      BasicBlock *DummyBlock = CatchPad->getUnwindDest();
-      assert(DummyBlock == CatchPad->getNormalDest());
-      CatchPad->dropAllReferences();
-      delete DummyBlock;
-    } else if (isa<CleanupPadInst>(PrevVal)) {
-      if (!isa<CleanupPadInst>(V))
-        return true;
-    }
     OldV->replaceAllUsesWith(V);
     delete PrevVal;
   }
 
-  return false;
+  return;
 }
 
 
@@ -961,8 +933,7 @@ Constant *BitcodeReaderValueList::getCon
   return C;
 }
 
-Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty,
-                                              OperatorConstraint OC) {
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
   // Bail out for a clearly invalid value. This would make us call resize(0)
   if (Idx == UINT_MAX)
     return nullptr;
@@ -974,39 +945,14 @@ Value *BitcodeReaderValueList::getValueF
     // If the types don't match, it's invalid.
     if (Ty && Ty != V->getType())
       return nullptr;
-    if (!OC)
-      return V;
-    // Use dyn_cast to enforce operator constraints
-    switch (OC) {
-    case OC_CatchPad:
-      return dyn_cast<CatchPadInst>(V);
-    case OC_CleanupPad:
-      return dyn_cast<CleanupPadInst>(V);
-    default:
-      llvm_unreachable("Unexpected operator constraint");
-    }
+    return V;
   }
 
   // No type specified, must be invalid reference.
   if (!Ty) return nullptr;
 
   // Create and return a placeholder, which will later be RAUW'd.
-  Value *V;
-  switch (OC) {
-  case OC_None:
-    V = new Argument(Ty);
-    break;
-  case OC_CatchPad: {
-    BasicBlock *BB = BasicBlock::Create(Context);
-    V = CatchPadInst::Create(BB, BB, {});
-    break;
-  }
-  default:
-    assert(OC == OC_CleanupPad && "unexpected operator constraint");
-    V = CleanupPadInst::Create(Context, {});
-    break;
-  }
-
+  Value *V = new Argument(Ty);
   ValuePtrs[Idx] = V;
   return V;
 }
@@ -3023,8 +2969,7 @@ std::error_code BitcodeReader::parseCons
     }
     }
 
-    if (ValueList.assignValue(V, NextCstNo))
-      return error("Invalid forward reference");
+    ValueList.assignValue(V, NextCstNo);
     ++NextCstNo;
   }
 }
@@ -4470,8 +4415,8 @@ std::error_code BitcodeReader::parseFunc
       if (Record.size() != 1 && Record.size() != 2)
         return error("Invalid record");
       unsigned Idx = 0;
-      Value *CleanupPad = getValue(Record, Idx++, NextValueNo,
-                                   Type::getTokenTy(Context), OC_CleanupPad);
+      Value *CleanupPad =
+          getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
       if (!CleanupPad)
         return error("Invalid record");
       BasicBlock *UnwindDest = nullptr;
@@ -4481,8 +4426,7 @@ std::error_code BitcodeReader::parseFunc
           return error("Invalid record");
       }
 
-      I = CleanupReturnInst::Create(cast<CleanupPadInst>(CleanupPad),
-                                    UnwindDest);
+      I = CleanupReturnInst::Create(CleanupPad, UnwindDest);
       InstructionList.push_back(I);
       break;
     }
@@ -4490,57 +4434,68 @@ std::error_code BitcodeReader::parseFunc
       if (Record.size() != 2)
         return error("Invalid record");
       unsigned Idx = 0;
-      Value *CatchPad = getValue(Record, Idx++, NextValueNo,
-                                 Type::getTokenTy(Context), OC_CatchPad);
+      Value *CatchPad =
+          getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
       if (!CatchPad)
         return error("Invalid record");
       BasicBlock *BB = getBasicBlock(Record[Idx++]);
       if (!BB)
         return error("Invalid record");
 
-      I = CatchReturnInst::Create(cast<CatchPadInst>(CatchPad), BB);
+      I = CatchReturnInst::Create(CatchPad, BB);
       InstructionList.push_back(I);
       break;
     }
-    case bitc::FUNC_CODE_INST_CATCHPAD: { // CATCHPAD: [bb#,bb#,num,(ty,val)*]
-      if (Record.size() < 3)
+    case bitc::FUNC_CODE_INST_CATCHSWITCH: { // CATCHSWITCH: [tok,num,(bb)*,bb?]
+      // We must have, at minimum, the outer scope and the number of arguments.
+      if (Record.size() < 2)
         return error("Invalid record");
+
       unsigned Idx = 0;
-      BasicBlock *NormalBB = getBasicBlock(Record[Idx++]);
-      if (!NormalBB)
-        return error("Invalid record");
-      BasicBlock *UnwindBB = getBasicBlock(Record[Idx++]);
-      if (!UnwindBB)
-        return error("Invalid record");
-      unsigned NumArgOperands = Record[Idx++];
-      SmallVector<Value *, 2> Args;
-      for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
-        Value *Val;
-        if (getValueTypePair(Record, Idx, NextValueNo, Val))
+
+      Value *ParentPad =
+          getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
+
+      unsigned NumHandlers = Record[Idx++];
+
+      SmallVector<BasicBlock *, 2> Handlers;
+      for (unsigned Op = 0; Op != NumHandlers; ++Op) {
+        BasicBlock *BB = getBasicBlock(Record[Idx++]);
+        if (!BB)
           return error("Invalid record");
-        Args.push_back(Val);
+        Handlers.push_back(BB);
       }
+
+      BasicBlock *UnwindDest = nullptr;
+      if (Idx + 1 == Record.size()) {
+        UnwindDest = getBasicBlock(Record[Idx++]);
+        if (!UnwindDest)
+          return error("Invalid record");
+      }
+
       if (Record.size() != Idx)
         return error("Invalid record");
 
-      I = CatchPadInst::Create(NormalBB, UnwindBB, Args);
+      auto *CatchSwitch =
+          CatchSwitchInst::Create(ParentPad, UnwindDest, NumHandlers);
+      for (BasicBlock *Handler : Handlers)
+        CatchSwitch->addHandler(Handler);
+      I = CatchSwitch;
       InstructionList.push_back(I);
       break;
     }
-    case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [bb#,num,(ty,val)*]
-      if (Record.size() < 1)
+    case bitc::FUNC_CODE_INST_TERMINATEPAD: { // TERMINATEPAD: [tok,bb#,num,(ty,val)*]
+      // We must have, at minimum, the outer scope and the number of arguments.
+      if (Record.size() < 2)
         return error("Invalid record");
+
       unsigned Idx = 0;
-      bool HasUnwindDest = !!Record[Idx++];
-      BasicBlock *UnwindDest = nullptr;
-      if (HasUnwindDest) {
-        if (Idx == Record.size())
-          return error("Invalid record");
-        UnwindDest = getBasicBlock(Record[Idx++]);
-        if (!UnwindDest)
-          return error("Invalid record");
-      }
+
+      Value *ParentPad =
+          getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
+
       unsigned NumArgOperands = Record[Idx++];
+
       SmallVector<Value *, 2> Args;
       for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
         Value *Val;
@@ -4548,18 +4503,34 @@ std::error_code BitcodeReader::parseFunc
           return error("Invalid record");
         Args.push_back(Val);
       }
+
+      BasicBlock *UnwindDest = nullptr;
+      if (Idx + 1 == Record.size()) {
+        UnwindDest = getBasicBlock(Record[Idx++]);
+        if (!UnwindDest)
+          return error("Invalid record");
+      }
+
       if (Record.size() != Idx)
         return error("Invalid record");
 
-      I = TerminatePadInst::Create(Context, UnwindDest, Args);
+      I = TerminatePadInst::Create(ParentPad, UnwindDest, Args);
       InstructionList.push_back(I);
       break;
     }
-    case bitc::FUNC_CODE_INST_CLEANUPPAD: { // CLEANUPPAD: [num,(ty,val)*]
-      if (Record.size() < 1)
+    case bitc::FUNC_CODE_INST_CATCHPAD:
+    case bitc::FUNC_CODE_INST_CLEANUPPAD: { // [tok,num,(ty,val)*]
+      // We must have, at minimum, the outer scope and the number of arguments.
+      if (Record.size() < 2)
         return error("Invalid record");
+
       unsigned Idx = 0;
+
+      Value *ParentPad =
+          getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
+
       unsigned NumArgOperands = Record[Idx++];
+
       SmallVector<Value *, 2> Args;
       for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
         Value *Val;
@@ -4567,42 +4538,14 @@ std::error_code BitcodeReader::parseFunc
           return error("Invalid record");
         Args.push_back(Val);
       }
-      if (Record.size() != Idx)
-        return error("Invalid record");
 
-      I = CleanupPadInst::Create(Context, Args);
-      InstructionList.push_back(I);
-      break;
-    }
-    case bitc::FUNC_CODE_INST_CATCHENDPAD: { // CATCHENDPADINST: [bb#] or []
-      if (Record.size() > 1)
-        return error("Invalid record");
-      BasicBlock *BB = nullptr;
-      if (Record.size() == 1) {
-        BB = getBasicBlock(Record[0]);
-        if (!BB)
-          return error("Invalid record");
-      }
-      I = CatchEndPadInst::Create(Context, BB);
-      InstructionList.push_back(I);
-      break;
-    }
-    case bitc::FUNC_CODE_INST_CLEANUPENDPAD: { // CLEANUPENDPADINST: [val] or [val,bb#]
-      if (Record.size() != 1 && Record.size() != 2)
-        return error("Invalid record");
-      unsigned Idx = 0;
-      Value *CleanupPad = getValue(Record, Idx++, NextValueNo,
-                                   Type::getTokenTy(Context), OC_CleanupPad);
-      if (!CleanupPad)
+      if (Record.size() != Idx)
         return error("Invalid record");
 
-      BasicBlock *BB = nullptr;
-      if (Record.size() == 2) {
-        BB = getBasicBlock(Record[Idx++]);
-        if (!BB)
-          return error("Invalid record");
-      }
-      I = CleanupEndPadInst::Create(cast<CleanupPadInst>(CleanupPad), BB);
+      if (BitCode == bitc::FUNC_CODE_INST_CLEANUPPAD)
+        I = CleanupPadInst::Create(ParentPad, Args);
+      else
+        I = CatchPadInst::Create(ParentPad, Args);
       InstructionList.push_back(I);
       break;
     }
@@ -5224,8 +5167,7 @@ std::error_code BitcodeReader::parseFunc
 
     // Non-void values get registered in the value table for future use.
     if (I && !I->getType()->isVoidTy())
-      if (ValueList.assignValue(I, NextValueNo++))
-        return error("Invalid forward reference");
+      ValueList.assignValue(I, NextValueNo++);
   }
 
 OutOfRecordLoop:

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Fri Dec 11 23:38:55 2015
@@ -1997,51 +1997,47 @@ static void WriteInstruction(const Instr
     Vals.push_back(VE.getValueID(CRI.getSuccessor()));
     break;
   }
+  case Instruction::CleanupPad:
   case Instruction::CatchPad: {
-    Code = bitc::FUNC_CODE_INST_CATCHPAD;
-    const auto &CPI = cast<CatchPadInst>(I);
-    Vals.push_back(VE.getValueID(CPI.getNormalDest()));
-    Vals.push_back(VE.getValueID(CPI.getUnwindDest()));
-    unsigned NumArgOperands = CPI.getNumArgOperands();
+    const auto &FuncletPad = cast<FuncletPadInst>(I);
+    Code = isa<CatchPadInst>(FuncletPad) ? bitc::FUNC_CODE_INST_CATCHPAD
+                                         : bitc::FUNC_CODE_INST_CLEANUPPAD;
+    pushValue(FuncletPad.getParentPad(), InstID, Vals, VE);
+
+    unsigned NumArgOperands = FuncletPad.getNumArgOperands();
     Vals.push_back(NumArgOperands);
     for (unsigned Op = 0; Op != NumArgOperands; ++Op)
-      PushValueAndType(CPI.getArgOperand(Op), InstID, Vals, VE);
+      PushValueAndType(FuncletPad.getArgOperand(Op), InstID, Vals, VE);
+    break;
+  }
+  case Instruction::CatchSwitch: {
+    Code = bitc::FUNC_CODE_INST_CATCHSWITCH;
+    const auto &CatchSwitch = cast<CatchSwitchInst>(I);
+
+    pushValue(CatchSwitch.getParentPad(), InstID, Vals, VE);
+
+    unsigned NumHandlers = CatchSwitch.getNumHandlers();
+    Vals.push_back(NumHandlers);
+    for (const BasicBlock *CatchPadBB : CatchSwitch.handlers())
+      Vals.push_back(VE.getValueID(CatchPadBB));
+
+    if (CatchSwitch.hasUnwindDest())
+      Vals.push_back(VE.getValueID(CatchSwitch.getUnwindDest()));
     break;
   }
   case Instruction::TerminatePad: {
     Code = bitc::FUNC_CODE_INST_TERMINATEPAD;
     const auto &TPI = cast<TerminatePadInst>(I);
-    Vals.push_back(TPI.hasUnwindDest());
-    if (TPI.hasUnwindDest())
-      Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
+
+    pushValue(TPI.getParentPad(), InstID, Vals, VE);
+
     unsigned NumArgOperands = TPI.getNumArgOperands();
     Vals.push_back(NumArgOperands);
     for (unsigned Op = 0; Op != NumArgOperands; ++Op)
       PushValueAndType(TPI.getArgOperand(Op), InstID, Vals, VE);
-    break;
-  }
-  case Instruction::CleanupPad: {
-    Code = bitc::FUNC_CODE_INST_CLEANUPPAD;
-    const auto &CPI = cast<CleanupPadInst>(I);
-    unsigned NumOperands = CPI.getNumOperands();
-    Vals.push_back(NumOperands);
-    for (unsigned Op = 0; Op != NumOperands; ++Op)
-      PushValueAndType(CPI.getOperand(Op), InstID, Vals, VE);
-    break;
-  }
-  case Instruction::CatchEndPad: {
-    Code = bitc::FUNC_CODE_INST_CATCHENDPAD;
-    const auto &CEPI = cast<CatchEndPadInst>(I);
-    if (CEPI.hasUnwindDest())
-      Vals.push_back(VE.getValueID(CEPI.getUnwindDest()));
-    break;
-  }
-  case Instruction::CleanupEndPad: {
-    Code = bitc::FUNC_CODE_INST_CLEANUPENDPAD;
-    const auto &CEPI = cast<CleanupEndPadInst>(I);
-    pushValue(CEPI.getCleanupPad(), InstID, Vals, VE);
-    if (CEPI.hasUnwindDest())
-      Vals.push_back(VE.getValueID(CEPI.getUnwindDest()));
+
+    if (TPI.hasUnwindDest())
+      Vals.push_back(VE.getValueID(TPI.getUnwindDest()));
     break;
   }
   case Instruction::Unreachable:

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp Fri Dec 11 23:38:55 2015
@@ -344,42 +344,32 @@ class InvokeStateChangeIterator {
   InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo,
                             MachineFunction::const_iterator MFI,
                             MachineFunction::const_iterator MFE,
-                            MachineBasicBlock::const_iterator MBBI)
-      : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI) {
+                            MachineBasicBlock::const_iterator MBBI,
+                            int BaseState)
+      : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) {
     LastStateChange.PreviousEndLabel = nullptr;
     LastStateChange.NewStartLabel = nullptr;
-    LastStateChange.NewState = NullState;
+    LastStateChange.NewState = BaseState;
     scan();
   }
 
 public:
   static iterator_range<InvokeStateChangeIterator>
-  range(const WinEHFuncInfo &EHInfo, const MachineFunction &MF) {
-    // Reject empty MFs to simplify bookkeeping by ensuring that we can get the
-    // end of the last block.
-    assert(!MF.empty());
-    auto FuncBegin = MF.begin();
-    auto FuncEnd = MF.end();
-    auto BlockBegin = FuncBegin->begin();
-    auto BlockEnd = MF.back().end();
-    return make_range(
-        InvokeStateChangeIterator(EHInfo, FuncBegin, FuncEnd, BlockBegin),
-        InvokeStateChangeIterator(EHInfo, FuncEnd, FuncEnd, BlockEnd));
-  }
-  static iterator_range<InvokeStateChangeIterator>
   range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin,
-        MachineFunction::const_iterator End) {
+        MachineFunction::const_iterator End, int BaseState = NullState) {
     // Reject empty ranges to simplify bookkeeping by ensuring that we can get
     // the end of the last block.
     assert(Begin != End);
     auto BlockBegin = Begin->begin();
     auto BlockEnd = std::prev(End)->end();
-    return make_range(InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin),
-                      InvokeStateChangeIterator(EHInfo, End, End, BlockEnd));
+    return make_range(
+        InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState),
+        InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState));
   }
 
   // Iterator methods.
   bool operator==(const InvokeStateChangeIterator &O) const {
+    assert(BaseState == O.BaseState);
     // Must be visiting same block.
     if (MFI != O.MFI)
       return false;
@@ -410,6 +400,7 @@ private:
   MachineBasicBlock::const_iterator MBBI;
   InvokeStateChange LastStateChange;
   bool VisitingInvoke = false;
+  int BaseState;
 };
 
 } // end anonymous namespace
@@ -421,14 +412,14 @@ InvokeStateChangeIterator &InvokeStateCh
       MBBI = MFI->begin();
     for (auto MBBE = MFI->end(); MBBI != MBBE; ++MBBI) {
       const MachineInstr &MI = *MBBI;
-      if (!VisitingInvoke && LastStateChange.NewState != NullState &&
+      if (!VisitingInvoke && LastStateChange.NewState != BaseState &&
           MI.isCall() && !EHStreamer::callToNoUnwindFunction(&MI)) {
         // Indicate a change of state to the null state.  We don't have
         // start/end EH labels handy but the caller won't expect them for
         // null state regions.
         LastStateChange.PreviousEndLabel = CurrentEndLabel;
         LastStateChange.NewStartLabel = nullptr;
-        LastStateChange.NewState = NullState;
+        LastStateChange.NewState = BaseState;
         CurrentEndLabel = nullptr;
         // Don't re-visit this instr on the next scan
         ++MBBI;
@@ -443,18 +434,12 @@ InvokeStateChangeIterator &InvokeStateCh
         VisitingInvoke = false;
         continue;
       }
-      auto InvokeMapIter = EHInfo.InvokeToStateMap.find(Label);
+      auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label);
       // Ignore EH labels that aren't the ones inserted before an invoke
-      if (InvokeMapIter == EHInfo.InvokeToStateMap.end())
+      if (InvokeMapIter == EHInfo.LabelToStateMap.end())
         continue;
       auto &StateAndEnd = InvokeMapIter->second;
       int NewState = StateAndEnd.first;
-      // Ignore EH labels explicitly annotated with the null state (which
-      // can happen for invokes that unwind to a chain of endpads the last
-      // of which unwinds to caller).  We'll see the subsequent invoke and
-      // report a transition to the null state same as we do for calls.
-      if (NewState == NullState)
-        continue;
       // Keep track of the fact that we're between EH start/end labels so
       // we know not to treat the inoke we'll see as unwinding to caller.
       VisitingInvoke = true;
@@ -476,11 +461,11 @@ InvokeStateChangeIterator &InvokeStateCh
     }
   }
   // Iteration hit the end of the block range.
-  if (LastStateChange.NewState != NullState) {
+  if (LastStateChange.NewState != BaseState) {
     // Report the end of the last new state
     LastStateChange.PreviousEndLabel = CurrentEndLabel;
     LastStateChange.NewStartLabel = nullptr;
-    LastStateChange.NewState = NullState;
+    LastStateChange.NewState = BaseState;
     // Leave CurrentEndLabel non-null to distinguish this state from end.
     assert(CurrentEndLabel != nullptr);
     return *this;
@@ -775,26 +760,54 @@ void WinException::emitCXXFrameHandler3T
 void WinException::computeIP2StateTable(
     const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
     SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) {
-  // Indicate that all calls from the prologue to the first invoke unwind to
-  // caller. We handle this as a special case since other ranges starting at end
-  // labels need to use LtmpN+1.
-  MCSymbol *StartLabel = Asm->getFunctionBegin();
-  assert(StartLabel && "need local function start label");
-  IPToStateTable.push_back(std::make_pair(create32bitRef(StartLabel), -1));
 
-  // FIXME: Do we need to emit entries for funclet base states?
-  for (const auto &StateChange :
-       InvokeStateChangeIterator::range(FuncInfo, *MF)) {
-    // Compute the label to report as the start of this entry; use the EH start
-    // label for the invoke if we have one, otherwise (this is a call which may
-    // unwind to our caller and does not have an EH start label, so) use the
-    // previous end label.
-    const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
-    if (!ChangeLabel)
-      ChangeLabel = StateChange.PreviousEndLabel;
-    // Emit an entry indicating that PCs after 'Label' have this EH state.
+  for (MachineFunction::const_iterator FuncletStart = MF->begin(),
+                                       FuncletEnd = MF->begin(),
+                                       End = MF->end();
+       FuncletStart != End; FuncletStart = FuncletEnd) {
+    // Find the end of the funclet
+    while (++FuncletEnd != End) {
+      if (FuncletEnd->isEHFuncletEntry()) {
+        break;
+      }
+    }
+
+    // Don't emit ip2state entries for cleanup funclets. Any interesting
+    // exceptional actions in cleanups must be handled in a separate IR
+    // function.
+    if (FuncletStart->isCleanupFuncletEntry())
+      continue;
+
+    MCSymbol *StartLabel;
+    int BaseState;
+    if (FuncletStart == MF->begin()) {
+      BaseState = NullState;
+      StartLabel = Asm->getFunctionBegin();
+    } else {
+      auto *FuncletPad =
+          cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI());
+      assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0);
+      BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second;
+      StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart);
+    }
+    assert(StartLabel && "need local function start label");
     IPToStateTable.push_back(
-        std::make_pair(getLabelPlusOne(ChangeLabel), StateChange.NewState));
+        std::make_pair(create32bitRef(StartLabel), BaseState));
+
+    for (const auto &StateChange : InvokeStateChangeIterator::range(
+             FuncInfo, FuncletStart, FuncletEnd, BaseState)) {
+      // Compute the label to report as the start of this entry; use the EH
+      // start label for the invoke if we have one, otherwise (this is a call
+      // which may unwind to our caller and does not have an EH start label, so)
+      // use the previous end label.
+      const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
+      if (!ChangeLabel)
+        ChangeLabel = StateChange.PreviousEndLabel;
+      // Emit an entry indicating that PCs after 'Label' have this EH state.
+      IPToStateTable.push_back(
+          std::make_pair(getLabelPlusOne(ChangeLabel), StateChange.NewState));
+      // FIXME: assert that NewState is between CatchLow and CatchHigh.
+    }
   }
 }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Fri Dec 11 23:38:55 2015
@@ -225,12 +225,12 @@ void FunctionLoweringInfo::set(const Fun
         MMI.setHasEHFunclets(true);
         MF->getFrameInfo()->setHasOpaqueSPAdjustment(true);
       }
-      if (isa<CatchEndPadInst>(I) || isa<CleanupEndPadInst>(I)) {
+      if (isa<CatchSwitchInst>(I)) {
         assert(&*BB->begin() == I &&
                "WinEHPrepare failed to remove PHIs from imaginary BBs");
         continue;
       }
-      if (isa<CatchPadInst>(I) || isa<CleanupPadInst>(I))
+      if (isa<FuncletPadInst>(I))
         assert(&*BB->begin() == I && "WinEHPrepare failed to demote PHIs");
     }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri Dec 11 23:38:55 2015
@@ -1184,21 +1184,7 @@ void SelectionDAGBuilder::visitCatchPad(
   if (IsMSVCCXX || IsCoreCLR)
     CatchPadMBB->setIsEHFuncletEntry();
 
-  MachineBasicBlock *NormalDestMBB = FuncInfo.MBBMap[I.getNormalDest()];
-
-  // Update machine-CFG edge.
-  FuncInfo.MBB->addSuccessor(NormalDestMBB);
-
-  SDValue Chain =
-      DAG.getNode(ISD::CATCHPAD, getCurSDLoc(), MVT::Other, getControlRoot());
-
-  // If this is not a fall-through branch or optimizations are switched off,
-  // emit the branch.
-  if (NormalDestMBB != NextBlock(CatchPadMBB) ||
-      TM.getOptLevel() == CodeGenOpt::None)
-    Chain = DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other, Chain,
-                        DAG.getBasicBlock(NormalDestMBB));
-  DAG.setRoot(Chain);
+  DAG.setRoot(DAG.getNode(ISD::CATCHPAD, getCurSDLoc(), MVT::Other, getControlRoot()));
 }
 
 void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) {
@@ -1234,10 +1220,6 @@ void SelectionDAGBuilder::visitCatchRet(
   DAG.setRoot(Ret);
 }
 
-void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) {
-  llvm_unreachable("should never codegen catchendpads");
-}
-
 void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) {
   // Don't emit any special code for the cleanuppad instruction. It just marks
   // the start of a funclet.
@@ -1248,8 +1230,8 @@ void SelectionDAGBuilder::visitCleanupPa
 /// When an invoke or a cleanupret unwinds to the next EH pad, there are
 /// many places it could ultimately go. In the IR, we have a single unwind
 /// destination, but in the machine CFG, we enumerate all the possible blocks.
-/// This function skips over imaginary basic blocks that hold catchpad,
-/// terminatepad, or catchendpad instructions, and finds all the "real" machine
+/// This function skips over imaginary basic blocks that hold catchswitch or
+/// terminatepad instructions, and finds all the "real" machine
 /// basic block destinations. As those destinations may not be successors of
 /// EHPadBB, here we also calculate the edge probability to those destinations.
 /// The passed-in Prob is the edge probability to EHPadBB.
@@ -1276,19 +1258,18 @@ static void findUnwindDestinations(
       UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Prob);
       UnwindDests.back().first->setIsEHFuncletEntry();
       break;
-    } else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
-      // Add the catchpad handler to the possible destinations.
-      UnwindDests.emplace_back(FuncInfo.MBBMap[EHPadBB], Prob);
-      // In MSVC C++, catchblocks are funclets and need prologues.
-      if (IsMSVCCXX || IsCoreCLR)
-        UnwindDests.back().first->setIsEHFuncletEntry();
-      NewEHPadBB = CPI->getUnwindDest();
-    } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad))
-      NewEHPadBB = CEPI->getUnwindDest();
-    else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(Pad))
-      NewEHPadBB = CEPI->getUnwindDest();
-    else
+    } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Pad)) {
+      // Add the catchpad handlers to the possible destinations.
+      for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
+        UnwindDests.emplace_back(FuncInfo.MBBMap[CatchPadBB], Prob);
+        // For MSVC++ and the CLR, catchblocks are funclets and need prologues.
+        if (IsMSVCCXX || IsCoreCLR)
+          UnwindDests.back().first->setIsEHFuncletEntry();
+      }
+      NewEHPadBB = CatchSwitch->getUnwindDest();
+    } else {
       continue;
+    }
 
     BranchProbabilityInfo *BPI = FuncInfo.BPI;
     if (BPI && NewEHPadBB)
@@ -1319,14 +1300,14 @@ void SelectionDAGBuilder::visitCleanupRe
   DAG.setRoot(Ret);
 }
 
-void SelectionDAGBuilder::visitCleanupEndPad(const CleanupEndPadInst &I) {
-  report_fatal_error("visitCleanupEndPad not yet implemented!");
-}
-
 void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) {
   report_fatal_error("visitTerminatePad not yet implemented!");
 }
 
+void SelectionDAGBuilder::visitCatchSwitch(const CatchSwitchInst &CSI) {
+  report_fatal_error("visitCatchSwitch not yet implemented!");
+}
+
 void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
   auto &DL = DAG.getDataLayout();
@@ -2124,8 +2105,8 @@ void SelectionDAGBuilder::visitBitTestCa
 void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
   MachineBasicBlock *InvokeMBB = FuncInfo.MBB;
 
-  // Retrieve successors. Look through artificial IR level blocks like catchpads
-  // and catchendpads for successors.
+  // Retrieve successors. Look through artificial IR level blocks like
+  // catchswitch for successors.
   MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
   const BasicBlock *EHPadBB = I.getSuccessor(1);
 
@@ -5367,8 +5348,10 @@ SelectionDAGBuilder::lowerInvokable(Targ
 
     // Inform MachineModuleInfo of range.
     if (MMI.hasEHFunclets()) {
+      assert(CLI.CS);
       WinEHFuncInfo *EHInfo = DAG.getMachineFunction().getWinEHFuncInfo();
-      EHInfo->addIPToStateRange(EHPadBB, BeginLabel, EndLabel);
+      EHInfo->addIPToStateRange(cast<InvokeInst>(CLI.CS->getInstruction()),
+                                BeginLabel, EndLabel);
     } else {
       MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel);
     }

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h Fri Dec 11 23:38:55 2015
@@ -736,9 +736,8 @@ private:
   void visitSwitch(const SwitchInst &I);
   void visitIndirectBr(const IndirectBrInst &I);
   void visitUnreachable(const UnreachableInst &I);
-  void visitCleanupEndPad(const CleanupEndPadInst &I);
   void visitCleanupRet(const CleanupReturnInst &I);
-  void visitCatchEndPad(const CatchEndPadInst &I);
+  void visitCatchSwitch(const CatchSwitchInst &I);
   void visitCatchRet(const CatchReturnInst &I);
   void visitCatchPad(const CatchPadInst &I);
   void visitTerminatePad(const TerminatePadInst &TPI);

Modified: llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp Fri Dec 11 23:38:55 2015
@@ -1570,13 +1570,12 @@ int TargetLoweringBase::InstructionOpcod
   case Invoke:         return 0;
   case Resume:         return 0;
   case Unreachable:    return 0;
-  case CleanupEndPad:  return 0;
   case CleanupRet:     return 0;
-  case CatchEndPad:  return 0;
   case CatchRet:       return 0;
-  case CatchPad:     return 0;
-  case TerminatePad: return 0;
-  case CleanupPad:   return 0;
+  case CatchPad:       return 0;
+  case CatchSwitch:    return 0;
+  case TerminatePad:   return 0;
+  case CleanupPad:     return 0;
   case Add:            return ISD::ADD;
   case FAdd:           return ISD::FADD;
   case Sub:            return ISD::SUB;

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Fri Dec 11 23:38:55 2015
@@ -17,7 +17,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/Passes.h"
-#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/Analysis/CFG.h"
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/CodeGen/WinEHFuncInfo.h"
@@ -69,27 +69,12 @@ private:
   AllocaInst *insertPHILoads(PHINode *PN, Function &F);
   void replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot,
                           DenseMap<BasicBlock *, Value *> &Loads, Function &F);
-  bool prepareExplicitEH(Function &F,
-                         SmallVectorImpl<BasicBlock *> &EntryBlocks);
+  bool prepareExplicitEH(Function &F);
   void replaceTerminatePadWithCleanup(Function &F);
-  void colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks);
-  void resolveFuncletAncestry(Function &F,
-                              SmallVectorImpl<BasicBlock *> &EntryBlocks);
-  void resolveFuncletAncestryForPath(
-      Function &F, SmallVectorImpl<BasicBlock *> &FuncletPath,
-      std::map<BasicBlock *, BasicBlock *> &IdentityMap);
-  void makeFuncletEdgeUnreachable(BasicBlock *Parent, BasicBlock *Child);
-  BasicBlock *cloneFuncletForParent(Function &F, BasicBlock *FuncletEntry,
-                                    BasicBlock *Parent);
-  void updateTerminatorsAfterFuncletClone(
-      Function &F, BasicBlock *OrigFunclet, BasicBlock *CloneFunclet,
-      BasicBlock *OrigBlock, BasicBlock *CloneBlock, BasicBlock *CloneParent,
-      ValueToValueMapTy &VMap,
-      std::map<BasicBlock *, BasicBlock *> &Orig2Clone);
+  void colorFunclets(Function &F);
 
   void demotePHIsOnFunclets(Function &F);
-  void cloneCommonBlocks(Function &F,
-                         SmallVectorImpl<BasicBlock *> &EntryBlocks);
+  void cloneCommonBlocks(Function &F);
   void removeImplausibleTerminators(Function &F);
   void cleanupPreparedFunclets(Function &F);
   void verifyPreparedFunclets(Function &F);
@@ -97,20 +82,8 @@ private:
   // All fields are reset by runOnFunction.
   EHPersonality Personality = EHPersonality::Unknown;
 
-  std::map<BasicBlock *, SetVector<BasicBlock *>> BlockColors;
-  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks;
-  std::map<BasicBlock *, std::vector<BasicBlock *>> FuncletChildren;
-  std::map<BasicBlock *, std::vector<BasicBlock *>> FuncletParents;
-
-  // This is a flag that indicates an uncommon situation where we need to
-  // clone funclets has been detected.
-  bool FuncletCloningRequired = false;
-  // When a funclet with multiple parents contains a catchret, the block to
-  // which it returns will be cloned so that there is a copy in each parent
-  // but one of the copies will not be properly linked to the catchret and
-  // in most cases will have no predecessors.  This double map allows us
-  // to find these cloned blocks when we clone the child funclet.
-  std::map<BasicBlock *, std::map<BasicBlock *, BasicBlock*>> EstrangedBlocks;
+  DenseMap<BasicBlock *, ColorVector> BlockColors;
+  MapVector<BasicBlock *, std::vector<BasicBlock *>> FuncletBlocks;
 };
 
 } // end anonymous namespace
@@ -123,21 +96,6 @@ FunctionPass *llvm::createWinEHPass(cons
   return new WinEHPrepare(TM);
 }
 
-static void findFuncletEntryPoints(Function &Fn,
-                                   SmallVectorImpl<BasicBlock *> &EntryBlocks) {
-  EntryBlocks.push_back(&Fn.getEntryBlock());
-  for (BasicBlock &BB : Fn) {
-    Instruction *First = BB.getFirstNonPHI();
-    if (!First->isEHPad())
-      continue;
-    assert(!isa<LandingPadInst>(First) &&
-           "landingpad cannot be used with funclet EH personality");
-    // Find EH pad blocks that represent funclet start points.
-    if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First))
-      EntryBlocks.push_back(&BB);
-  }
-}
-
 bool WinEHPrepare::runOnFunction(Function &Fn) {
   if (!Fn.hasPersonalityFn())
     return false;
@@ -149,14 +107,7 @@ bool WinEHPrepare::runOnFunction(Functio
   if (!isFuncletEHPersonality(Personality))
     return false;
 
-  // Remove unreachable blocks.  It is not valuable to assign them a color and
-  // their existence can trick us into thinking values are alive when they are
-  // not.
-  removeUnreachableBlocks(Fn);
-
-  SmallVector<BasicBlock *, 4> EntryBlocks;
-  findFuncletEntryPoints(Fn, EntryBlocks);
-  return prepareExplicitEH(Fn, EntryBlocks);
+  return prepareExplicitEH(Fn);
 }
 
 bool WinEHPrepare::doFinalization(Module &M) { return false; }
@@ -198,117 +149,142 @@ static void addTryBlockMapEntry(WinEHFun
   FuncInfo.TryBlockMap.push_back(TBME);
 }
 
-static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) {
-  for (const BasicBlock *PredBlock : predecessors(BB))
-    if (auto *CPI = dyn_cast<CatchPadInst>(PredBlock->getFirstNonPHI()))
-      return CPI;
+static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CleanupPad) {
+  for (const User *U : CleanupPad->users())
+    if (const auto *CRI = dyn_cast<CleanupReturnInst>(U))
+      return CRI->getUnwindDest();
   return nullptr;
 }
 
-/// Find all the catchpads that feed directly into the catchendpad. Frontends
-/// using this personality should ensure that each catchendpad and catchpad has
-/// one or zero catchpad predecessors.
-///
-/// The following C++ generates the IR after it:
-///   try {
-///   } catch (A) {
-///   } catch (B) {
-///   }
-///
-/// IR:
-///   %catchpad.A
-///     catchpad [i8* A typeinfo]
-///         to label %catch.A unwind label %catchpad.B
-///   %catchpad.B
-///     catchpad [i8* B typeinfo]
-///         to label %catch.B unwind label %endcatches
-///   %endcatches
-///     catchendblock unwind to caller
-static void
-findCatchPadsForCatchEndPad(const BasicBlock *CatchEndBB,
-                            SmallVectorImpl<const CatchPadInst *> &Handlers) {
-  const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB);
-  while (CPI) {
-    Handlers.push_back(CPI);
-    CPI = getSingleCatchPadPredecessor(CPI->getParent());
-  }
-  // We've pushed these back into reverse source order.  Reverse them to get
-  // the list back into source order.
-  std::reverse(Handlers.begin(), Handlers.end());
+static void calculateStateNumbersForInvokes(const Function *Fn,
+                                            WinEHFuncInfo &FuncInfo) {
+  auto *F = const_cast<Function *>(Fn);
+  DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(*F);
+  for (BasicBlock &BB : *F) {
+    auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
+    if (!II)
+      continue;
+
+    auto &BBColors = BlockColors[&BB];
+    assert(BBColors.size() == 1 &&
+           "multi-color BB not removed by preparation");
+    BasicBlock *FuncletEntryBB = BBColors.front();
+
+    BasicBlock *FuncletUnwindDest;
+    auto *FuncletPad =
+        dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI());
+    assert(FuncletPad || FuncletEntryBB == &Fn->getEntryBlock());
+    if (!FuncletPad)
+      FuncletUnwindDest = nullptr;
+    else if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad))
+      FuncletUnwindDest = CatchPad->getCatchSwitch()->getUnwindDest();
+    else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPad))
+      FuncletUnwindDest = getCleanupRetUnwindDest(CleanupPad);
+    else
+      llvm_unreachable("unexpected funclet pad!");
+
+    BasicBlock *InvokeUnwindDest = II->getUnwindDest();
+    int BaseState = -1;
+    if (FuncletUnwindDest == InvokeUnwindDest) {
+      auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
+      if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
+        BaseState = BaseStateI->second;
+    }
+
+    if (BaseState != -1) {
+      FuncInfo.InvokeStateMap[II] = BaseState;
+    } else {
+      Instruction *PadInst = InvokeUnwindDest->getFirstNonPHI();
+      assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
+      FuncInfo.InvokeStateMap[II] = FuncInfo.EHPadStateMap[PadInst];
+    }
+  }
 }
 
 // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
 // to. If the unwind edge came from an invoke, return null.
-static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
+static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB,
+                                                 Value *ParentPad) {
   const TerminatorInst *TI = BB->getTerminator();
   if (isa<InvokeInst>(TI))
     return nullptr;
-  if (TI->isEHPad())
+  if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
+    if (CatchSwitch->getParentPad() != ParentPad)
+      return nullptr;
     return BB;
-  return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
+  }
+  assert(!TI->isEHPad() && "unexpected EHPad!");
+  auto *CleanupPad = cast<CleanupReturnInst>(TI)->getCleanupPad();
+  if (CleanupPad->getParentPad() != ParentPad)
+    return nullptr;
+  return CleanupPad->getParent();
 }
 
-static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
-                                             const BasicBlock &BB,
-                                             int ParentState) {
-  assert(BB.isEHPad());
-  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-  // All catchpad instructions will be handled when we process their
-  // respective catchendpad instruction.
-  if (isa<CatchPadInst>(FirstNonPHI))
-    return;
+static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo,
+                                     const Instruction *FirstNonPHI,
+                                     int ParentState) {
+  const BasicBlock *BB = FirstNonPHI->getParent();
+  assert(BB->isEHPad() && "not a funclet!");
+
+  if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
+    assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
+           "shouldn't revist catch funclets!");
 
-  if (isa<CatchEndPadInst>(FirstNonPHI)) {
     SmallVector<const CatchPadInst *, 2> Handlers;
-    findCatchPadsForCatchEndPad(&BB, Handlers);
-    const BasicBlock *FirstTryPad = Handlers.front()->getParent();
+    for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
+      auto *CatchPad = cast<CatchPadInst>(CatchPadBB->getFirstNonPHI());
+      Handlers.push_back(CatchPad);
+    }
     int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
-    FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
-    for (const BasicBlock *PredBlock : predecessors(FirstTryPad))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow);
+    FuncInfo.EHPadStateMap[CatchSwitch] = TryLow;
+    for (const BasicBlock *PredBlock : predecessors(BB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock,
+                                               CatchSwitch->getParentPad())))
+        calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
+                                 TryLow);
     int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
 
     // catchpads are separate funclets in C++ EH due to the way rethrow works.
-    // In SEH, they aren't, so no invokes will unwind to the catchendpad.
-    FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
     int TryHigh = CatchLow - 1;
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow);
+    for (const auto *CatchPad : Handlers) {
+      FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
+      for (const User *U : CatchPad->users()) {
+        const auto *UserI = cast<Instruction>(U);
+        if (UserI->isEHPad())
+          calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
+      }
+    }
     int CatchHigh = FuncInfo.getLastStateNumber();
     addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
-    DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow
+    DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n');
+    DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh << '\n');
+    DEBUG(dbgs() << "CatchHigh[" << BB->getName() << "]: " << CatchHigh
                  << '\n');
-    DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh
-                 << '\n');
-    DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
-                 << '\n');
-  } else if (isa<CleanupPadInst>(FirstNonPHI)) {
-    // A cleanup can have multiple exits; don't re-process after the first.
-    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+  } else {
+    auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
+
+    // It's possible for a cleanup to be visited twice: it might have multiple
+    // cleanupret instructions.
+    if (FuncInfo.EHPadStateMap.count(CleanupPad))
       return;
-    int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
-    FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
+
+    int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, BB);
+    FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
-                 << BB.getName() << '\n');
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
-  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
-    // Propagate ParentState to the cleanuppad in case it doesn't have
-    // any cleanuprets.
-    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
-    calculateExplicitCXXStateNumbers(FuncInfo, *CleanupBlock, ParentState);
-    // Anything unwinding through CleanupEndPadInst is in ParentState.
-    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, ParentState);
-  } else if (isa<TerminatePadInst>(FirstNonPHI)) {
-    report_fatal_error("Not yet implemented!");
-  } else {
-    llvm_unreachable("unexpected EH Pad!");
+                 << BB->getName() << '\n');
+    for (const BasicBlock *PredBlock : predecessors(BB)) {
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock,
+                                               CleanupPad->getParentPad()))) {
+        calculateCXXStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
+                                 CleanupState);
+      }
+    }
+    for (const User *U : CleanupPad->users()) {
+      const auto *UserI = cast<Instruction>(U);
+      if (UserI->isEHPad())
+        report_fatal_error("Cleanup funclets for the MSVC++ personality cannot "
+                           "contain exceptional actions");
+    }
   }
 }
 
@@ -334,94 +310,84 @@ static int addSEHFinally(WinEHFuncInfo &
   return FuncInfo.SEHUnwindMap.size() - 1;
 }
 
-static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
-                                             const BasicBlock &BB,
-                                             int ParentState) {
-  assert(BB.isEHPad());
-  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-  // All catchpad instructions will be handled when we process their
-  // respective catchendpad instruction.
-  if (isa<CatchPadInst>(FirstNonPHI))
-    return;
+static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo,
+                                     const Instruction *FirstNonPHI,
+                                     int ParentState) {
+  const BasicBlock *BB = FirstNonPHI->getParent();
+  assert(BB->isEHPad() && "no a funclet!");
+
+  if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FirstNonPHI)) {
+    assert(FuncInfo.EHPadStateMap.count(CatchSwitch) == 0 &&
+           "shouldn't revist catch funclets!");
 
-  if (isa<CatchEndPadInst>(FirstNonPHI)) {
     // Extract the filter function and the __except basic block and create a
     // state for them.
-    SmallVector<const CatchPadInst *, 1> Handlers;
-    findCatchPadsForCatchEndPad(&BB, Handlers);
-    assert(Handlers.size() == 1 &&
+    assert(CatchSwitch->getNumHandlers() == 1 &&
            "SEH doesn't have multiple handlers per __try");
-    const CatchPadInst *CPI = Handlers.front();
-    const BasicBlock *CatchPadBB = CPI->getParent();
+    const auto *CatchPad =
+        cast<CatchPadInst>((*CatchSwitch->handler_begin())->getFirstNonPHI());
+    const BasicBlock *CatchPadBB = CatchPad->getParent();
     const Constant *FilterOrNull =
-        cast<Constant>(CPI->getArgOperand(0)->stripPointerCasts());
+        cast<Constant>(CatchPad->getArgOperand(0)->stripPointerCasts());
     const Function *Filter = dyn_cast<Function>(FilterOrNull);
     assert((Filter || FilterOrNull->isNullValue()) &&
            "unexpected filter value");
     int TryState = addSEHExcept(FuncInfo, ParentState, Filter, CatchPadBB);
 
     // Everything in the __try block uses TryState as its parent state.
-    FuncInfo.EHPadStateMap[CPI] = TryState;
+    FuncInfo.EHPadStateMap[CatchSwitch] = TryState;
     DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
                  << CatchPadBB->getName() << '\n');
-    for (const BasicBlock *PredBlock : predecessors(CatchPadBB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState);
+    for (const BasicBlock *PredBlock : predecessors(BB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock,
+                                               CatchSwitch->getParentPad())))
+        calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
+                                 TryState);
 
     // Everything in the __except block unwinds to ParentState, just like code
     // outside the __try.
-    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
-    DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
-                 << BB.getName() << '\n');
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
-  } else if (isa<CleanupPadInst>(FirstNonPHI)) {
-    // A cleanup can have multiple exits; don't re-process after the first.
-    if (FuncInfo.EHPadStateMap.count(FirstNonPHI))
+    for (const User *U : CatchPad->users()) {
+      const auto *UserI = cast<Instruction>(U);
+      if (UserI->isEHPad()) {
+        calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
+      }
+    }
+  } else {
+    auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
+
+    // It's possible for a cleanup to be visited twice: it might have multiple
+    // cleanupret instructions.
+    if (FuncInfo.EHPadStateMap.count(CleanupPad))
       return;
-    int CleanupState = addSEHFinally(FuncInfo, ParentState, &BB);
-    FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
+
+    int CleanupState = addSEHFinally(FuncInfo, ParentState, BB);
+    FuncInfo.EHPadStateMap[CleanupPad] = CleanupState;
     DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
-                 << BB.getName() << '\n');
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
-  } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(FirstNonPHI)) {
-    // Propagate ParentState to the cleanuppad in case it doesn't have
-    // any cleanuprets.
-    BasicBlock *CleanupBlock = CEPI->getCleanupPad()->getParent();
-    calculateExplicitSEHStateNumbers(FuncInfo, *CleanupBlock, ParentState);
-    // Anything unwinding through CleanupEndPadInst is in ParentState.
-    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
-    DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
-                 << BB.getName() << '\n');
-    for (const BasicBlock *PredBlock : predecessors(&BB))
-      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
-  } else if (isa<TerminatePadInst>(FirstNonPHI)) {
-    report_fatal_error("Not yet implemented!");
-  } else {
-    llvm_unreachable("unexpected EH Pad!");
+                 << BB->getName() << '\n');
+    for (const BasicBlock *PredBlock : predecessors(BB))
+      if ((PredBlock =
+               getEHPadFromPredecessor(PredBlock, CleanupPad->getParentPad())))
+        calculateSEHStateNumbers(FuncInfo, PredBlock->getFirstNonPHI(),
+                                 CleanupState);
+    for (const User *U : CleanupPad->users()) {
+      const auto *UserI = cast<Instruction>(U);
+      if (UserI->isEHPad())
+        report_fatal_error("Cleanup funclets for the SEH personality cannot "
+                           "contain exceptional actions");
+    }
   }
 }
 
-/// Check if the EH Pad unwinds to caller.  Cleanups are a little bit of a
-/// special case because we have to look at the cleanupret instruction that uses
-/// the cleanuppad.
-static bool doesEHPadUnwindToCaller(const Instruction *EHPad) {
-  auto *CPI = dyn_cast<CleanupPadInst>(EHPad);
-  if (!CPI)
-    return EHPad->mayThrow();
-
-  // This cleanup does not return or unwind, so we say it unwinds to caller.
-  if (CPI->use_empty())
-    return true;
-
-  const Instruction *User = CPI->user_back();
-  if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
-    return CRI->unwindsToCaller();
-  return cast<CleanupEndPadInst>(User)->unwindsToCaller();
+static bool isTopLevelPadForMSVC(const Instruction *EHPad) {
+  if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(EHPad))
+    return isa<ConstantTokenNone>(CatchSwitch->getParentPad()) &&
+           CatchSwitch->unwindsToCaller();
+  if (auto *CleanupPad = dyn_cast<CleanupPadInst>(EHPad))
+    return isa<ConstantTokenNone>(CleanupPad->getParentPad()) &&
+           getCleanupRetUnwindDest(CleanupPad) == nullptr;
+  if (isa<CatchPadInst>(EHPad))
+    return false;
+  llvm_unreachable("unexpected EHPad!");
 }
 
 void llvm::calculateSEHStateNumbers(const Function *Fn,
@@ -431,10 +397,15 @@ void llvm::calculateSEHStateNumbers(cons
     return;
 
   for (const BasicBlock &BB : *Fn) {
-    if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI()))
+    if (!BB.isEHPad())
+      continue;
+    const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+    if (!isTopLevelPadForMSVC(FirstNonPHI))
       continue;
-    calculateExplicitSEHStateNumbers(FuncInfo, BB, -1);
+    ::calculateSEHStateNumbers(FuncInfo, FirstNonPHI, -1);
   }
+
+  calculateStateNumbersForInvokes(Fn, FuncInfo);
 }
 
 void llvm::calculateWinCXXEHStateNumbers(const Function *Fn,
@@ -446,13 +417,13 @@ void llvm::calculateWinCXXEHStateNumbers
   for (const BasicBlock &BB : *Fn) {
     if (!BB.isEHPad())
       continue;
-    if (BB.isLandingPad())
-      report_fatal_error("MSVC C++ EH cannot use landingpads");
     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-    if (!doesEHPadUnwindToCaller(FirstNonPHI))
+    if (!isTopLevelPadForMSVC(FirstNonPHI))
       continue;
-    calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
+    calculateCXXStateNumbers(FuncInfo, FirstNonPHI, -1);
   }
+
+  calculateStateNumbersForInvokes(Fn, FuncInfo);
 }
 
 static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
@@ -483,7 +454,7 @@ void llvm::calculateClrEHStateNumbers(co
     if (BB.isLandingPad())
       report_fatal_error("CoreCLR EH cannot use landingpads");
     const Instruction *FirstNonPHI = BB.getFirstNonPHI();
-    if (!doesEHPadUnwindToCaller(FirstNonPHI))
+    if (!isTopLevelPadForMSVC(FirstNonPHI))
       continue;
     // queue this with sentinel parent state -1 to mean unwind to caller.
     Worklist.emplace_back(FirstNonPHI, -1);
@@ -494,16 +465,11 @@ void llvm::calculateClrEHStateNumbers(co
     int ParentState;
     std::tie(Pad, ParentState) = Worklist.pop_back_val();
 
+    Value *ParentPad;
     int PredState;
-    if (const CleanupEndPadInst *EndPad = dyn_cast<CleanupEndPadInst>(Pad)) {
-      FuncInfo.EHPadStateMap[EndPad] = ParentState;
-      // Queue the cleanuppad, in case it doesn't have a cleanupret.
-      Worklist.emplace_back(EndPad->getCleanupPad(), ParentState);
-      // Preds of the endpad should get the parent state.
-      PredState = ParentState;
-    } else if (const CleanupPadInst *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
+    if (const CleanupPadInst *Cleanup = dyn_cast<CleanupPadInst>(Pad)) {
       // A cleanup can have multiple exits; don't re-process after the first.
-      if (FuncInfo.EHPadStateMap.count(Pad))
+      if (FuncInfo.EHPadStateMap.count(Cleanup))
         continue;
       // CoreCLR personality uses arity to distinguish faults from finallies.
       const BasicBlock *PadBlock = Cleanup->getParent();
@@ -514,30 +480,47 @@ void llvm::calculateClrEHStateNumbers(co
           addClrEHHandler(FuncInfo, ParentState, HandlerType, 0, PadBlock);
       FuncInfo.EHPadStateMap[Cleanup] = NewState;
       // Propagate the new state to all preds of the cleanup
+      ParentPad = Cleanup->getParentPad();
       PredState = NewState;
-    } else if (const CatchEndPadInst *EndPad = dyn_cast<CatchEndPadInst>(Pad)) {
-      FuncInfo.EHPadStateMap[EndPad] = ParentState;
-      // Preds of the endpad should get the parent state.
-      PredState = ParentState;
-    } else if (const CatchPadInst *Catch = dyn_cast<CatchPadInst>(Pad)) {
-      const BasicBlock *PadBlock = Catch->getParent();
-      uint32_t TypeToken = static_cast<uint32_t>(
-          cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
-      int NewState = addClrEHHandler(FuncInfo, ParentState,
-                                     ClrHandlerType::Catch, TypeToken, PadBlock);
-      FuncInfo.EHPadStateMap[Catch] = NewState;
-      // Preds of the catch get its state
+    } else if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(Pad)) {
+      SmallVector<const CatchPadInst *, 1> Handlers;
+      for (const BasicBlock *CatchPadBB : CatchSwitch->handlers()) {
+        const auto *Catch = cast<CatchPadInst>(CatchPadBB->getFirstNonPHI());
+        Handlers.push_back(Catch);
+      }
+      FuncInfo.EHPadStateMap[CatchSwitch] = ParentState;
+      int NewState = ParentState;
+      for (auto HandlerI = Handlers.rbegin(), HandlerE = Handlers.rend();
+           HandlerI != HandlerE; ++HandlerI) {
+        const CatchPadInst *Catch = *HandlerI;
+        const BasicBlock *PadBlock = Catch->getParent();
+        uint32_t TypeToken = static_cast<uint32_t>(
+            cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue());
+        NewState = addClrEHHandler(FuncInfo, NewState, ClrHandlerType::Catch,
+                                   TypeToken, PadBlock);
+        FuncInfo.EHPadStateMap[Catch] = NewState;
+      }
+      for (const auto *CatchPad : Handlers) {
+        for (const User *U : CatchPad->users()) {
+          const auto *UserI = cast<Instruction>(U);
+          if (UserI->isEHPad())
+            Worklist.emplace_back(UserI, ParentState);
+        }
+      }
       PredState = NewState;
+      ParentPad = CatchSwitch->getParentPad();
     } else {
       llvm_unreachable("Unexpected EH pad");
     }
 
     // Queue all predecessors with the given state
     for (const BasicBlock *Pred : predecessors(Pad->getParent())) {
-      if ((Pred = getEHPadFromPredecessor(Pred)))
+      if ((Pred = getEHPadFromPredecessor(Pred, ParentPad)))
         Worklist.emplace_back(Pred->getFirstNonPHI(), PredState);
     }
   }
+
+  calculateStateNumbersForInvokes(Fn, FuncInfo);
 }
 
 void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) {
@@ -559,8 +542,9 @@ void WinEHPrepare::replaceTerminatePadWi
                          "C++ personalities!");
 
     // Insert the cleanuppad instruction.
-    auto *CPI = CleanupPadInst::Create(
-        BB.getContext(), {}, Twine("terminatepad.for.", BB.getName()), &BB);
+    auto *CPI =
+        CleanupPadInst::Create(TPI->getParentPad(), {},
+                               Twine("terminatepad.for.", BB.getName()), &BB);
 
     // Insert the call to the terminate instruction.
     auto *CallTerminate = CallInst::Create(TerminateFn, {}, &BB);
@@ -578,980 +562,32 @@ void WinEHPrepare::replaceTerminatePadWi
   }
 }
 
-static void
-colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks,
-              std::map<BasicBlock *, SetVector<BasicBlock *>> &BlockColors,
-              std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletBlocks) {
-  SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
-  BasicBlock *EntryBlock = &F.getEntryBlock();
-
-  // Build up the color map, which maps each block to its set of 'colors'.
-  // For any block B, the "colors" of B are the set of funclets F (possibly
-  // including a root "funclet" representing the main function), such that
-  // F will need to directly contain B or a copy of B (where the term "directly
-  // contain" is used to distinguish from being "transitively contained" in
-  // a nested funclet).
-  // Use a CFG walk driven by a worklist of (block, color) pairs.  The "color"
-  // sets attached during this processing to a block which is the entry of some
-  // funclet F is actually the set of F's parents -- i.e. the union of colors
-  // of all predecessors of F's entry.  For all other blocks, the color sets
-  // are as defined above.  A post-pass fixes up the block color map to reflect
-  // the same sense of "color" for funclet entries as for other blocks.
-
-  DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for "
-                                                  << F.getName() << "\n");
-
-  Worklist.push_back({EntryBlock, EntryBlock});
-
-  while (!Worklist.empty()) {
-    BasicBlock *Visiting;
-    BasicBlock *Color;
-    std::tie(Visiting, Color) = Worklist.pop_back_val();
-    DEBUG_WITH_TYPE("winehprepare-coloring",
-                    dbgs() << "Visiting " << Visiting->getName() << ", "
-                           << Color->getName() << "\n");
-    Instruction *VisitingHead = Visiting->getFirstNonPHI();
-    if (VisitingHead->isEHPad() && !isa<CatchEndPadInst>(VisitingHead) &&
-        !isa<CleanupEndPadInst>(VisitingHead)) {
-      // Mark this as a funclet head as a member of itself.
-      FuncletBlocks[Visiting].insert(Visiting);
-      // Queue exits (i.e. successors of rets/endpads) with the parent color.
-      // Skip any exits that are catchendpads, since the parent color must then
-      // represent one of the catches chained to that catchendpad, but the
-      // catchendpad should get the color of the common parent of all its
-      // chained catches (i.e. the grandparent color of the current pad).
-      // We don't need to worry abou catchendpads going unvisited, since the
-      // catches chained to them must have unwind edges to them by which we will
-      // visit them.
-      for (User *U : VisitingHead->users()) {
-        if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
-          for (BasicBlock *Succ : successors(Exit->getParent()))
-            if (!isa<CatchEndPadInst>(*Succ->getFirstNonPHI()))
-              if (BlockColors[Succ].insert(Color)) {
-                DEBUG_WITH_TYPE("winehprepare-coloring",
-                                dbgs() << "  Assigned color \'"
-                                       << Color->getName() << "\' to block \'"
-                                       << Succ->getName() << "\'.\n");
-                Worklist.push_back({Succ, Color});
-              }
-        }
-      }
-      // Handle CatchPad specially since its successors need different colors.
-      if (CatchPadInst *CatchPad = dyn_cast<CatchPadInst>(VisitingHead)) {
-        // Visit the normal successor with the color of the new EH pad, and
-        // visit the unwind successor with the color of the parent.
-        BasicBlock *NormalSucc = CatchPad->getNormalDest();
-        if (BlockColors[NormalSucc].insert(Visiting)) {
-          DEBUG_WITH_TYPE("winehprepare-coloring",
-                          dbgs() << "  Assigned color \'" << Visiting->getName()
-                                 << "\' to block \'" << NormalSucc->getName()
-                                 << "\'.\n");
-          Worklist.push_back({NormalSucc, Visiting});
-        }
-        BasicBlock *UnwindSucc = CatchPad->getUnwindDest();
-        if (BlockColors[UnwindSucc].insert(Color)) {
-          DEBUG_WITH_TYPE("winehprepare-coloring",
-                          dbgs() << "  Assigned color \'" << Color->getName()
-                                 << "\' to block \'" << UnwindSucc->getName()
-                                 << "\'.\n");
-          Worklist.push_back({UnwindSucc, Color});
-        }
-        continue;
-      }
-      // Switch color to the current node, except for terminate pads which
-      // have no bodies and only unwind successors and so need their successors
-      // visited with the color of the parent.
-      if (!isa<TerminatePadInst>(VisitingHead))
-        Color = Visiting;
-    } else {
-      // Note that this is a member of the given color.
-      FuncletBlocks[Color].insert(Visiting);
-    }
-
-    TerminatorInst *Terminator = Visiting->getTerminator();
-    if (isa<CleanupReturnInst>(Terminator) ||
-        isa<CatchReturnInst>(Terminator) ||
-        isa<CleanupEndPadInst>(Terminator)) {
-      // These blocks' successors have already been queued with the parent
-      // color.
-      continue;
-    }
-    for (BasicBlock *Succ : successors(Visiting)) {
-      if (isa<CatchEndPadInst>(Succ->getFirstNonPHI())) {
-        // The catchendpad needs to be visited with the parent's color, not
-        // the current color.  This will happen in the code above that visits
-        // any catchpad unwind successor with the parent color, so we can
-        // safely skip this successor here.
-        continue;
-      }
-      if (BlockColors[Succ].insert(Color)) {
-        DEBUG_WITH_TYPE("winehprepare-coloring",
-                        dbgs() << "  Assigned color \'" << Color->getName()
-                               << "\' to block \'" << Succ->getName()
-                               << "\'.\n");
-        Worklist.push_back({Succ, Color});
-      }
-    }
-  }
-}
-
-static BasicBlock *getEndPadForCatch(CatchPadInst *Catch) {
-  // The catch may have sibling catches.  Follow the unwind chain until we get
-  // to the catchendpad.
-  BasicBlock *NextUnwindDest = Catch->getUnwindDest();
-  auto *UnwindTerminator = NextUnwindDest->getTerminator();
-  while (auto *NextCatch = dyn_cast<CatchPadInst>(UnwindTerminator)) {
-    NextUnwindDest = NextCatch->getUnwindDest();
-    UnwindTerminator = NextUnwindDest->getTerminator();
-  }
-  // The last catch in the chain must unwind to a catchendpad.
-  assert(isa<CatchEndPadInst>(UnwindTerminator));
-  return NextUnwindDest;
-}
-
-static void updateClonedEHPadUnwindToParent(
-    BasicBlock *UnwindDest, BasicBlock *OrigBlock, BasicBlock *CloneBlock,
-    std::vector<BasicBlock *> &OrigParents, BasicBlock *CloneParent) {
-  auto updateUnwindTerminator = [](BasicBlock *BB) {
-    auto *Terminator = BB->getTerminator();
-    if (isa<CatchEndPadInst>(Terminator) ||
-        isa<CleanupEndPadInst>(Terminator)) {
-      removeUnwindEdge(BB);
-    } else {
-      // If the block we're updating has a cleanupendpad or cleanupret
-      // terminator, we just want to replace that terminator with an
-      // unreachable instruction.
-      assert(isa<CleanupEndPadInst>(Terminator) ||
-             isa<CleanupReturnInst>(Terminator));
-      // Loop over all of the successors, removing the block's entry from any
-      // PHI nodes.
-      for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
-        (*SI)->removePredecessor(BB);
-      // Remove the terminator and replace it with an unreachable instruction.
-      BB->getTerminator()->eraseFromParent();
-      new UnreachableInst(BB->getContext(), BB);
-    }
-  };
-
-  assert(UnwindDest->isEHPad());
-  // There are many places to which this EH terminator can unwind and each has
-  // slightly different rules for whether or not it fits with the given
-  // location.
-  auto *EHPadInst = UnwindDest->getFirstNonPHI();
-  if (isa<CatchEndPadInst>(EHPadInst)) {
-    auto *CloneParentCatch =
-        dyn_cast<CatchPadInst>(CloneParent->getFirstNonPHI());
-    if (!CloneParentCatch ||
-        getEndPadForCatch(CloneParentCatch) != UnwindDest) {
-      DEBUG_WITH_TYPE(
-          "winehprepare-coloring",
-          dbgs() << "      removing unwind destination of clone block \'"
-                 << CloneBlock->getName() << "\'.\n");
-      updateUnwindTerminator(CloneBlock);
-    }
-    // It's possible that the catch end pad is a legal match for both the clone
-    // and the original, so they must be checked separately.  If the original
-    // funclet will still have multiple parents after the current clone parent
-    // is removed, we'll leave its unwind terminator until later.
-    assert(OrigParents.size() >= 2);
-    if (OrigParents.size() != 2)
-      return;
-
-    // If the original funclet will have a single parent after the clone parent
-    // is removed, check that parent's unwind destination.
-    assert(OrigParents.front() == CloneParent ||
-           OrigParents.back() == CloneParent);
-    BasicBlock *OrigParent;
-    if (OrigParents.front() == CloneParent)
-      OrigParent = OrigParents.back();
-    else
-      OrigParent = OrigParents.front();
-
-    auto *OrigParentCatch =
-        dyn_cast<CatchPadInst>(OrigParent->getFirstNonPHI());
-    if (!OrigParentCatch || getEndPadForCatch(OrigParentCatch) != UnwindDest) {
-      DEBUG_WITH_TYPE(
-          "winehprepare-coloring",
-          dbgs() << "      removing unwind destination of original block \'"
-                 << OrigBlock << "\'.\n");
-      updateUnwindTerminator(OrigBlock);
-    }
-  } else if (auto *CleanupEnd = dyn_cast<CleanupEndPadInst>(EHPadInst)) {
-    // If the EH terminator unwinds to a cleanupendpad, that cleanupendpad
-    // must be ending a cleanuppad of either our clone parent or one
-    // one of the parents of the original funclet.
-    auto *CloneParentCP =
-        dyn_cast<CleanupPadInst>(CloneParent->getFirstNonPHI());
-    auto *EndedCP = CleanupEnd->getCleanupPad();
-    if (EndedCP == CloneParentCP) {
-      // If it is ending the cleanuppad of our cloned parent, then we
-      // want to remove the unwind destination of the EH terminator that
-      // we associated with the original funclet.
-      assert(isa<CatchEndPadInst>(OrigBlock->getFirstNonPHI()));
-      DEBUG_WITH_TYPE(
-          "winehprepare-coloring",
-          dbgs() << "      removing unwind destination of original block \'"
-                 << OrigBlock->getName() << "\'.\n");
-      updateUnwindTerminator(OrigBlock);
-    } else {
-      // If it isn't ending the cleanuppad of our clone parent, then we
-      // want to remove the unwind destination of the EH terminator that
-      // associated with our cloned funclet.
-      assert(isa<CatchEndPadInst>(CloneBlock->getFirstNonPHI()));
-      DEBUG_WITH_TYPE(
-          "winehprepare-coloring",
-          dbgs() << "      removing unwind destination of clone block \'"
-                 << CloneBlock->getName() << "\'.\n");
-      updateUnwindTerminator(CloneBlock);
-    }
-  } else {
-    // If the EH terminator unwinds to a catchpad, cleanuppad or
-    // terminatepad that EH pad must be a sibling of the funclet we're
-    // cloning.  We'll clone it later and update one of the catchendpad
-    // instrunctions that unwinds to it at that time.
-    assert(isa<CatchPadInst>(EHPadInst) || isa<CleanupPadInst>(EHPadInst) ||
-           isa<TerminatePadInst>(EHPadInst));
-  }
-}
-
-// If the terminator is a catchpad, we must also clone the catchendpad to which
-// it unwinds and add this to the clone parent's block list.  The catchendpad
-// unwinds to either its caller, a sibling EH pad, a cleanup end pad in its
-// parent funclet or a catch end pad in its grandparent funclet (which must be
-// coupled with the parent funclet).  If it has no unwind destination
-// (i.e. unwind to caller), there is nothing to be done. If the unwind
-// destination is a sibling EH pad, we will update the terminators later (in
-// resolveFuncletAncestryForPath).  If it unwinds to a cleanup end pad or a
-// catch end pad and this end pad corresponds to the clone parent, we will
-// remove the unwind destination in the original catchendpad. If it unwinds to
-// a cleanup end pad or a catch end pad that does not correspond to the clone
-// parent, we will remove the unwind destination in the cloned catchendpad.
-static void updateCatchTerminators(
-    Function &F, CatchPadInst *OrigCatch, CatchPadInst *CloneCatch,
-    std::vector<BasicBlock *> &OrigParents, BasicBlock *CloneParent,
-    ValueToValueMapTy &VMap,
-    std::map<BasicBlock *, SetVector<BasicBlock *>> &BlockColors,
-    std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletBlocks) {
-  // If we're cloning a catch pad that unwinds to a catchendpad, we also
-  // need to clone the catchendpad.  The coloring algorithm associates
-  // the catchendpad block with the funclet's parent, so we have some work
-  // to do here to figure out whether the original belongs to the clone
-  // parent or one of the original funclets other parents (it might have
-  // more than one at this point).  In either case, we might also need to
-  // remove the unwind edge if the catchendpad doesn't unwind to a block
-  // in the right grandparent funclet.
-  Instruction *I = CloneCatch->getUnwindDest()->getFirstNonPHI();
-  if (auto *CEP = dyn_cast<CatchEndPadInst>(I)) {
-    assert(BlockColors[CEP->getParent()].size() == 1);
-    BasicBlock *CEPFunclet = *(BlockColors[CEP->getParent()].begin());
-    BasicBlock *CEPCloneParent = nullptr;
-    CatchPadInst *PredCatch = nullptr;
-    if (CEPFunclet == CloneParent) {
-      // The catchendpad is in the clone parent, so we need to clone it
-      // and associate the clone with the original funclet's parent.  If
-      // the original funclet had multiple parents, we'll add it to the
-      // first parent that isn't the clone parent.  The logic in
-      // updateClonedEHPadUnwindToParent() will only remove the unwind edge
-      // if there is only one parent other than the clone parent, so we don't
-      // need to verify the ancestry.  The catchendpad will eventually be
-      // cloned into the correct parent and all invalid unwind edges will be
-      // removed.
-      for (auto *Parent : OrigParents) {
-        if (Parent != CloneParent) {
-          CEPCloneParent = Parent;
-          break;
-        }
-      }
-      PredCatch = OrigCatch;
-    } else {
-      CEPCloneParent = CloneParent;
-      PredCatch = CloneCatch;
-    }
-    assert(CEPCloneParent && PredCatch);
-    DEBUG_WITH_TYPE("winehprepare-coloring",
-                    dbgs() << "  Cloning catchendpad \'"
-                           << CEP->getParent()->getName() << "\' for funclet \'"
-                           << CEPCloneParent->getName() << "\'.\n");
-    BasicBlock *ClonedCEP = CloneBasicBlock(
-        CEP->getParent(), VMap, Twine(".from.", CEPCloneParent->getName()));
-    // Insert the clone immediately after the original to ensure determinism
-    // and to keep the same relative ordering of any funclet's blocks.
-    ClonedCEP->insertInto(&F, CEP->getParent()->getNextNode());
-    PredCatch->setUnwindDest(ClonedCEP);
-    FuncletBlocks[CEPCloneParent].insert(ClonedCEP);
-    BlockColors[ClonedCEP].insert(CEPCloneParent);
-    DEBUG_WITH_TYPE("winehprepare-coloring",
-                    dbgs() << "    Assigning color \'"
-                           << CEPCloneParent->getName() << "\' to block \'"
-                           << ClonedCEP->getName() << "\'.\n");
-    auto *ClonedCEPInst = cast<CatchEndPadInst>(ClonedCEP->getTerminator());
-    if (auto *Dest = ClonedCEPInst->getUnwindDest())
-      updateClonedEHPadUnwindToParent(Dest, OrigCatch->getUnwindDest(),
-                                      CloneCatch->getUnwindDest(), OrigParents,
-                                      CloneParent);
-  }
-}
-
-// While we are cloning a funclet because it has multiple parents, we will call
-// this routine to update the terminators for the original and cloned copies
-// of each basic block.  All blocks in the funclet have been clone by this time.
-// OrigBlock and CloneBlock will be identical except for their block label.
-//
-// If the terminator is a catchpad, we must also clone the catchendpad to which
-// it unwinds and in most cases update either the original catchendpad or the
-// clone.  See the updateCatchTerminators() helper routine for details.
-//
-// If the terminator is a catchret its successor is a block in its parent
-// funclet.  If the instruction returns to a block in the parent for which the
-// cloned funclet was created, the terminator in the original block must be
-// replaced by an unreachable instruction.  Otherwise the terminator in the
-// clone block must be replaced by an unreachable instruction.
-//
-// If the terminator is a cleanupret or cleanupendpad it either unwinds to
-// caller or unwinds to a sibling EH pad, a cleanup end pad in its parent
-// funclet or a catch end pad in its grandparent funclet (which must be
-// coupled with the parent funclet).  If it unwinds to caller there is
-// nothing to be done. If the unwind destination is a sibling EH pad, we will
-// update the terminators later (in resolveFuncletAncestryForPath).  If it
-// unwinds to a cleanup end pad or a catch end pad and this end pad corresponds
-// to the clone parent, we will replace the terminator in the original block
-// with an unreachable instruction. If it unwinds to a cleanup end pad or a
-// catch end pad that does not correspond to the clone parent, we will replace
-// the terminator in the clone block with an unreachable instruction.
-//
-// If the terminator is an invoke instruction, we will handle it after all
-// siblings of the current funclet have been cloned.
-void WinEHPrepare::updateTerminatorsAfterFuncletClone(
-    Function &F, BasicBlock *OrigFunclet, BasicBlock *CloneFunclet,
-    BasicBlock *OrigBlock, BasicBlock *CloneBlock, BasicBlock *CloneParent,
-    ValueToValueMapTy &VMap, std::map<BasicBlock *, BasicBlock *> &Orig2Clone) {
-  // If the cloned block doesn't have an exceptional terminator, there is
-  // nothing to be done here.
-  TerminatorInst *CloneTerminator = CloneBlock->getTerminator();
-  if (!CloneTerminator->isExceptional())
-    return;
-
-  if (auto *CloneCatch = dyn_cast<CatchPadInst>(CloneTerminator)) {
-    // A cloned catch pad has a lot of wrinkles, so we'll call a helper function
-    // to update this case.
-    auto *OrigCatch = cast<CatchPadInst>(OrigBlock->getTerminator());
-    updateCatchTerminators(F, OrigCatch, CloneCatch,
-                           FuncletParents[OrigFunclet], CloneParent, VMap,
-                           BlockColors, FuncletBlocks);
-  } else if (auto *CRI = dyn_cast<CatchReturnInst>(CloneTerminator)) {
-    if (FuncletBlocks[CloneParent].count(CRI->getSuccessor())) {
-      BasicBlock *OrigParent;
-      // The original funclet may have more than two parents, but that's OK.
-      // We just need to remap the original catchret to any of the parents.
-      // All of the parents should have an entry in the EstrangedBlocks map
-      // if any of them do.
-      if (FuncletParents[OrigFunclet].front() == CloneParent)
-        OrigParent = FuncletParents[OrigFunclet].back();
-      else
-        OrigParent = FuncletParents[OrigFunclet].front();
-      for (succ_iterator SI = succ_begin(OrigBlock), SE = succ_end(OrigBlock);
-           SI != SE; ++SI)
-        (*SI)->removePredecessor(OrigBlock);
-      BasicBlock *LostBlock = EstrangedBlocks[OrigParent][CRI->getSuccessor()];
-      auto *OrigCatchRet = cast<CatchReturnInst>(OrigBlock->getTerminator());
-      if (LostBlock) {
-        OrigCatchRet->setSuccessor(LostBlock);
-      } else {
-        OrigCatchRet->eraseFromParent();
-        new UnreachableInst(OrigBlock->getContext(), OrigBlock);
-      }
-    } else {
-      for (succ_iterator SI = succ_begin(CloneBlock), SE = succ_end(CloneBlock);
-           SI != SE; ++SI)
-        (*SI)->removePredecessor(CloneBlock);
-      BasicBlock *LostBlock = EstrangedBlocks[CloneParent][CRI->getSuccessor()];
-      if (LostBlock) {
-        CRI->setSuccessor(LostBlock);
-      } else {
-        CRI->eraseFromParent();
-        new UnreachableInst(CloneBlock->getContext(), CloneBlock);
-      }
-    }
-  } else if (isa<CleanupReturnInst>(CloneTerminator) ||
-             isa<CleanupEndPadInst>(CloneTerminator)) {
-    BasicBlock *UnwindDest = nullptr;
-
-    // A cleanup pad can unwind through either a cleanupret or a cleanupendpad
-    // but both are handled the same way.
-    if (auto *CRI = dyn_cast<CleanupReturnInst>(CloneTerminator))
-      UnwindDest = CRI->getUnwindDest();
-    else if (auto *CEI = dyn_cast<CleanupEndPadInst>(CloneTerminator))
-      UnwindDest = CEI->getUnwindDest();
-
-    // If the instruction has no local unwind destination, there is nothing
-    // to be done.
-    if (!UnwindDest)
-      return;
-
-    // The unwind destination may be a sibling EH pad, a catchendpad in
-    // a grandparent funclet (ending a catchpad in the parent) or a cleanup
-    // cleanupendpad in the parent.  Call a helper routine to diagnose this
-    // and remove either the clone or original terminator as needed.
-    updateClonedEHPadUnwindToParent(UnwindDest, OrigBlock, CloneBlock,
-                                    FuncletParents[OrigFunclet], CloneParent);
-  }
-}
-
-// Clones all blocks used by the specified funclet to avoid the funclet having
-// multiple parent funclets.  All terminators in the parent that unwind to the
-// original funclet are remapped to unwind to the clone.  Any terminator in the
-// original funclet which returned to this parent is converted to an unreachable
-// instruction. Likewise, any terminator in the cloned funclet which returns to
-// a parent funclet other than the specified parent is converted to an
-// unreachable instruction.
-BasicBlock *WinEHPrepare::cloneFuncletForParent(Function &F,
-                                                BasicBlock *FuncletEntry,
-                                                BasicBlock *Parent) {
-  std::set<BasicBlock *> &BlocksInFunclet = FuncletBlocks[FuncletEntry];
-
-  DEBUG_WITH_TYPE("winehprepare-coloring",
-                  dbgs() << "Cloning funclet \'" << FuncletEntry->getName()
-                         << "\' for parent \'" << Parent->getName() << "\'.\n");
-
-  std::map<BasicBlock *, BasicBlock *> Orig2Clone;
-  ValueToValueMapTy VMap;
-  for (BasicBlock *BB : BlocksInFunclet) {
-    // Create a new basic block and copy instructions into it.
-    BasicBlock *CBB =
-        CloneBasicBlock(BB, VMap, Twine(".from.", Parent->getName()));
-
-    // Insert the clone immediately after the original to ensure determinism
-    // and to keep the same relative ordering of any funclet's blocks.
-    CBB->insertInto(&F, BB->getNextNode());
-
-    // Add basic block mapping.
-    VMap[BB] = CBB;
-
-    // Record delta operations that we need to perform to our color mappings.
-    Orig2Clone[BB] = CBB;
-  } // end for (BasicBlock *BB : BlocksInFunclet)
-
-  BasicBlock *ClonedFunclet = Orig2Clone[FuncletEntry];
-  assert(ClonedFunclet);
-
-  // Set the coloring for the blocks we just cloned.
-  std::set<BasicBlock *> &ClonedBlocks = FuncletBlocks[ClonedFunclet];
-  for (auto &BBMapping : Orig2Clone) {
-    BasicBlock *NewBlock = BBMapping.second;
-    ClonedBlocks.insert(NewBlock);
-    BlockColors[NewBlock].insert(ClonedFunclet);
-
-    DEBUG_WITH_TYPE("winehprepare-coloring",
-                    dbgs() << "  Assigning color \'" << ClonedFunclet->getName()
-                           << "\' to block \'" << NewBlock->getName()
-                           << "\'.\n");
-
-    // Use the VMap to remap the instructions in this cloned block.
-    for (Instruction &I : *NewBlock)
-      RemapInstruction(&I, VMap, RF_IgnoreMissingEntries);
-  }
-
-  // All the cloned blocks have to be colored in the loop above before we can
-  // update the terminators because doing so can require checking the color of
-  // other blocks in the cloned funclet.
-  for (auto &BBMapping : Orig2Clone) {
-    BasicBlock *OldBlock = BBMapping.first;
-    BasicBlock *NewBlock = BBMapping.second;
-
-    // Update the terminator, if necessary, in both the original block and the
-    // cloned so that the original funclet never returns to a block in the
-    // clone parent and the clone funclet never returns to a block in any other
-    // of the original funclet's parents.
-    updateTerminatorsAfterFuncletClone(F, FuncletEntry, ClonedFunclet, OldBlock,
-                                       NewBlock, Parent, VMap, Orig2Clone);
-
-    // Check to see if the cloned block successor has PHI nodes. If so, we need
-    // to add entries to the PHI nodes for the cloned block now.
-    for (BasicBlock *SuccBB : successors(NewBlock)) {
-      for (Instruction &SuccI : *SuccBB) {
-        auto *SuccPN = dyn_cast<PHINode>(&SuccI);
-        if (!SuccPN)
-          break;
-
-        // Ok, we have a PHI node.  Figure out what the incoming value was for
-        // the OldBlock.
-        int OldBlockIdx = SuccPN->getBasicBlockIndex(OldBlock);
-        if (OldBlockIdx == -1)
-          break;
-        Value *IV = SuccPN->getIncomingValue(OldBlockIdx);
-
-        // Remap the value if necessary.
-        if (auto *Inst = dyn_cast<Instruction>(IV)) {
-          ValueToValueMapTy::iterator I = VMap.find(Inst);
-          if (I != VMap.end())
-            IV = I->second;
-        }
-
-        SuccPN->addIncoming(IV, NewBlock);
-      }
-    }
-  }
-
-  // Erase the clone's parent from the original funclet's parent list.
-  std::vector<BasicBlock *> &Parents = FuncletParents[FuncletEntry];
-  Parents.erase(std::remove(Parents.begin(), Parents.end(), Parent),
-                Parents.end());
-
-  // Store the cloned funclet's parent.
-  assert(std::find(FuncletParents[ClonedFunclet].begin(),
-                   FuncletParents[ClonedFunclet].end(),
-                   Parent) == std::end(FuncletParents[ClonedFunclet]));
-  FuncletParents[ClonedFunclet].push_back(Parent);
-
-  // Copy any children of the original funclet to the clone.  We'll either
-  // clone them too or make that path unreachable when we take the next step
-  // in resolveFuncletAncestryForPath().
-  for (auto *Child : FuncletChildren[FuncletEntry]) {
-    assert(std::find(FuncletChildren[ClonedFunclet].begin(),
-                     FuncletChildren[ClonedFunclet].end(),
-                     Child) == std::end(FuncletChildren[ClonedFunclet]));
-    FuncletChildren[ClonedFunclet].push_back(Child);
-    assert(std::find(FuncletParents[Child].begin(), FuncletParents[Child].end(),
-                     ClonedFunclet) == std::end(FuncletParents[Child]));
-    FuncletParents[Child].push_back(ClonedFunclet);
-  }
-
-  // Find any blocks that unwound to the original funclet entry from the
-  // clone parent block and remap them to the clone.
-  for (auto *U : FuncletEntry->users()) {
-    auto *UT = dyn_cast<TerminatorInst>(U);
-    if (!UT)
-      continue;
-    BasicBlock *UBB = UT->getParent();
-    assert(BlockColors[UBB].size() == 1);
-    BasicBlock *UFunclet = *(BlockColors[UBB].begin());
-    // Funclets shouldn't be able to loop back on themselves.
-    assert(UFunclet != FuncletEntry);
-    // If this instruction unwinds to the original funclet from the clone
-    // parent, remap the terminator so that it unwinds to the clone instead.
-    // We will perform a similar transformation for siblings after all
-    // the siblings have been cloned.
-    if (UFunclet == Parent) {
-      // We're about to break the path from this block to the uncloned funclet
-      // entry, so remove it as a predeccessor to clean up the PHIs.
-      FuncletEntry->removePredecessor(UBB);
-      TerminatorInst *Terminator = UBB->getTerminator();
-      RemapInstruction(Terminator, VMap, RF_IgnoreMissingEntries);
-    }
-  }
-
-  // This asserts a condition that is relied upon inside the loop below,
-  // namely that no predecessors of the original funclet entry block
-  // are also predecessors of the cloned funclet entry block.
-  assert(std::all_of(pred_begin(FuncletEntry), pred_end(FuncletEntry),
-                     [&ClonedFunclet](BasicBlock *Pred) {
-                       return std::find(pred_begin(ClonedFunclet),
-                                        pred_end(ClonedFunclet),
-                                        Pred) == pred_end(ClonedFunclet);
-                     }));
-
-  // Remove any invalid PHI node entries in the cloned funclet.cl
-  std::vector<PHINode *> PHIsToErase;
-  for (Instruction &I : *ClonedFunclet) {
-    auto *PN = dyn_cast<PHINode>(&I);
-    if (!PN)
-      break;
-
-    // Predecessors of the original funclet do not reach the cloned funclet,
-    // but the cloning process assumes they will.  Remove them now.
-    for (auto *Pred : predecessors(FuncletEntry))
-      PN->removeIncomingValue(Pred, false);
-  }
-  for (auto *PN : PHIsToErase)
-    PN->eraseFromParent();
-
-  // Replace the original funclet in the parent's children vector with the
-  // cloned funclet.
-  for (auto &It : FuncletChildren[Parent]) {
-    if (It == FuncletEntry) {
-      It = ClonedFunclet;
-      break;
-    }
-  }
-
-  return ClonedFunclet;
-}
-
-// Removes the unwind edge for any exceptional terminators within the specified
-// parent funclet that previously unwound to the specified child funclet.
-void WinEHPrepare::makeFuncletEdgeUnreachable(BasicBlock *Parent,
-                                              BasicBlock *Child) {
-  for (BasicBlock *BB : FuncletBlocks[Parent]) {
-    TerminatorInst *Terminator = BB->getTerminator();
-    if (!Terminator->isExceptional())
-      continue;
-
-    // Look for terninators that unwind to the child funclet.
-    BasicBlock *UnwindDest = nullptr;
-    if (auto *I = dyn_cast<InvokeInst>(Terminator))
-      UnwindDest = I->getUnwindDest();
-    else if (auto *I = dyn_cast<CatchEndPadInst>(Terminator))
-      UnwindDest = I->getUnwindDest();
-    else if (auto *I = dyn_cast<TerminatePadInst>(Terminator))
-      UnwindDest = I->getUnwindDest();
-    // cleanupendpad, catchret and cleanupret don't represent a parent-to-child
-    // funclet transition, so we don't need to consider them here.
-
-    // If the child funclet is the unwind destination, replace the terminator
-    // with an unreachable instruction.
-    if (UnwindDest == Child)
-      removeUnwindEdge(BB);
-  }
-  // The specified parent is no longer a parent of the specified child.
-  std::vector<BasicBlock *> &Children = FuncletChildren[Parent];
-  Children.erase(std::remove(Children.begin(), Children.end(), Child),
-                 Children.end());
-}
-
-// This routine is called after funclets with multiple parents are cloned for
-// a specific parent.  Here we look for children of the specified funclet that
-// unwind to other children of that funclet and update the unwind destinations
-// to ensure that each sibling is connected to the correct clone of the sibling
-// to which it unwinds.
-//
-// If the terminator is an invoke instruction, it unwinds either to a child
-// EH pad, a cleanup end pad in the current funclet, or a catch end pad in a
-// parent funclet (which ends either the current catch pad or a sibling
-// catch pad).  If it unwinds to a child EH pad, the child will have multiple
-// parents after this funclet is cloned and this case will be handled later in
-// the resolveFuncletAncestryForPath processing.  If it unwinds to a
-// cleanup end pad in the current funclet, the instruction remapping during
-// the cloning process should have already mapped the unwind destination to
-// the cloned copy of the cleanup end pad.  If it unwinds to a catch end pad
-// there are two possibilities: either the catch end pad is the unwind
-// destination for the catch pad we are currently cloning or it is the unwind
-// destination for a sibling catch pad.  If it it the unwind destination of the
-// catch pad we are cloning, we need to update the cloned invoke instruction
-// to unwind to the cloned catch end pad.  Otherwise, we will handle this
-// later (in resolveFuncletAncestryForPath).
-static void updateSiblingToSiblingUnwind(
-    BasicBlock *CurFunclet,
-    std::map<BasicBlock *, SetVector<BasicBlock *>> &BlockColors,
-    std::map<BasicBlock *, std::set<BasicBlock *>> &FuncletBlocks,
-    std::map<BasicBlock *, std::vector<BasicBlock *>> &FuncletParents,
-    std::map<BasicBlock *, std::vector<BasicBlock *>> &FuncletChildren,
-    std::map<BasicBlock *, BasicBlock *> &Funclet2Orig) {
-  // Remap any bad sibling-to-sibling transitions for funclets that
-  // we just cloned.
-  for (BasicBlock *ChildFunclet : FuncletChildren[CurFunclet]) {
-    for (auto *BB : FuncletBlocks[ChildFunclet]) {
-      TerminatorInst *Terminator = BB->getTerminator();
-      if (!Terminator->isExceptional())
-        continue;
-
-      // See if this terminator has an unwind destination.
-      // Note that catchendpads are handled when the associated catchpad
-      // is cloned.  They don't fit the pattern we're looking for here.
-      BasicBlock *UnwindDest = nullptr;
-      if (auto *I = dyn_cast<CatchPadInst>(Terminator)) {
-        UnwindDest = I->getUnwindDest();
-        // The catchendpad is not a sibling destination.  This case should
-        // have been handled in cloneFuncletForParent().
-        if (isa<CatchEndPadInst>(Terminator)) {
-          assert(BlockColors[UnwindDest].size() == 1 &&
-                 "Cloned catchpad unwinds to an pad with multiple parents.");
-          assert(FuncletParents[UnwindDest].front() == CurFunclet &&
-                 "Cloned catchpad unwinds to the wrong parent.");
-          continue;
-        }
-      } else {
-        if (auto *I = dyn_cast<CleanupReturnInst>(Terminator))
-          UnwindDest = I->getUnwindDest();
-        else if (auto *I = dyn_cast<CleanupEndPadInst>(Terminator))
-          UnwindDest = I->getUnwindDest();
-
-        // If the cleanup unwinds to caller, there is nothing to be done.
-        if (!UnwindDest)
-          continue;
-      }
-
-      // If the destination is not a cleanup pad, catch pad or terminate pad
-      // we don't need to handle it here.
-      Instruction *EHPad = UnwindDest->getFirstNonPHI();
-      if (!isa<CleanupPadInst>(EHPad) && !isa<CatchPadInst>(EHPad) &&
-          !isa<TerminatePadInst>(EHPad))
-        continue;
-
-      // If it is one of these, then it is either a sibling of the current
-      // child funclet or a clone of one of those siblings.
-      // If it is a sibling, no action is needed.
-      if (FuncletParents[UnwindDest].size() == 1 &&
-          FuncletParents[UnwindDest].front() == CurFunclet)
-        continue;
-
-      // If the unwind destination is a clone of a sibling, we need to figure
-      // out which sibling it is a clone of and use that sibling as the
-      // unwind destination.
-      BasicBlock *DestOrig = Funclet2Orig[UnwindDest];
-      BasicBlock *TargetSibling = nullptr;
-      for (auto &Mapping : Funclet2Orig) {
-        if (Mapping.second != DestOrig)
-          continue;
-        BasicBlock *MappedFunclet = Mapping.first;
-        if (FuncletParents[MappedFunclet].size() == 1 &&
-            FuncletParents[MappedFunclet].front() == CurFunclet) {
-          TargetSibling = MappedFunclet;
-        }
-      }
-      // If we didn't find the sibling we were looking for then the
-      // unwind destination is not a clone of one of child's siblings.
-      // That's unexpected.
-      assert(TargetSibling && "Funclet unwinds to unexpected destination.");
-
-      // Update the terminator instruction to unwind to the correct sibling.
-      if (auto *I = dyn_cast<CatchPadInst>(Terminator))
-        I->setUnwindDest(TargetSibling);
-      else if (auto *I = dyn_cast<CleanupReturnInst>(Terminator))
-        I->setUnwindDest(TargetSibling);
-      else if (auto *I = dyn_cast<CleanupEndPadInst>(Terminator))
-        I->setUnwindDest(TargetSibling);
-    }
-  }
-  
-  // Invoke remapping can't be done correctly until after all of their
-  // other sibling-to-sibling unwinds have been remapped.
-  for (BasicBlock *ChildFunclet : FuncletChildren[CurFunclet]) {
-    bool NeedOrigInvokeRemapping = false;
-    for (auto *BB : FuncletBlocks[ChildFunclet]) {
-      TerminatorInst *Terminator = BB->getTerminator();
-      auto *II = dyn_cast<InvokeInst>(Terminator);
-      if (!II)
-        continue;
-
-      BasicBlock *UnwindDest = II->getUnwindDest();
-      assert(UnwindDest && "Invoke unwinds to a null destination.");
-      assert(UnwindDest->isEHPad() && "Invoke does not unwind to an EH pad.");
-      auto *EHPadInst = UnwindDest->getFirstNonPHI();
-      if (isa<CleanupEndPadInst>(EHPadInst)) {
-        // An invoke that unwinds to a cleanup end pad must be in a cleanup pad.
-        assert(isa<CleanupPadInst>(ChildFunclet->getFirstNonPHI()) &&
-               "Unwinding to cleanup end pad from a non cleanup pad funclet.");
-        // The funclet cloning should have remapped the destination to the cloned
-        // cleanup end pad.
-        assert(FuncletBlocks[ChildFunclet].count(UnwindDest) &&
-               "Unwind destination for invoke was not updated during cloning.");
-      } else if (isa<CatchEndPadInst>(EHPadInst)) {
-        // If the invoke unwind destination is the unwind destination for
-        // the current child catch pad funclet, there is nothing to be done.
-        BasicBlock *OrigFunclet = Funclet2Orig[ChildFunclet];
-        auto *CurCatch = cast<CatchPadInst>(ChildFunclet->getFirstNonPHI());
-        auto *OrigCatch = cast<CatchPadInst>(OrigFunclet->getFirstNonPHI());
-        if (OrigCatch->getUnwindDest() == UnwindDest) {
-          // If the invoke unwinds to a catch end pad that is the unwind
-          // destination for the original catch pad, the cloned invoke should
-          // unwind to the cloned catch end pad.
-          II->setUnwindDest(CurCatch->getUnwindDest());
-        } else if (CurCatch->getUnwindDest() == UnwindDest) {
-          // If the invoke unwinds to a catch end pad that is the unwind
-          // destination for the clone catch pad, the original invoke should
-          // unwind to the unwind destination of the original catch pad.
-          // This happens when the catch end pad is matched to the clone
-          // parent when the catchpad instruction is cloned and the original
-          // invoke instruction unwinds to the original catch end pad (which
-          // is now the unwind destination of the cloned catch pad).
-          NeedOrigInvokeRemapping = true;
-        } else {
-          // Otherwise, the invoke unwinds to a catch end pad that is the unwind
-          // destination another catch pad in the unwind chain from either the
-          // current catch pad or one of its clones.  If it is already the
-          // catch end pad at the end unwind chain from the current catch pad,
-          // we'll need to check the invoke instructions in the original funclet
-          // later.  Otherwise, we need to remap this invoke now.
-          assert((getEndPadForCatch(OrigCatch) == UnwindDest ||
-                  getEndPadForCatch(CurCatch) == UnwindDest) &&
-                "Invoke within catch pad unwinds to an invalid catch end pad.");
-          BasicBlock *CurCatchEnd = getEndPadForCatch(CurCatch);
-          if (CurCatchEnd == UnwindDest)
-            NeedOrigInvokeRemapping = true;
-          else
-            II->setUnwindDest(CurCatchEnd);
-        }
-      }
-    }
-    if (NeedOrigInvokeRemapping) {
-      // To properly remap invoke instructions that unwind to catch end pads
-      // that are not the unwind destination of the catch pad funclet in which
-      // the invoke appears, we must also look at the uncloned invoke in the
-      // original funclet.  If we saw an invoke that was already properly
-      // unwinding to a sibling's catch end pad, we need to check the invokes
-      // in the original funclet.
-      BasicBlock *OrigFunclet = Funclet2Orig[ChildFunclet];
-      for (auto *BB : FuncletBlocks[OrigFunclet]) {
-        auto *II = dyn_cast<InvokeInst>(BB->getTerminator());
-        if (!II)
-          continue;
+void WinEHPrepare::colorFunclets(Function &F) {
+  BlockColors = colorEHFunclets(F);
 
-        BasicBlock *UnwindDest = II->getUnwindDest();
-        assert(UnwindDest && "Invoke unwinds to a null destination.");
-        assert(UnwindDest->isEHPad() && "Invoke does not unwind to an EH pad.");
-        auto *CEP = dyn_cast<CatchEndPadInst>(UnwindDest->getFirstNonPHI());
-        if (!CEP)
-          continue;
-
-        // If the invoke unwind destination is the unwind destination for
-        // the original catch pad funclet, there is nothing to be done.
-        auto *OrigCatch = cast<CatchPadInst>(OrigFunclet->getFirstNonPHI());
-
-        // If the invoke unwinds to a catch end pad that is neither the unwind
-        // destination of OrigCatch or the destination another catch pad in the
-        // unwind chain from current catch pad, we need to remap the invoke.
-        BasicBlock *OrigCatchEnd = getEndPadForCatch(OrigCatch);
-        if (OrigCatchEnd != UnwindDest)
-          II->setUnwindDest(OrigCatchEnd);
-      }
-    }
-  }
-}
-
-void WinEHPrepare::resolveFuncletAncestry(
-    Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
-  // Most of the time this will be unnecessary.  If the conditions arise that
-  // require this work, this flag will be set.
-  if (!FuncletCloningRequired)
-    return;
-  
-  // Funclet2Orig is used to map any cloned funclets back to the original
-  // funclet from which they were cloned.  The map is seeded with the
-  // original funclets mapping to themselves.
-  std::map<BasicBlock *, BasicBlock *> Funclet2Orig;
-  for (auto *Funclet : EntryBlocks)
-    Funclet2Orig[Funclet] = Funclet;
-
-  // Start with the entry funclet and walk the funclet parent-child tree.
-  SmallVector<BasicBlock *, 4> FuncletPath;
-  FuncletPath.push_back(&(F.getEntryBlock()));
-  resolveFuncletAncestryForPath(F, FuncletPath, Funclet2Orig);
-}
-
-// Walks the funclet control flow, cloning any funclets that have more than one
-// parent funclet and breaking any cyclic unwind chains so that the path becomes
-// unreachable at the point where a funclet would have unwound to a funclet that
-// was already in the chain.
-void WinEHPrepare::resolveFuncletAncestryForPath(
-    Function &F, SmallVectorImpl<BasicBlock *> &FuncletPath,
-    std::map<BasicBlock *, BasicBlock *> &Funclet2Orig) {
-  bool ClonedAnyChildren = false;
-  BasicBlock *CurFunclet = FuncletPath.back();
-  // Copy the children vector because we might changing it.
-  std::vector<BasicBlock *> Children(FuncletChildren[CurFunclet]);
-  for (BasicBlock *ChildFunclet : Children) {
-    // Don't allow the funclet chain to unwind back on itself.
-    // If this funclet is already in the current funclet chain, make the
-    // path to it through the current funclet unreachable.
-    bool IsCyclic = false;
-    BasicBlock *ChildIdentity = Funclet2Orig[ChildFunclet];
-    for (BasicBlock *Ancestor : FuncletPath) {
-      BasicBlock *AncestorIdentity = Funclet2Orig[Ancestor];
-      if (AncestorIdentity == ChildIdentity) {
-        IsCyclic = true;
-        break;
-      }
-    }
-    // If the unwind chain wraps back on itself, break the chain.
-    if (IsCyclic) {
-      makeFuncletEdgeUnreachable(CurFunclet, ChildFunclet);
-      continue;
-    }
-    // If this child funclet has other parents, clone the entire funclet.
-    if (FuncletParents[ChildFunclet].size() > 1) {
-      ChildFunclet = cloneFuncletForParent(F, ChildFunclet, CurFunclet);
-      Funclet2Orig[ChildFunclet] = ChildIdentity;
-      ClonedAnyChildren = true;
-    }
-    FuncletPath.push_back(ChildFunclet);
-    resolveFuncletAncestryForPath(F, FuncletPath, Funclet2Orig);
-    FuncletPath.pop_back();
-  }
-  // If we didn't clone any children, we can return now.
-  if (!ClonedAnyChildren)
-    return;
-
-  updateSiblingToSiblingUnwind(CurFunclet, BlockColors, FuncletBlocks,
-                               FuncletParents, FuncletChildren, Funclet2Orig);
-}
-
-void WinEHPrepare::colorFunclets(Function &F,
-                                 SmallVectorImpl<BasicBlock *> &EntryBlocks) {
-  ::colorFunclets(F, EntryBlocks, BlockColors, FuncletBlocks);
-
-  // The processing above actually accumulated the parent set for this
-  // funclet into the color set for its entry; use the parent set to
-  // populate the children map, and reset the color set to include just
-  // the funclet itself (no instruction can target a funclet entry except on
-  // that transitions to the child funclet).
-  for (BasicBlock *FuncletEntry : EntryBlocks) {
-    SetVector<BasicBlock *> &ColorMapItem = BlockColors[FuncletEntry];
-    // It will be rare for funclets to have multiple parents, but if any
-    // do we need to clone the funclet later to address that.  Here we
-    // set a flag indicating that this case has arisen so that we don't
-    // have to do a lot of checking later to handle the more common case.
-    if (ColorMapItem.size() > 1)
-      FuncletCloningRequired = true;
-    for (BasicBlock *Parent : ColorMapItem) {
-      assert(std::find(FuncletChildren[Parent].begin(),
-                       FuncletChildren[Parent].end(),
-                       FuncletEntry) == std::end(FuncletChildren[Parent]));
-      FuncletChildren[Parent].push_back(FuncletEntry);
-      assert(std::find(FuncletParents[FuncletEntry].begin(),
-                       FuncletParents[FuncletEntry].end(),
-                       Parent) == std::end(FuncletParents[FuncletEntry]));
-      FuncletParents[FuncletEntry].push_back(Parent);
-    }
-    ColorMapItem.clear();
-    ColorMapItem.insert(FuncletEntry);
+  // Invert the map from BB to colors to color to BBs.
+  for (BasicBlock &BB : F) {
+    ColorVector &Colors = BlockColors[&BB];
+    for (BasicBlock *Color : Colors)
+      FuncletBlocks[Color].push_back(&BB);
   }
 }
 
 void llvm::calculateCatchReturnSuccessorColors(const Function *Fn,
                                                WinEHFuncInfo &FuncInfo) {
-  SmallVector<BasicBlock *, 4> EntryBlocks;
-  // colorFunclets needs the set of EntryBlocks, get them using
-  // findFuncletEntryPoints.
-  findFuncletEntryPoints(const_cast<Function &>(*Fn), EntryBlocks);
-
-  std::map<BasicBlock *, SetVector<BasicBlock *>> BlockColors;
-  std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks;
-  // Figure out which basic blocks belong to which funclets.
-  colorFunclets(const_cast<Function &>(*Fn), EntryBlocks, BlockColors,
-                FuncletBlocks);
-
-  // The static colorFunclets routine assigns multiple colors to funclet entries
-  // because that information is needed to calculate funclets' parent-child
-  // relationship, but we don't need those relationship here and ultimately the
-  // entry blocks should have the color of the funclet they begin.
-  for (BasicBlock *FuncletEntry : EntryBlocks) {
-    BlockColors[FuncletEntry].clear();
-    BlockColors[FuncletEntry].insert(FuncletEntry);
-  }
-
-  // We need to find the catchret successors.  To do this, we must first find
-  // all the catchpad funclets.
-  for (auto &Funclet : FuncletBlocks) {
-    // Figure out what kind of funclet we are looking at; We only care about
-    // catchpads.
-    BasicBlock *FuncletPadBB = Funclet.first;
-    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
-    auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
-    if (!CatchPad)
+  for (const BasicBlock &BB : *Fn) {
+    const auto *CatchRet = dyn_cast<CatchReturnInst>(BB.getTerminator());
+    if (!CatchRet)
       continue;
-
-    // The users of a catchpad are always catchrets.
-    for (User *Exit : CatchPad->users()) {
-      auto *CatchReturn = dyn_cast<CatchReturnInst>(Exit);
-      if (!CatchReturn)
-        continue;
-      BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
-      SetVector<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
-      assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");
-      BasicBlock *Color = *SuccessorColors.begin();
-      // Record the catchret successor's funclet membership.
-      FuncInfo.CatchRetSuccessorColorMap[CatchReturn] = Color;
-    }
+    // A 'catchret' returns to the outer scope's color.
+    Value *ParentPad = CatchRet->getParentPad();
+    const BasicBlock *Color;
+    if (isa<ConstantTokenNone>(ParentPad))
+      Color = &Fn->getEntryBlock();
+    else
+      Color = cast<Instruction>(ParentPad)->getParent();
+    // Record the catchret successor's funclet membership.
+    FuncInfo.CatchRetSuccessorColorMap[CatchRet] = Color;
   }
 }
 
@@ -1584,70 +620,23 @@ void WinEHPrepare::demotePHIsOnFunclets(
   }
 }
 
-void WinEHPrepare::cloneCommonBlocks(
-    Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
+void WinEHPrepare::cloneCommonBlocks(Function &F) {
   // We need to clone all blocks which belong to multiple funclets.  Values are
   // remapped throughout the funclet to propogate both the new instructions
   // *and* the new basic blocks themselves.
-  for (BasicBlock *FuncletPadBB : EntryBlocks) {
-    std::set<BasicBlock *> &BlocksInFunclet = FuncletBlocks[FuncletPadBB];
+  for (auto &Funclets : FuncletBlocks) {
+    BasicBlock *FuncletPadBB = Funclets.first;
+    std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second;
 
-    std::map<BasicBlock *, BasicBlock *> Orig2Clone;
+    std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;
     ValueToValueMapTy VMap;
-    for (auto BlockIt = BlocksInFunclet.begin(),
-              BlockEnd = BlocksInFunclet.end();
-         BlockIt != BlockEnd;) {
-      // Increment the iterator inside the loop because we might be removing
-      // blocks from the set.
-      BasicBlock *BB = *BlockIt++;
-      SetVector<BasicBlock *> &ColorsForBB = BlockColors[BB];
+    for (BasicBlock *BB : BlocksInFunclet) {
+      ColorVector &ColorsForBB = BlockColors[BB];
       // We don't need to do anything if the block is monochromatic.
       size_t NumColorsForBB = ColorsForBB.size();
       if (NumColorsForBB == 1)
         continue;
 
-      // If this block is a catchendpad, it shouldn't be cloned.
-      // We will only see a catchendpad with multiple colors in the case where
-      // some funclet has multiple parents.  In that case, the color will be
-      // resolved during the resolveFuncletAncestry processing.
-      // For now, find the catchpad that unwinds to this block and assign
-      // that catchpad's first parent to be the color for this block.
-      if (isa<CatchEndPadInst>(BB->getFirstNonPHI())) {
-        assert(
-            FuncletCloningRequired &&
-            "Found multi-colored catchendpad with no multi-parent funclets.");
-        BasicBlock *CatchParent = nullptr;
-        // There can only be one catchpad predecessor for a catchendpad.
-        for (BasicBlock *PredBB : predecessors(BB)) {
-          if (isa<CatchPadInst>(PredBB->getTerminator())) {
-            CatchParent = PredBB;
-            break;
-          }
-        }
-        // There must be one catchpad predecessor for a catchendpad.
-        assert(CatchParent && "No catchpad found for catchendpad.");
-
-        // If the catchpad has multiple parents, we'll clone the catchendpad
-        // when we clone the catchpad funclet and insert it into the correct
-        // funclet.  For now, we just select the first parent of the catchpad
-        // and give the catchendpad that color.
-        BasicBlock *CorrectColor = FuncletParents[CatchParent].front();
-        assert(FuncletBlocks[CorrectColor].count(BB));
-        assert(BlockColors[BB].count(CorrectColor));
-
-        // Remove this block from the FuncletBlocks set of any funclet that
-        // isn't the funclet whose color we just selected.
-        for (BasicBlock *ContainingFunclet : BlockColors[BB])
-          if (ContainingFunclet != CorrectColor)
-            FuncletBlocks[ContainingFunclet].erase(BB);
-        BlockColors[BB].remove_if([&](BasicBlock *ContainingFunclet) {
-          return ContainingFunclet != CorrectColor;
-        });
-        // This should leave just one color for BB.
-        assert(BlockColors[BB].size() == 1);
-        continue;
-      }
-
       DEBUG_WITH_TYPE("winehprepare-coloring",
                       dbgs() << "  Cloning block \'" << BB->getName()
                               << "\' for funclet \'" << FuncletPadBB->getName()
@@ -1664,7 +653,7 @@ void WinEHPrepare::cloneCommonBlocks(
       VMap[BB] = CBB;
 
       // Record delta operations that we need to perform to our color mappings.
-      Orig2Clone[BB] = CBB;
+      Orig2Clone.emplace_back(BB, CBB);
     }
 
     // If nothing was cloned, we're done cloning in this funclet.
@@ -1677,55 +666,28 @@ void WinEHPrepare::cloneCommonBlocks(
       BasicBlock *OldBlock = BBMapping.first;
       BasicBlock *NewBlock = BBMapping.second;
 
-      BlocksInFunclet.insert(NewBlock);
-      BlockColors[NewBlock].insert(FuncletPadBB);
+      BlocksInFunclet.push_back(NewBlock);
+      ColorVector &NewColors = BlockColors[NewBlock];
+      assert(NewColors.empty() && "A new block should only have one color!");
+      NewColors.push_back(FuncletPadBB);
 
       DEBUG_WITH_TYPE("winehprepare-coloring",
                       dbgs() << "  Assigned color \'" << FuncletPadBB->getName()
                               << "\' to block \'" << NewBlock->getName()
                               << "\'.\n");
 
-      BlocksInFunclet.erase(OldBlock);
-      BlockColors[OldBlock].remove(FuncletPadBB);
+      BlocksInFunclet.erase(
+          std::remove(BlocksInFunclet.begin(), BlocksInFunclet.end(), OldBlock),
+          BlocksInFunclet.end());
+      ColorVector &OldColors = BlockColors[OldBlock];
+      OldColors.erase(
+          std::remove(OldColors.begin(), OldColors.end(), FuncletPadBB),
+          OldColors.end());
 
       DEBUG_WITH_TYPE("winehprepare-coloring",
                       dbgs() << "  Removed color \'" << FuncletPadBB->getName()
                               << "\' from block \'" << OldBlock->getName()
                               << "\'.\n");
-
-      // If we are cloning a funclet that might share a child funclet with
-      // another funclet, look to see if the cloned block is reached from a
-      // catchret instruction.  If so, save this association so we can retrieve
-      // the possibly orphaned clone when we clone the child funclet.
-      if (FuncletCloningRequired) {
-        for (auto *Pred : predecessors(OldBlock)) {
-          auto *Terminator = Pred->getTerminator();
-          if (!isa<CatchReturnInst>(Terminator))
-            continue;
-          // If this block is reached from a catchret instruction in a funclet
-          // that has multiple parents, it will have a color for each of those
-          // parents.  We just removed the color of one of the parents, but
-          // the cloned block will be unreachable until we clone the child
-          // funclet that contains the catchret instruction.  In that case we
-          // need to create a mapping that will let us find the cloned block
-          // later and associate it with the cloned child funclet.
-          bool BlockWillBeEstranged = false;
-          for (auto *Color : BlockColors[Pred]) {
-            if (FuncletParents[Color].size() > 1) {
-              BlockWillBeEstranged = true;
-              break; // Breaks out of the color loop
-            }
-          }
-          if (BlockWillBeEstranged) {
-            EstrangedBlocks[FuncletPadBB][OldBlock] = NewBlock;
-            DEBUG_WITH_TYPE("winehprepare-coloring",
-                            dbgs() << "  Saved mapping of estranged block \'"
-                                  << NewBlock->getName() << "\' for \'"
-                                  << FuncletPadBB->getName() << "\'.\n");
-            break; // Breaks out of the predecessor loop
-          }
-        }
-      }
     }
 
     // Loop over all of the instructions in this funclet, fixing up operand
@@ -1736,6 +698,40 @@ void WinEHPrepare::cloneCommonBlocks(
         RemapInstruction(&I, VMap,
                          RF_IgnoreMissingEntries | RF_NoModuleLevelChanges);
 
+    auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {
+      unsigned NumPreds = PN->getNumIncomingValues();
+      for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;
+           ++PredIdx) {
+        BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx);
+        ColorVector &IncomingColors = BlockColors[IncomingBlock];
+        bool BlockInFunclet = IncomingColors.size() == 1 &&
+                              IncomingColors.front() == FuncletPadBB;
+        if (IsForOldBlock != BlockInFunclet)
+          continue;
+        PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);
+        // Revisit the next entry.
+        --PredIdx;
+        --PredEnd;
+      }
+    };
+
+    for (auto &BBMapping : Orig2Clone) {
+      BasicBlock *OldBlock = BBMapping.first;
+      BasicBlock *NewBlock = BBMapping.second;
+      for (Instruction &OldI : *OldBlock) {
+        auto *OldPN = dyn_cast<PHINode>(&OldI);
+        if (!OldPN)
+          break;
+        UpdatePHIOnClonedBlock(OldPN, /*IsForOldBlock=*/true);
+      }
+      for (Instruction &NewI : *NewBlock) {
+        auto *NewPN = dyn_cast<PHINode>(&NewI);
+        if (!NewPN)
+          break;
+        UpdatePHIOnClonedBlock(NewPN, /*IsForOldBlock=*/false);
+      }
+    }
+
     // Check to see if SuccBB has PHI nodes. If so, we need to add entries to
     // the PHI nodes for NewBB now.
     for (auto &BBMapping : Orig2Clone) {
@@ -1783,7 +779,7 @@ void WinEHPrepare::cloneCommonBlocks(
       for (Use &U : OldI->uses()) {
         Instruction *UserI = cast<Instruction>(U.getUser());
         BasicBlock *UserBB = UserI->getParent();
-        SetVector<BasicBlock *> &ColorsForUserBB = BlockColors[UserBB];
+        ColorVector &ColorsForUserBB = BlockColors[UserBB];
         assert(!ColorsForUserBB.empty());
         if (ColorsForUserBB.size() > 1 ||
             *ColorsForUserBB.begin() != FuncletPadBB)
@@ -1813,10 +809,10 @@ void WinEHPrepare::removeImplausibleTerm
   // Remove implausible terminators and replace them with UnreachableInst.
   for (auto &Funclet : FuncletBlocks) {
     BasicBlock *FuncletPadBB = Funclet.first;
-    std::set<BasicBlock *> &BlocksInFunclet = Funclet.second;
-    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
-    auto *CatchPad = dyn_cast<CatchPadInst>(FirstNonPHI);
-    auto *CleanupPad = dyn_cast<CleanupPadInst>(FirstNonPHI);
+    std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
+    Instruction *FuncletPadInst = FuncletPadBB->getFirstNonPHI();
+    auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPadInst);
+    auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPadInst);
 
     for (BasicBlock *BB : BlocksInFunclet) {
       TerminatorInst *TI = BB->getTerminator();
@@ -1830,34 +826,22 @@ void WinEHPrepare::removeImplausibleTerm
       bool IsUnreachableCleanupret = false;
       if (auto *CRI = dyn_cast<CleanupReturnInst>(TI))
         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
-      // The token consumed by a CleanupEndPadInst must match the funclet token.
-      bool IsUnreachableCleanupendpad = false;
-      if (auto *CEPI = dyn_cast<CleanupEndPadInst>(TI))
-        IsUnreachableCleanupendpad = CEPI->getCleanupPad() != CleanupPad;
       if (IsUnreachableRet || IsUnreachableCatchret ||
-          IsUnreachableCleanupret || IsUnreachableCleanupendpad) {
+          IsUnreachableCleanupret) {
         // Loop through all of our successors and make sure they know that one
         // of their predecessors is going away.
         for (BasicBlock *SuccBB : TI->successors())
           SuccBB->removePredecessor(BB);
 
-        if (IsUnreachableCleanupendpad) {
-          // We can't simply replace a cleanupendpad with unreachable, because
-          // its predecessor edges are EH edges and unreachable is not an EH
-          // pad.  Change all predecessors to the "unwind to caller" form.
-          for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
-               PI != PE;) {
-            BasicBlock *Pred = *PI++;
-            removeUnwindEdge(Pred);
-          }
-        }
-
         new UnreachableInst(BB->getContext(), TI);
         TI->eraseFromParent();
+      } else if (isa<InvokeInst>(TI)) {
+        // Invokes within a cleanuppad for the MSVC++ personality never
+        // transfer control to their unwind edge: the personality will
+        // terminate the program.
+        if (Personality == EHPersonality::MSVC_CXX && CleanupPad)
+          removeUnwindEdge(BB);
       }
-      // FIXME: Check for invokes/cleanuprets/cleanupendpads which unwind to
-      // implausible catchendpads (i.e. catchendpad not in immediate parent
-      // funclet).
     }
   }
 }
@@ -1886,27 +870,31 @@ void WinEHPrepare::verifyPreparedFunclet
       report_fatal_error("Uncolored BB!");
     if (NumColors > 1)
       report_fatal_error("Multicolor BB!");
-    bool EHPadHasPHI = BB.isEHPad() && isa<PHINode>(BB.begin());
-    assert(!EHPadHasPHI && "EH Pad still has a PHI!");
-    if (EHPadHasPHI)
-      report_fatal_error("EH Pad still has a PHI!");
+    if (!DisableDemotion) {
+      bool EHPadHasPHI = BB.isEHPad() && isa<PHINode>(BB.begin());
+      assert(!EHPadHasPHI && "EH Pad still has a PHI!");
+      if (EHPadHasPHI)
+        report_fatal_error("EH Pad still has a PHI!");
+    }
   }
 }
 
-bool WinEHPrepare::prepareExplicitEH(
-    Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks) {
+bool WinEHPrepare::prepareExplicitEH(Function &F) {
+  // Remove unreachable blocks.  It is not valuable to assign them a color and
+  // their existence can trick us into thinking values are alive when they are
+  // not.
+  removeUnreachableBlocks(F);
+
   replaceTerminatePadWithCleanup(F);
 
   // Determine which blocks are reachable from which funclet entries.
-  colorFunclets(F, EntryBlocks);
+  colorFunclets(F);
+
+  cloneCommonBlocks(F);
 
   if (!DisableDemotion)
     demotePHIsOnFunclets(F);
 
-  cloneCommonBlocks(F, EntryBlocks);
-
-  resolveFuncletAncestry(F, EntryBlocks);
-
   if (!DisableCleanups) {
     removeImplausibleTerminators(F);
 
@@ -1917,10 +905,6 @@ bool WinEHPrepare::prepareExplicitEH(
 
   BlockColors.clear();
   FuncletBlocks.clear();
-  FuncletChildren.clear();
-  FuncletParents.clear();
-  EstrangedBlocks.clear();
-  FuncletCloningRequired = false;
 
   return true;
 }
@@ -1930,9 +914,11 @@ bool WinEHPrepare::prepareExplicitEH(
 AllocaInst *WinEHPrepare::insertPHILoads(PHINode *PN, Function &F) {
   BasicBlock *PHIBlock = PN->getParent();
   AllocaInst *SpillSlot = nullptr;
+  Instruction *EHPad = PHIBlock->getFirstNonPHI();
 
-  if (isa<CleanupPadInst>(PHIBlock->getFirstNonPHI())) {
-    // Insert a load in place of the PHI and replace all uses.
+  if (!isa<TerminatorInst>(EHPad)) {
+    // If the EHPad isn't a terminator, then we can insert a load in this block
+    // that will dominate all uses.
     SpillSlot = new AllocaInst(PN->getType(), nullptr,
                                Twine(PN->getName(), ".wineh.spillslot"),
                                &F.getEntryBlock().front());
@@ -1942,16 +928,16 @@ AllocaInst *WinEHPrepare::insertPHILoads
     return SpillSlot;
   }
 
+  // Otherwise, we have a PHI on a terminator EHPad, and we give up and insert
+  // loads of the slot before every use.
   DenseMap<BasicBlock *, Value *> Loads;
   for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
        UI != UE;) {
     Use &U = *UI++;
     auto *UsingInst = cast<Instruction>(U.getUser());
-    BasicBlock *UsingBB = UsingInst->getParent();
-    if (UsingBB->isEHPad()) {
+    if (isa<PHINode>(UsingInst) && UsingInst->getParent()->isEHPad()) {
       // Use is on an EH pad phi.  Leave it alone; we'll insert loads and
       // stores for it separately.
-      assert(isa<PHINode>(UsingInst));
       continue;
     }
     replaceUseWithLoad(PN, U, SpillSlot, Loads, F);
@@ -2005,7 +991,7 @@ void WinEHPrepare::insertPHIStore(
     SmallVectorImpl<std::pair<BasicBlock *, Value *>> &Worklist) {
 
   if (PredBlock->isEHPad() &&
-      !isa<CleanupPadInst>(PredBlock->getFirstNonPHI())) {
+      isa<TerminatorInst>(PredBlock->getFirstNonPHI())) {
     // Pred is unsplittable, so we need to queue it on the worklist.
     Worklist.push_back({PredBlock, PredVal});
     return;
@@ -2065,10 +1051,10 @@ void WinEHPrepare::replaceUseWithLoad(Va
       Goto->setSuccessor(0, PHIBlock);
       CatchRet->setSuccessor(NewBlock);
       // Update the color mapping for the newly split edge.
-      SetVector<BasicBlock *> &ColorsForPHIBlock = BlockColors[PHIBlock];
+      ColorVector &ColorsForPHIBlock = BlockColors[PHIBlock];
       BlockColors[NewBlock] = ColorsForPHIBlock;
       for (BasicBlock *FuncletPad : ColorsForPHIBlock)
-        FuncletBlocks[FuncletPad].insert(NewBlock);
+        FuncletBlocks[FuncletPad].push_back(NewBlock);
       // Treat the new block as incoming for load insertion.
       IncomingBlock = NewBlock;
     }
@@ -2087,11 +1073,10 @@ void WinEHPrepare::replaceUseWithLoad(Va
   }
 }
 
-void WinEHFuncInfo::addIPToStateRange(const BasicBlock *PadBB,
+void WinEHFuncInfo::addIPToStateRange(const InvokeInst *II,
                                       MCSymbol *InvokeBegin,
                                       MCSymbol *InvokeEnd) {
-  assert(PadBB->isEHPad() && EHPadStateMap.count(PadBB->getFirstNonPHI()) &&
-         "should get EH pad BB with precomputed state");
-  InvokeToStateMap[InvokeBegin] =
-      std::make_pair(EHPadStateMap[PadBB->getFirstNonPHI()], InvokeEnd);
+  assert(InvokeStateMap.count(II) &&
+         "should get invoke with precomputed state");
+  LabelToStateMap[InvokeBegin] = std::make_pair(InvokeStateMap[II], InvokeEnd);
 }

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Fri Dec 11 23:38:55 2015
@@ -2890,19 +2890,36 @@ void AssemblyWriter::printInstruction(co
 
       writeOperand(LPI->getClause(i), true);
     }
-  } else if (const auto *CPI = dyn_cast<CatchPadInst>(&I)) {
+  } else if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(&I)) {
+    Out << " within ";
+    writeOperand(CatchSwitch->getParentPad(), /*PrintType=*/false);
     Out << " [";
-    for (unsigned Op = 0, NumOps = CPI->getNumArgOperands(); Op < NumOps;
+    unsigned Op = 0;
+    for (const BasicBlock *PadBB : CatchSwitch->handlers()) {
+      if (Op > 0)
+        Out << ", ";
+      writeOperand(PadBB, /*PrintType=*/true);
+      ++Op;
+    }
+    Out << "] unwind ";
+    if (const BasicBlock *UnwindDest = CatchSwitch->getUnwindDest())
+      writeOperand(UnwindDest, /*PrintType=*/true);
+    else
+      Out << "to caller";
+  } else if (const auto *FPI = dyn_cast<FuncletPadInst>(&I)) {
+    Out << " within ";
+    writeOperand(FPI->getParentPad(), /*PrintType=*/false);
+    Out << " [";
+    for (unsigned Op = 0, NumOps = FPI->getNumArgOperands(); Op < NumOps;
          ++Op) {
       if (Op > 0)
         Out << ", ";
-      writeOperand(CPI->getArgOperand(Op), /*PrintType=*/true);
+      writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
     }
-    Out << "]\n          to ";
-    writeOperand(CPI->getNormalDest(), /*PrintType=*/true);
-    Out << " unwind ";
-    writeOperand(CPI->getUnwindDest(), /*PrintType=*/true);
+    Out << ']';
   } else if (const auto *TPI = dyn_cast<TerminatePadInst>(&I)) {
+    Out << " within ";
+    writeOperand(TPI->getParentPad(), /*PrintType=*/false);
     Out << " [";
     for (unsigned Op = 0, NumOps = TPI->getNumArgOperands(); Op < NumOps;
          ++Op) {
@@ -2915,44 +2932,21 @@ void AssemblyWriter::printInstruction(co
       writeOperand(TPI->getUnwindDest(), /*PrintType=*/true);
     else
       Out << "to caller";
-  } else if (const auto *CPI = dyn_cast<CleanupPadInst>(&I)) {
-    Out << " [";
-    for (unsigned Op = 0, NumOps = CPI->getNumOperands(); Op < NumOps; ++Op) {
-      if (Op > 0)
-        Out << ", ";
-      writeOperand(CPI->getOperand(Op), /*PrintType=*/true);
-    }
-    Out << "]";
   } else if (isa<ReturnInst>(I) && !Operand) {
     Out << " void";
   } else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
-    Out << ' ';
-    writeOperand(CRI->getCatchPad(), /*PrintType=*/false);
+    Out << " from ";
+    writeOperand(CRI->getOperand(0), /*PrintType=*/false);
 
     Out << " to ";
-    writeOperand(CRI->getSuccessor(), /*PrintType=*/true);
+    writeOperand(CRI->getOperand(1), /*PrintType=*/true);
   } else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
-    Out << ' ';
-    writeOperand(CRI->getCleanupPad(), /*PrintType=*/false);
+    Out << " from ";
+    writeOperand(CRI->getOperand(0), /*PrintType=*/false);
 
     Out << " unwind ";
     if (CRI->hasUnwindDest())
-      writeOperand(CRI->getUnwindDest(), /*PrintType=*/true);
-    else
-      Out << "to caller";
-  } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(&I)) {
-    Out << " unwind ";
-    if (CEPI->hasUnwindDest())
-      writeOperand(CEPI->getUnwindDest(), /*PrintType=*/true);
-    else
-      Out << "to caller";
-  } else if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(&I)) {
-    Out << ' ';
-    writeOperand(CEPI->getCleanupPad(), /*PrintType=*/false);
-
-    Out << " unwind ";
-    if (CEPI->hasUnwindDest())
-      writeOperand(CEPI->getUnwindDest(), /*PrintType=*/true);
+      writeOperand(CRI->getOperand(1), /*PrintType=*/true);
     else
       Out << "to caller";
   } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {

Modified: llvm/trunk/lib/IR/Dominators.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Dominators.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Dominators.cpp (original)
+++ llvm/trunk/lib/IR/Dominators.cpp Fri Dec 11 23:38:55 2015
@@ -91,11 +91,11 @@ bool DominatorTree::dominates(const Inst
   if (Def == User)
     return false;
 
-  // The value defined by an invoke/catchpad dominates an instruction only if
-  // it dominates every instruction in UseBB.
-  // A PHI is dominated only if the instruction dominates every possible use
-  // in the UseBB.
-  if (isa<InvokeInst>(Def) || isa<CatchPadInst>(Def) || isa<PHINode>(User))
+  // The value defined by an invoke dominates an instruction only if it
+  // dominates every instruction in UseBB.
+  // A PHI is dominated only if the instruction dominates every possible use in
+  // the UseBB.
+  if (isa<InvokeInst>(Def) || isa<PHINode>(User))
     return dominates(Def, UseBB);
 
   if (DefBB != UseBB)
@@ -126,18 +126,13 @@ bool DominatorTree::dominates(const Inst
   if (DefBB == UseBB)
     return false;
 
-  // Invoke/CatchPad results are only usable in the normal destination, not in
-  // the exceptional destination.
+  // Invoke results are only usable in the normal destination, not in the
+  // exceptional destination.
   if (const auto *II = dyn_cast<InvokeInst>(Def)) {
     BasicBlock *NormalDest = II->getNormalDest();
     BasicBlockEdge E(DefBB, NormalDest);
     return dominates(E, UseBB);
   }
-  if (const auto *CPI = dyn_cast<CatchPadInst>(Def)) {
-    BasicBlock *NormalDest = CPI->getNormalDest();
-    BasicBlockEdge E(DefBB, NormalDest);
-    return dominates(E, UseBB);
-  }
 
   return dominates(DefBB, UseBB);
 }
@@ -239,8 +234,8 @@ bool DominatorTree::dominates(const Inst
   if (!isReachableFromEntry(DefBB))
     return false;
 
-  // Invoke/CatchPad instructions define their return values on the edges
-  // to their normal successors, so we have to handle them specially.
+  // Invoke instructions define their return values on the edges to their normal
+  // successors, so we have to handle them specially.
   // Among other things, this means they don't dominate anything in
   // their own block, except possibly a phi, so we don't need to
   // walk the block in any case.
@@ -249,11 +244,6 @@ bool DominatorTree::dominates(const Inst
     BasicBlockEdge E(DefBB, NormalDest);
     return dominates(E, U);
   }
-  if (const auto *CPI = dyn_cast<CatchPadInst>(Def)) {
-    BasicBlock *NormalDest = CPI->getNormalDest();
-    BasicBlockEdge E(DefBB, NormalDest);
-    return dominates(E, U);
-  }
 
   // If the def and use are in different blocks, do a simple CFG dominator
   // tree query.

Modified: llvm/trunk/lib/IR/Instruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instruction.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Instruction.cpp (original)
+++ llvm/trunk/lib/IR/Instruction.cpp Fri Dec 11 23:38:55 2015
@@ -202,11 +202,10 @@ const char *Instruction::getOpcodeName(u
   case Invoke: return "invoke";
   case Resume: return "resume";
   case Unreachable: return "unreachable";
-  case CleanupEndPad: return "cleanupendpad";
   case CleanupRet: return "cleanupret";
-  case CatchEndPad: return "catchendpad";
   case CatchRet: return "catchret";
   case CatchPad: return "catchpad";
+  case CatchSwitch: return "catchswitch";
   case TerminatePad: return "terminatepad";
 
   // Standard binary operators...
@@ -476,10 +475,8 @@ bool Instruction::mayThrow() const {
     return !CI->doesNotThrow();
   if (const auto *CRI = dyn_cast<CleanupReturnInst>(this))
     return CRI->unwindsToCaller();
-  if (const auto *CEPI = dyn_cast<CleanupEndPadInst>(this))
-    return CEPI->unwindsToCaller();
-  if (const auto *CEPI = dyn_cast<CatchEndPadInst>(this))
-    return CEPI->unwindsToCaller();
+  if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(this))
+    return CatchSwitch->unwindsToCaller();
   if (const auto *TPI = dyn_cast<TerminatePadInst>(this))
     return TPI->unwindsToCaller();
   return isa<ResumeInst>(this);

Modified: llvm/trunk/lib/IR/Instructions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Instructions.cpp (original)
+++ llvm/trunk/lib/IR/Instructions.cpp Fri Dec 11 23:38:55 2015
@@ -764,61 +764,6 @@ BasicBlock *ResumeInst::getSuccessorV(un
 }
 
 //===----------------------------------------------------------------------===//
-//                        CleanupEndPadInst Implementation
-//===----------------------------------------------------------------------===//
-
-CleanupEndPadInst::CleanupEndPadInst(const CleanupEndPadInst &CEPI)
-    : TerminatorInst(CEPI.getType(), Instruction::CleanupEndPad,
-                     OperandTraits<CleanupEndPadInst>::op_end(this) -
-                         CEPI.getNumOperands(),
-                     CEPI.getNumOperands()) {
-  setInstructionSubclassData(CEPI.getSubclassDataFromInstruction());
-  setCleanupPad(CEPI.getCleanupPad());
-  if (BasicBlock *UnwindDest = CEPI.getUnwindDest())
-    setUnwindDest(UnwindDest);
-}
-
-void CleanupEndPadInst::init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB) {
-  setCleanupPad(CleanupPad);
-  if (UnwindBB) {
-    setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
-    setUnwindDest(UnwindBB);
-  }
-}
-
-CleanupEndPadInst::CleanupEndPadInst(CleanupPadInst *CleanupPad,
-                                     BasicBlock *UnwindBB, unsigned Values,
-                                     Instruction *InsertBefore)
-    : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
-                     Instruction::CleanupEndPad,
-                     OperandTraits<CleanupEndPadInst>::op_end(this) - Values,
-                     Values, InsertBefore) {
-  init(CleanupPad, UnwindBB);
-}
-
-CleanupEndPadInst::CleanupEndPadInst(CleanupPadInst *CleanupPad,
-                                     BasicBlock *UnwindBB, unsigned Values,
-                                     BasicBlock *InsertAtEnd)
-    : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
-                     Instruction::CleanupEndPad,
-                     OperandTraits<CleanupEndPadInst>::op_end(this) - Values,
-                     Values, InsertAtEnd) {
-  init(CleanupPad, UnwindBB);
-}
-
-BasicBlock *CleanupEndPadInst::getSuccessorV(unsigned Idx) const {
-  assert(Idx == 0);
-  return getUnwindDest();
-}
-unsigned CleanupEndPadInst::getNumSuccessorsV() const {
-  return getNumSuccessors();
-}
-void CleanupEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
-  assert(Idx == 0);
-  setUnwindDest(B);
-}
-
-//===----------------------------------------------------------------------===//
 //                        CleanupReturnInst Implementation
 //===----------------------------------------------------------------------===//
 
@@ -828,23 +773,22 @@ CleanupReturnInst::CleanupReturnInst(con
                          CRI.getNumOperands(),
                      CRI.getNumOperands()) {
   setInstructionSubclassData(CRI.getSubclassDataFromInstruction());
-  Op<-1>() = CRI.Op<-1>();
+  Op<0>() = CRI.Op<0>();
   if (CRI.hasUnwindDest())
-    Op<-2>() = CRI.Op<-2>();
+    Op<1>() = CRI.Op<1>();
 }
 
-void CleanupReturnInst::init(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB) {
+void CleanupReturnInst::init(Value *CleanupPad, BasicBlock *UnwindBB) {
   if (UnwindBB)
     setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
 
-  Op<-1>() = CleanupPad;
+  Op<0>() = CleanupPad;
   if (UnwindBB)
-    Op<-2>() = UnwindBB;
+    Op<1>() = UnwindBB;
 }
 
-CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad,
-                                     BasicBlock *UnwindBB, unsigned Values,
-                                     Instruction *InsertBefore)
+CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB,
+                                     unsigned Values, Instruction *InsertBefore)
     : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
                      Instruction::CleanupRet,
                      OperandTraits<CleanupReturnInst>::op_end(this) - Values,
@@ -852,9 +796,8 @@ CleanupReturnInst::CleanupReturnInst(Cle
   init(CleanupPad, UnwindBB);
 }
 
-CleanupReturnInst::CleanupReturnInst(CleanupPadInst *CleanupPad,
-                                     BasicBlock *UnwindBB, unsigned Values,
-                                     BasicBlock *InsertAtEnd)
+CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB,
+                                     unsigned Values, BasicBlock *InsertAtEnd)
     : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
                      Instruction::CleanupRet,
                      OperandTraits<CleanupReturnInst>::op_end(this) - Values,
@@ -875,58 +818,9 @@ void CleanupReturnInst::setSuccessorV(un
 }
 
 //===----------------------------------------------------------------------===//
-//                        CatchEndPadInst Implementation
-//===----------------------------------------------------------------------===//
-
-CatchEndPadInst::CatchEndPadInst(const CatchEndPadInst &CRI)
-    : TerminatorInst(CRI.getType(), Instruction::CatchEndPad,
-                     OperandTraits<CatchEndPadInst>::op_end(this) -
-                         CRI.getNumOperands(),
-                     CRI.getNumOperands()) {
-  setInstructionSubclassData(CRI.getSubclassDataFromInstruction());
-  if (BasicBlock *UnwindDest = CRI.getUnwindDest())
-    setUnwindDest(UnwindDest);
-}
-
-void CatchEndPadInst::init(BasicBlock *UnwindBB) {
-  if (UnwindBB) {
-    setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
-    setUnwindDest(UnwindBB);
-  }
-}
-
-CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
-                                 unsigned Values, Instruction *InsertBefore)
-    : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
-                     OperandTraits<CatchEndPadInst>::op_end(this) - Values,
-                     Values, InsertBefore) {
-  init(UnwindBB);
-}
-
-CatchEndPadInst::CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB,
-                                 unsigned Values, BasicBlock *InsertAtEnd)
-    : TerminatorInst(Type::getVoidTy(C), Instruction::CatchEndPad,
-                     OperandTraits<CatchEndPadInst>::op_end(this) - Values,
-                     Values, InsertAtEnd) {
-  init(UnwindBB);
-}
-
-BasicBlock *CatchEndPadInst::getSuccessorV(unsigned Idx) const {
-  assert(Idx == 0);
-  return getUnwindDest();
-}
-unsigned CatchEndPadInst::getNumSuccessorsV() const {
-  return getNumSuccessors();
-}
-void CatchEndPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
-  assert(Idx == 0);
-  setUnwindDest(B);
-}
-
-//===----------------------------------------------------------------------===//
 //                        CatchReturnInst Implementation
 //===----------------------------------------------------------------------===//
-void CatchReturnInst::init(CatchPadInst *CatchPad, BasicBlock *BB) {
+void CatchReturnInst::init(Value *CatchPad, BasicBlock *BB) {
   Op<0>() = CatchPad;
   Op<1>() = BB;
 }
@@ -938,7 +832,7 @@ CatchReturnInst::CatchReturnInst(const C
   Op<1>() = CRI.Op<1>();
 }
 
-CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
+CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB,
                                  Instruction *InsertBefore)
     : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
                      OperandTraits<CatchReturnInst>::op_begin(this), 2,
@@ -946,7 +840,7 @@ CatchReturnInst::CatchReturnInst(CatchPa
   init(CatchPad, BB);
 }
 
-CatchReturnInst::CatchReturnInst(CatchPadInst *CatchPad, BasicBlock *BB,
+CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB,
                                  BasicBlock *InsertAtEnd)
     : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
                      OperandTraits<CatchReturnInst>::op_begin(this), 2,
@@ -967,64 +861,136 @@ void CatchReturnInst::setSuccessorV(unsi
 }
 
 //===----------------------------------------------------------------------===//
-//                        CatchPadInst Implementation
+//                       CatchSwitchInst Implementation
 //===----------------------------------------------------------------------===//
-void CatchPadInst::init(BasicBlock *IfNormal, BasicBlock *IfException,
-                        ArrayRef<Value *> Args, const Twine &NameStr) {
-  assert(getNumOperands() == 2 + Args.size() && "NumOperands not set up?");
-  Op<-2>() = IfNormal;
-  Op<-1>() = IfException;
-  std::copy(Args.begin(), Args.end(), op_begin());
+
+CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+                                 unsigned NumReservedValues,
+                                 const Twine &NameStr,
+                                 Instruction *InsertBefore)
+    : TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0,
+                     InsertBefore) {
+  if (UnwindDest)
+    ++NumReservedValues;
+  init(ParentPad, UnwindDest, NumReservedValues + 1);
   setName(NameStr);
 }
 
-CatchPadInst::CatchPadInst(const CatchPadInst &CPI)
-    : TerminatorInst(CPI.getType(), Instruction::CatchPad,
-                     OperandTraits<CatchPadInst>::op_end(this) -
-                         CPI.getNumOperands(),
-                     CPI.getNumOperands()) {
-  std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
+CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
+                                 unsigned NumReservedValues,
+                                 const Twine &NameStr, BasicBlock *InsertAtEnd)
+    : TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0,
+                     InsertAtEnd) {
+  if (UnwindDest)
+    ++NumReservedValues;
+  init(ParentPad, UnwindDest, NumReservedValues + 1);
+  setName(NameStr);
 }
 
-CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
-                           ArrayRef<Value *> Args, unsigned Values,
-                           const Twine &NameStr, Instruction *InsertBefore)
-    : TerminatorInst(Type::getTokenTy(IfNormal->getContext()),
-                     Instruction::CatchPad,
-                     OperandTraits<CatchPadInst>::op_end(this) - Values, Values,
-                     InsertBefore) {
-  init(IfNormal, IfException, Args, NameStr);
+CatchSwitchInst::CatchSwitchInst(const CatchSwitchInst &CSI)
+    : TerminatorInst(CSI.getType(), Instruction::CatchSwitch, nullptr,
+                     CSI.getNumOperands()) {
+  init(CSI.getParentPad(), CSI.getUnwindDest(), CSI.getNumOperands());
+  setNumHungOffUseOperands(ReservedSpace);
+  Use *OL = getOperandList();
+  const Use *InOL = CSI.getOperandList();
+  for (unsigned I = 1, E = ReservedSpace; I != E; ++I)
+    OL[I] = InOL[I];
 }
 
-CatchPadInst::CatchPadInst(BasicBlock *IfNormal, BasicBlock *IfException,
-                           ArrayRef<Value *> Args, unsigned Values,
-                           const Twine &NameStr, BasicBlock *InsertAtEnd)
-    : TerminatorInst(Type::getTokenTy(IfNormal->getContext()),
-                     Instruction::CatchPad,
-                     OperandTraits<CatchPadInst>::op_end(this) - Values, Values,
-                     InsertAtEnd) {
-  init(IfNormal, IfException, Args, NameStr);
+void CatchSwitchInst::init(Value *ParentPad, BasicBlock *UnwindDest,
+                           unsigned NumReservedValues) {
+  assert(ParentPad && NumReservedValues);
+
+  ReservedSpace = NumReservedValues;
+  setNumHungOffUseOperands(UnwindDest ? 2 : 1);
+  allocHungoffUses(ReservedSpace);
+
+  Op<0>() = ParentPad;
+  if (UnwindDest) {
+    setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
+    setUnwindDest(UnwindDest);
+  }
 }
 
-BasicBlock *CatchPadInst::getSuccessorV(unsigned Idx) const {
-  return getSuccessor(Idx);
+/// growOperands - grow operands - This grows the operand list in response to a
+/// push_back style of operation. This grows the number of ops by 2 times.
+void CatchSwitchInst::growOperands(unsigned Size) {
+  unsigned NumOperands = getNumOperands();
+  assert(NumOperands >= 1);
+  if (ReservedSpace >= NumOperands + Size)
+    return;
+  ReservedSpace = (NumOperands + Size / 2) * 2;
+  growHungoffUses(ReservedSpace);
 }
-unsigned CatchPadInst::getNumSuccessorsV() const {
+
+void CatchSwitchInst::addHandler(BasicBlock *Handler) {
+  unsigned OpNo = getNumOperands();
+  growOperands(1);
+  assert(OpNo < ReservedSpace && "Growing didn't work!");
+  setNumHungOffUseOperands(getNumOperands() + 1);
+  getOperandList()[OpNo] = Handler;
+}
+
+BasicBlock *CatchSwitchInst::getSuccessorV(unsigned idx) const {
+  return getSuccessor(idx);
+}
+unsigned CatchSwitchInst::getNumSuccessorsV() const {
   return getNumSuccessors();
 }
-void CatchPadInst::setSuccessorV(unsigned Idx, BasicBlock *B) {
-  return setSuccessor(Idx, B);
+void CatchSwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) {
+  setSuccessor(idx, B);
+}
+
+//===----------------------------------------------------------------------===//
+//                        FuncletPadInst Implementation
+//===----------------------------------------------------------------------===//
+void FuncletPadInst::init(Value *ParentPad, ArrayRef<Value *> Args,
+                          const Twine &NameStr) {
+  assert(getNumOperands() == 1 + Args.size() && "NumOperands not set up?");
+  std::copy(Args.begin(), Args.end(), op_begin());
+  setParentPad(ParentPad);
+  setName(NameStr);
+}
+
+FuncletPadInst::FuncletPadInst(const FuncletPadInst &FPI)
+    : Instruction(FPI.getType(), FPI.getOpcode(),
+                  OperandTraits<FuncletPadInst>::op_end(this) -
+                      FPI.getNumOperands(),
+                  FPI.getNumOperands()) {
+  std::copy(FPI.op_begin(), FPI.op_end(), op_begin());
+  setParentPad(FPI.getParentPad());
+}
+
+FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+                               ArrayRef<Value *> Args, unsigned Values,
+                               const Twine &NameStr, Instruction *InsertBefore)
+    : Instruction(ParentPad->getType(), Op,
+                  OperandTraits<FuncletPadInst>::op_end(this) - Values, Values,
+                  InsertBefore) {
+  init(ParentPad, Args, NameStr);
+}
+
+FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
+                               ArrayRef<Value *> Args, unsigned Values,
+                               const Twine &NameStr, BasicBlock *InsertAtEnd)
+    : Instruction(ParentPad->getType(), Op,
+                  OperandTraits<FuncletPadInst>::op_end(this) - Values, Values,
+                  InsertAtEnd) {
+  init(ParentPad, Args, NameStr);
 }
 
 //===----------------------------------------------------------------------===//
 //                        TerminatePadInst Implementation
 //===----------------------------------------------------------------------===//
-void TerminatePadInst::init(BasicBlock *BB, ArrayRef<Value *> Args) {
-  if (BB)
+void TerminatePadInst::init(Value *ParentPad, BasicBlock *BB,
+                            ArrayRef<Value *> Args) {
+  if (BB) {
     setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
-  if (BB)
-    Op<-1>() = BB;
-  std::copy(Args.begin(), Args.end(), op_begin());
+    setUnwindDest(BB);
+  }
+  std::copy(Args.begin(), Args.end(), arg_begin());
+  setParentPad(ParentPad);
 }
 
 TerminatePadInst::TerminatePadInst(const TerminatePadInst &TPI)
@@ -1036,22 +1002,24 @@ TerminatePadInst::TerminatePadInst(const
   std::copy(TPI.op_begin(), TPI.op_end(), op_begin());
 }
 
-TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
                                    ArrayRef<Value *> Args, unsigned Values,
                                    Instruction *InsertBefore)
-    : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
+    : TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
+                     Instruction::TerminatePad,
                      OperandTraits<TerminatePadInst>::op_end(this) - Values,
                      Values, InsertBefore) {
-  init(BB, Args);
+  init(ParentPad, BB, Args);
 }
 
-TerminatePadInst::TerminatePadInst(LLVMContext &C, BasicBlock *BB,
+TerminatePadInst::TerminatePadInst(Value *ParentPad, BasicBlock *BB,
                                    ArrayRef<Value *> Args, unsigned Values,
                                    BasicBlock *InsertAtEnd)
-    : TerminatorInst(Type::getVoidTy(C), Instruction::TerminatePad,
+    : TerminatorInst(Type::getVoidTy(ParentPad->getContext()),
+                     Instruction::TerminatePad,
                      OperandTraits<TerminatePadInst>::op_end(this) - Values,
                      Values, InsertAtEnd) {
-  init(BB, Args);
+  init(ParentPad, BB, Args);
 }
 
 BasicBlock *TerminatePadInst::getSuccessorV(unsigned Idx) const {
@@ -1067,39 +1035,6 @@ void TerminatePadInst::setSuccessorV(uns
 }
 
 //===----------------------------------------------------------------------===//
-//                        CleanupPadInst Implementation
-//===----------------------------------------------------------------------===//
-void CleanupPadInst::init(ArrayRef<Value *> Args, const Twine &NameStr) {
-  assert(getNumOperands() == Args.size() && "NumOperands not set up?");
-  std::copy(Args.begin(), Args.end(), op_begin());
-  setName(NameStr);
-}
-
-CleanupPadInst::CleanupPadInst(const CleanupPadInst &CPI)
-    : Instruction(CPI.getType(), Instruction::CleanupPad,
-                  OperandTraits<CleanupPadInst>::op_end(this) -
-                      CPI.getNumOperands(),
-                  CPI.getNumOperands()) {
-  std::copy(CPI.op_begin(), CPI.op_end(), op_begin());
-}
-
-CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
-                               const Twine &NameStr, Instruction *InsertBefore)
-    : Instruction(Type::getTokenTy(C), Instruction::CleanupPad,
-                  OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
-                  Args.size(), InsertBefore) {
-  init(Args, NameStr);
-}
-
-CleanupPadInst::CleanupPadInst(LLVMContext &C, ArrayRef<Value *> Args,
-                               const Twine &NameStr, BasicBlock *InsertAtEnd)
-    : Instruction(Type::getTokenTy(C), Instruction::CleanupPad,
-                  OperandTraits<CleanupPadInst>::op_end(this) - Args.size(),
-                  Args.size(), InsertAtEnd) {
-  init(Args, NameStr);
-}
-
-//===----------------------------------------------------------------------===//
 //                      UnreachableInst Implementation
 //===----------------------------------------------------------------------===//
 
@@ -4074,32 +4009,24 @@ InvokeInst *InvokeInst::cloneImpl() cons
 
 ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
 
-CleanupEndPadInst *CleanupEndPadInst::cloneImpl() const {
-  return new (getNumOperands()) CleanupEndPadInst(*this);
-}
-
 CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
   return new (getNumOperands()) CleanupReturnInst(*this);
 }
 
-CatchEndPadInst *CatchEndPadInst::cloneImpl() const {
-  return new (getNumOperands()) CatchEndPadInst(*this);
-}
-
 CatchReturnInst *CatchReturnInst::cloneImpl() const {
   return new (getNumOperands()) CatchReturnInst(*this);
 }
 
-CatchPadInst *CatchPadInst::cloneImpl() const {
-  return new (getNumOperands()) CatchPadInst(*this);
+CatchSwitchInst *CatchSwitchInst::cloneImpl() const {
+  return new CatchSwitchInst(*this);
 }
 
-TerminatePadInst *TerminatePadInst::cloneImpl() const {
-  return new (getNumOperands()) TerminatePadInst(*this);
+FuncletPadInst *FuncletPadInst::cloneImpl() const {
+  return new (getNumOperands()) FuncletPadInst(*this);
 }
 
-CleanupPadInst *CleanupPadInst::cloneImpl() const {
-  return new (getNumOperands()) CleanupPadInst(*this);
+TerminatePadInst *TerminatePadInst::cloneImpl() const {
+  return new (getNumOperands()) TerminatePadInst(*this);
 }
 
 UnreachableInst *UnreachableInst::cloneImpl() const {

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Dec 11 23:38:55 2015
@@ -399,9 +399,9 @@ private:
   void visitEHPadPredecessors(Instruction &I);
   void visitLandingPadInst(LandingPadInst &LPI);
   void visitCatchPadInst(CatchPadInst &CPI);
-  void visitCatchEndPadInst(CatchEndPadInst &CEPI);
+  void visitCatchReturnInst(CatchReturnInst &CatchReturn);
   void visitCleanupPadInst(CleanupPadInst &CPI);
-  void visitCleanupEndPadInst(CleanupEndPadInst &CEPI);
+  void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch);
   void visitCleanupReturnInst(CleanupReturnInst &CRI);
   void visitTerminatePadInst(TerminatePadInst &TPI);
 
@@ -2885,25 +2885,24 @@ void Verifier::visitEHPadPredecessors(In
     }
     return;
   }
+  if (auto *CPI = dyn_cast<CatchPadInst>(&I)) {
+    if (!pred_empty(BB))
+      Assert(BB->getUniquePredecessor() == CPI->getCatchSwitch()->getParent(),
+             "Block containg CatchPadInst must be jumped to "
+             "only by its catchswitch.",
+             CPI);
+    return;
+  }
 
   for (BasicBlock *PredBB : predecessors(BB)) {
     TerminatorInst *TI = PredBB->getTerminator();
-    if (auto *II = dyn_cast<InvokeInst>(TI))
+    if (auto *II = dyn_cast<InvokeInst>(TI)) {
       Assert(II->getUnwindDest() == BB && II->getNormalDest() != BB,
              "EH pad must be jumped to via an unwind edge", &I, II);
-    else if (auto *CPI = dyn_cast<CatchPadInst>(TI))
-      Assert(CPI->getUnwindDest() == BB && CPI->getNormalDest() != BB,
-             "EH pad must be jumped to via an unwind edge", &I, CPI);
-    else if (isa<CatchEndPadInst>(TI))
-      ;
-    else if (isa<CleanupReturnInst>(TI))
-      ;
-    else if (isa<CleanupEndPadInst>(TI))
-      ;
-    else if (isa<TerminatePadInst>(TI))
-      ;
-    else
+    } else if (!isa<CleanupReturnInst>(TI) && !isa<TerminatePadInst>(TI) &&
+               !isa<CatchSwitchInst>(TI)) {
       Assert(false, "EH pad must be jumped to via an unwind edge", &I, TI);
+    }
   }
 }
 
@@ -2952,67 +2951,29 @@ void Verifier::visitCatchPadInst(CatchPa
   visitEHPadPredecessors(CPI);
 
   BasicBlock *BB = CPI.getParent();
+
   Function *F = BB->getParent();
   Assert(F->hasPersonalityFn(),
          "CatchPadInst needs to be in a function with a personality.", &CPI);
 
+  Assert(isa<CatchSwitchInst>(CPI.getParentPad()),
+         "CatchPadInst needs to be directly nested in a CatchSwitchInst.",
+         CPI.getParentPad());
+
   // The catchpad instruction must be the first non-PHI instruction in the
   // block.
   Assert(BB->getFirstNonPHI() == &CPI,
-         "CatchPadInst not the first non-PHI instruction in the block.",
-         &CPI);
-
-  if (!BB->getSinglePredecessor())
-    for (BasicBlock *PredBB : predecessors(BB)) {
-      Assert(!isa<CatchPadInst>(PredBB->getTerminator()),
-             "CatchPadInst with CatchPadInst predecessor cannot have any other "
-             "predecessors.",
-             &CPI);
-    }
-
-  BasicBlock *UnwindDest = CPI.getUnwindDest();
-  Instruction *I = UnwindDest->getFirstNonPHI();
-  Assert(
-      isa<CatchPadInst>(I) || isa<CatchEndPadInst>(I),
-      "CatchPadInst must unwind to a CatchPadInst or a CatchEndPadInst.",
-      &CPI);
+         "CatchPadInst not the first non-PHI instruction in the block.", &CPI);
 
-  visitTerminatorInst(CPI);
+  visitInstruction(CPI);
 }
 
-void Verifier::visitCatchEndPadInst(CatchEndPadInst &CEPI) {
-  visitEHPadPredecessors(CEPI);
-
-  BasicBlock *BB = CEPI.getParent();
-  Function *F = BB->getParent();
-  Assert(F->hasPersonalityFn(),
-         "CatchEndPadInst needs to be in a function with a personality.",
-         &CEPI);
+void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) {
+  Assert(isa<CatchPadInst>(CatchReturn.getOperand(0)),
+         "CatchReturnInst needs to be provided a CatchPad", &CatchReturn,
+         CatchReturn.getOperand(0));
 
-  // The catchendpad instruction must be the first non-PHI instruction in the
-  // block.
-  Assert(BB->getFirstNonPHI() == &CEPI,
-         "CatchEndPadInst not the first non-PHI instruction in the block.",
-         &CEPI);
-
-  unsigned CatchPadsSeen = 0;
-  for (BasicBlock *PredBB : predecessors(BB))
-    if (isa<CatchPadInst>(PredBB->getTerminator()))
-      ++CatchPadsSeen;
-
-  Assert(CatchPadsSeen <= 1, "CatchEndPadInst must have no more than one "
-                               "CatchPadInst predecessor.",
-         &CEPI);
-
-  if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
-    Instruction *I = UnwindDest->getFirstNonPHI();
-    Assert(
-        I->isEHPad() && !isa<LandingPadInst>(I),
-        "CatchEndPad must unwind to an EH block which is not a landingpad.",
-        &CEPI);
-  }
-
-  visitTerminatorInst(CEPI);
+  visitTerminatorInst(CatchReturn);
 }
 
 void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
@@ -3030,57 +2991,76 @@ void Verifier::visitCleanupPadInst(Clean
          "CleanupPadInst not the first non-PHI instruction in the block.",
          &CPI);
 
+  auto *ParentPad = CPI.getParentPad();
+  Assert(isa<CatchSwitchInst>(ParentPad) || isa<ConstantTokenNone>(ParentPad) ||
+             isa<CleanupPadInst>(ParentPad) || isa<CatchPadInst>(ParentPad),
+         "CleanupPadInst has an invalid parent.", &CPI);
+
   User *FirstUser = nullptr;
   BasicBlock *FirstUnwindDest = nullptr;
   for (User *U : CPI.users()) {
     BasicBlock *UnwindDest;
     if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(U)) {
       UnwindDest = CRI->getUnwindDest();
+    } else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U) ||
+               isa<TerminatePadInst>(U)) {
+      continue;
     } else {
-      UnwindDest = cast<CleanupEndPadInst>(U)->getUnwindDest();
+      Assert(false, "bogus cleanuppad use", &CPI);
     }
 
     if (!FirstUser) {
       FirstUser = U;
       FirstUnwindDest = UnwindDest;
     } else {
-      Assert(UnwindDest == FirstUnwindDest,
-             "Cleanuprets/cleanupendpads from the same cleanuppad must "
-             "have the same unwind destination",
-             FirstUser, U);
+      Assert(
+          UnwindDest == FirstUnwindDest,
+          "cleanupret instructions from the same cleanuppad must have the same "
+          "unwind destination",
+          FirstUser, U);
     }
   }
 
   visitInstruction(CPI);
 }
 
-void Verifier::visitCleanupEndPadInst(CleanupEndPadInst &CEPI) {
-  visitEHPadPredecessors(CEPI);
+void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) {
+  visitEHPadPredecessors(CatchSwitch);
+
+  BasicBlock *BB = CatchSwitch.getParent();
 
-  BasicBlock *BB = CEPI.getParent();
   Function *F = BB->getParent();
   Assert(F->hasPersonalityFn(),
-         "CleanupEndPadInst needs to be in a function with a personality.",
-         &CEPI);
+         "CatchSwitchInst needs to be in a function with a personality.",
+         &CatchSwitch);
 
-  // The cleanupendpad instruction must be the first non-PHI instruction in the
+  // The catchswitch instruction must be the first non-PHI instruction in the
   // block.
-  Assert(BB->getFirstNonPHI() == &CEPI,
-         "CleanupEndPadInst not the first non-PHI instruction in the block.",
-         &CEPI);
+  Assert(BB->getFirstNonPHI() == &CatchSwitch,
+         "CatchSwitchInst not the first non-PHI instruction in the block.",
+         &CatchSwitch);
 
-  if (BasicBlock *UnwindDest = CEPI.getUnwindDest()) {
+  if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) {
     Instruction *I = UnwindDest->getFirstNonPHI();
-    Assert(
-        I->isEHPad() && !isa<LandingPadInst>(I),
-        "CleanupEndPad must unwind to an EH block which is not a landingpad.",
-        &CEPI);
+    Assert(I->isEHPad() && !isa<LandingPadInst>(I),
+           "CatchSwitchInst must unwind to an EH block which is not a "
+           "landingpad.",
+           &CatchSwitch);
   }
 
-  visitTerminatorInst(CEPI);
+  auto *ParentPad = CatchSwitch.getParentPad();
+  Assert(isa<CatchSwitchInst>(ParentPad) || isa<ConstantTokenNone>(ParentPad) ||
+             isa<CleanupPadInst>(ParentPad) || isa<CatchPadInst>(ParentPad),
+         "CatchSwitchInst has an invalid parent.", ParentPad);
+
+  visitTerminatorInst(CatchSwitch);
 }
 
 void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) {
+  Assert(isa<CleanupPadInst>(CRI.getOperand(0)),
+         "CleanupReturnInst needs to be provided a CleanupPad", &CRI,
+         CRI.getOperand(0));
+
   if (BasicBlock *UnwindDest = CRI.getUnwindDest()) {
     Instruction *I = UnwindDest->getFirstNonPHI();
     Assert(I->isEHPad() && !isa<LandingPadInst>(I),
@@ -3115,6 +3095,11 @@ void Verifier::visitTerminatePadInst(Ter
            &TPI);
   }
 
+  auto *ParentPad = TPI.getParentPad();
+  Assert(isa<CatchSwitchInst>(ParentPad) || isa<ConstantTokenNone>(ParentPad) ||
+             isa<CleanupPadInst>(ParentPad) || isa<CatchPadInst>(ParentPad),
+         "TerminatePadInst has an invalid parent.", ParentPad);
+
   visitTerminatorInst(TPI);
 }
 

Modified: llvm/trunk/lib/Target/X86/X86WinEHState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinEHState.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86WinEHState.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86WinEHState.cpp Fri Dec 11 23:38:55 2015
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "X86.h"
+#include "llvm/Analysis/CFG.h"
 #include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/Passes.h"
@@ -416,20 +417,33 @@ void WinEHStatePass::addStateStores(Func
     calculateWinCXXEHStateNumbers(&F, FuncInfo);
 
   // Iterate all the instructions and emit state number stores.
+  DenseMap<BasicBlock *, ColorVector> BlockColors = colorEHFunclets(F);
   for (BasicBlock &BB : F) {
+    // Figure out what state we should assign calls in this block.
+    int BaseState = -1;
+    auto &BBColors = BlockColors[&BB];
+
+    assert(BBColors.size() == 1 &&
+           "multi-color BB not removed by preparation");
+    BasicBlock *FuncletEntryBB = BBColors.front();
+    if (auto *FuncletPad =
+            dyn_cast<FuncletPadInst>(FuncletEntryBB->getFirstNonPHI())) {
+      auto BaseStateI = FuncInfo.FuncletBaseStateMap.find(FuncletPad);
+      if (BaseStateI != FuncInfo.FuncletBaseStateMap.end())
+        BaseState = BaseStateI->second;
+    }
+
     for (Instruction &I : BB) {
       if (auto *CI = dyn_cast<CallInst>(&I)) {
         // Possibly throwing call instructions have no actions to take after
         // an unwind. Ensure they are in the -1 state.
         if (CI->doesNotThrow())
           continue;
-        insertStateNumberStore(RegNode, CI, -1);
+        insertStateNumberStore(RegNode, CI, BaseState);
       } else if (auto *II = dyn_cast<InvokeInst>(&I)) {
         // Look up the state number of the landingpad this unwinds to.
-        Instruction *PadInst = II->getUnwindDest()->getFirstNonPHI();
-        // FIXME: Why does this assertion fail?
-        //assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
-        int State = FuncInfo.EHPadStateMap[PadInst];
+        assert(FuncInfo.InvokeStateMap.count(II) && "invoke has no state!");
+        int State = FuncInfo.InvokeStateMap[II];
         insertStateNumberStore(RegNode, II, State);
       }
     }

Modified: llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp Fri Dec 11 23:38:55 2015
@@ -2684,12 +2684,12 @@ struct MemorySanitizerVisitor : public I
     setOrigin(&I, getCleanOrigin());
   }
 
-  void visitCleanupPadInst(CleanupPadInst &I) {
+  void visitCatchSwitchInst(CatchSwitchInst &I) {
     setShadow(&I, getCleanShadow(&I));
     setOrigin(&I, getCleanOrigin());
   }
 
-  void visitCatchPad(CatchPadInst &I) {
+  void visitFuncletPadInst(FuncletPadInst &I) {
     setShadow(&I, getCleanShadow(&I));
     setOrigin(&I, getCleanOrigin());
   }
@@ -2699,16 +2699,6 @@ struct MemorySanitizerVisitor : public I
     // Nothing to do here.
   }
 
-  void visitCatchEndPadInst(CatchEndPadInst &I) {
-    DEBUG(dbgs() << "CatchEndPad: " << I << "\n");
-    // Nothing to do here.
-  }
-
-  void visitCleanupEndPadInst(CleanupEndPadInst &I) {
-    DEBUG(dbgs() << "CleanupEndPad: " << I << "\n");
-    // Nothing to do here.
-  }
-
   void visitGetElementPtrInst(GetElementPtrInst &I) {
     handleShadowOr(I);
   }

Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Fri Dec 11 23:38:55 2015
@@ -947,8 +947,6 @@ static Value *NegateValue(Value *V, Inst
     if (Instruction *InstInput = dyn_cast<Instruction>(V)) {
       if (InvokeInst *II = dyn_cast<InvokeInst>(InstInput)) {
         InsertPt = II->getNormalDest()->begin();
-      } else if (auto *CPI = dyn_cast<CatchPadInst>(InstInput)) {
-        InsertPt = CPI->getNormalDest()->begin();
       } else {
         InsertPt = ++InstInput->getIterator();
       }

Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Fri Dec 11 23:38:55 2015
@@ -480,8 +480,10 @@ private:
   void visitExtractValueInst(ExtractValueInst &EVI);
   void visitInsertValueInst(InsertValueInst &IVI);
   void visitLandingPadInst(LandingPadInst &I) { markAnythingOverdefined(&I); }
-  void visitCleanupPadInst(CleanupPadInst &CPI) { markAnythingOverdefined(&CPI); }
-  void visitCatchPadInst(CatchPadInst &CPI) {
+  void visitFuncletPadInst(FuncletPadInst &FPI) {
+    markAnythingOverdefined(&FPI);
+  }
+  void visitCatchSwitchInst(CatchSwitchInst &CPI) {
     markAnythingOverdefined(&CPI);
     visitTerminatorInst(CPI);
   }

Modified: llvm/trunk/lib/Transforms/Scalar/Sink.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Sink.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Sink.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Sink.cpp Fri Dec 11 23:38:55 2015
@@ -169,7 +169,8 @@ static bool isSafeToMove(Instruction *In
         return false;
   }
 
-  if (isa<TerminatorInst>(Inst) || isa<PHINode>(Inst) || Inst->isEHPad())
+  if (isa<TerminatorInst>(Inst) || isa<PHINode>(Inst) || Inst->isEHPad() ||
+      Inst->mayThrow())
     return false;
 
   // Convergent operations cannot be made control-dependent on additional
@@ -194,6 +195,11 @@ bool Sinking::IsAcceptableTarget(Instruc
   if (Inst->getParent() == SuccToSinkTo)
     return false;
 
+  // It's never legal to sink an instruction into a block which terminates in an
+  // EH-pad.
+  if (SuccToSinkTo->getTerminator()->isExceptional())
+    return false;
+
   // If the block has multiple predecessors, this would introduce computation
   // on different code paths.  We could split the critical edge, but for now we
   // just punt.

Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Fri Dec 11 23:38:55 2015
@@ -560,8 +560,8 @@ emitCallAndSwitchStatement(Function *new
           // Restore values just before we exit
           Function::arg_iterator OAI = OutputArgBegin;
           for (unsigned out = 0, e = outputs.size(); out != e; ++out) {
-            // For an invoke/catchpad, the normal destination is the only one
-            // that is dominated by the result of the invocation
+            // For an invoke, the normal destination is the only one that is
+            // dominated by the result of the invocation
             BasicBlock *DefBlock = cast<Instruction>(outputs[out])->getParent();
 
             bool DominatesDef = true;
@@ -569,8 +569,6 @@ emitCallAndSwitchStatement(Function *new
             BasicBlock *NormalDest = nullptr;
             if (auto *Invoke = dyn_cast<InvokeInst>(outputs[out]))
               NormalDest = Invoke->getNormalDest();
-            if (auto *CatchPad = dyn_cast<CatchPadInst>(outputs[out]))
-              NormalDest = CatchPad->getNormalDest();
 
             if (NormalDest) {
               DefBlock = NormalDest;

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Fri Dec 11 23:38:55 2015
@@ -21,6 +21,7 @@
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/EHPersonalities.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Attributes.h"
@@ -192,8 +193,6 @@ HandleCallsInBlockInlinedThroughInvoke(B
     // instructions require no special handling.
     CallInst *CI = dyn_cast<CallInst>(I);
 
-    // If this call cannot unwind, don't convert it to an invoke.
-    // Inline asm calls cannot throw.
     if (!CI || CI->doesNotThrow() || isa<InlineAsm>(CI->getCalledValue()))
       continue;
 
@@ -327,40 +326,10 @@ static void HandleInlinedEHPad(InvokeIns
     }
   };
 
-  // Forward EH terminator instructions to the caller's invoke destination.
-  // This is as simple as connect all the instructions which 'unwind to caller'
-  // to the invoke destination.
+  // This connects all the instructions which 'unwind to caller' to the invoke
+  // destination.
   for (Function::iterator BB = FirstNewBlock->getIterator(), E = Caller->end();
        BB != E; ++BB) {
-    Instruction *I = BB->getFirstNonPHI();
-    if (I->isEHPad()) {
-      if (auto *CEPI = dyn_cast<CatchEndPadInst>(I)) {
-        if (CEPI->unwindsToCaller()) {
-          CatchEndPadInst::Create(CEPI->getContext(), UnwindDest, CEPI);
-          CEPI->eraseFromParent();
-          UpdatePHINodes(&*BB);
-        }
-      } else if (auto *CEPI = dyn_cast<CleanupEndPadInst>(I)) {
-        if (CEPI->unwindsToCaller()) {
-          CleanupEndPadInst::Create(CEPI->getCleanupPad(), UnwindDest, CEPI);
-          CEPI->eraseFromParent();
-          UpdatePHINodes(&*BB);
-        }
-      } else if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
-        if (TPI->unwindsToCaller()) {
-          SmallVector<Value *, 3> TerminatePadArgs;
-          for (Value *ArgOperand : TPI->arg_operands())
-            TerminatePadArgs.push_back(ArgOperand);
-          TerminatePadInst::Create(TPI->getContext(), UnwindDest,
-                                   TerminatePadArgs, TPI);
-          TPI->eraseFromParent();
-          UpdatePHINodes(&*BB);
-        }
-      } else {
-        assert(isa<CatchPadInst>(I) || isa<CleanupPadInst>(I));
-      }
-    }
-
     if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
       if (CRI->unwindsToCaller()) {
         CleanupReturnInst::Create(CRI->getCleanupPad(), UnwindDest, CRI);
@@ -368,6 +337,40 @@ static void HandleInlinedEHPad(InvokeIns
         UpdatePHINodes(&*BB);
       }
     }
+
+    Instruction *I = BB->getFirstNonPHI();
+    if (!I->isEHPad())
+      continue;
+
+    Instruction *Replacement = nullptr;
+    if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
+      if (TPI->unwindsToCaller()) {
+        SmallVector<Value *, 3> TerminatePadArgs;
+        for (Value *ArgOperand : TPI->arg_operands())
+          TerminatePadArgs.push_back(ArgOperand);
+        Replacement = TerminatePadInst::Create(TPI->getParentPad(), UnwindDest,
+                                               TerminatePadArgs, TPI);
+      }
+    } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
+      if (CatchSwitch->unwindsToCaller()) {
+        auto *NewCatchSwitch = CatchSwitchInst::Create(
+            CatchSwitch->getParentPad(), UnwindDest,
+            CatchSwitch->getNumHandlers(), CatchSwitch->getName(),
+            CatchSwitch);
+        for (BasicBlock *PadBB : CatchSwitch->handlers())
+          NewCatchSwitch->addHandler(PadBB);
+        Replacement = NewCatchSwitch;
+      }
+    } else if (!isa<FuncletPadInst>(I)) {
+      llvm_unreachable("unexpected EHPad!");
+    }
+
+    if (Replacement) {
+      Replacement->takeName(I);
+      I->replaceAllUsesWith(Replacement);
+      I->eraseFromParent();
+      UpdatePHINodes(&*BB);
+    }
   }
 
   if (InlinedCodeInfo.ContainsCalls)
@@ -1090,6 +1093,53 @@ bool llvm::InlineFunction(CallSite CS, I
       return false;
   }
 
+  // We need to figure out which funclet the callsite was in so that we may
+  // properly nest the callee.
+  Instruction *CallSiteEHPad = nullptr;
+  if (CalledPersonality && CallerPersonality) {
+    EHPersonality Personality = classifyEHPersonality(CalledPersonality);
+    if (isFuncletEHPersonality(Personality)) {
+      DenseMap<BasicBlock *, ColorVector> CallerBlockColors =
+          colorEHFunclets(*Caller);
+      ColorVector &CallSiteColors = CallerBlockColors[OrigBB];
+      size_t NumColors = CallSiteColors.size();
+      // There is no single parent, inlining will not succeed.
+      if (NumColors > 1)
+        return false;
+      if (NumColors == 1) {
+        BasicBlock *CallSiteFuncletBB = CallSiteColors.front();
+        if (CallSiteFuncletBB != Caller->begin()) {
+          CallSiteEHPad = CallSiteFuncletBB->getFirstNonPHI();
+          assert(CallSiteEHPad->isEHPad() && "Expected an EHPad!");
+        }
+      }
+
+      // OK, the inlining site is legal.  What about the target function?
+
+      if (CallSiteEHPad) {
+        if (Personality == EHPersonality::MSVC_CXX) {
+          // The MSVC personality cannot tolerate catches getting inlined into
+          // cleanup funclets.
+          if (isa<CleanupPadInst>(CallSiteEHPad)) {
+            // Ok, the call site is within a cleanuppad.  Let's check the callee
+            // for catchpads.
+            for (const BasicBlock &CalledBB : *CalledFunc) {
+              if (isa<CatchPadInst>(CalledBB.getFirstNonPHI()))
+                return false;
+            }
+          }
+        } else if (isAsynchronousEHPersonality(Personality)) {
+          // SEH is even less tolerant, there may not be any sort of exceptional
+          // funclet in the callee.
+          for (const BasicBlock &CalledBB : *CalledFunc) {
+            if (CalledBB.isEHPad())
+              return false;
+          }
+        }
+      }
+    }
+  }
+
   // Get an iterator to the last basic block in the function, which will have
   // the new function inlined after it.
   Function::iterator LastBlock = --Caller->end();
@@ -1381,6 +1431,30 @@ bool llvm::InlineFunction(CallSite CS, I
     }
   }
 
+  // Update the lexical scopes of the new funclets.  Anything that had 'none' as
+  // its parent is now nested inside the callsite's EHPad.
+  if (CallSiteEHPad) {
+    for (Function::iterator BB = FirstNewBlock->getIterator(),
+                            E = Caller->end();
+         BB != E; ++BB) {
+      Instruction *I = BB->getFirstNonPHI();
+      if (!I->isEHPad())
+        continue;
+
+      if (auto *TPI = dyn_cast<TerminatePadInst>(I)) {
+        if (isa<ConstantTokenNone>(TPI->getParentPad()))
+          TPI->setParentPad(CallSiteEHPad);
+      } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
+        if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
+          CatchSwitch->setParentPad(CallSiteEHPad);
+      } else {
+        auto *FPI = cast<FuncletPadInst>(I);
+        if (isa<ConstantTokenNone>(FPI->getParentPad()))
+          FPI->setParentPad(CallSiteEHPad);
+      }
+    }
+  }
+
   // If we are inlining for an invoke instruction, we must make sure to rewrite
   // any call instructions into invoke instructions.
   if (auto *II = dyn_cast<InvokeInst>(TheCall)) {

Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LCSSA.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LCSSA.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Fri Dec 11 23:38:55 2015
@@ -84,15 +84,13 @@ static bool processInstruction(Loop &L,
 
   ++NumLCSSA; // We are applying the transformation
 
-  // Invoke/CatchPad instructions are special in that their result value is not
-  // available along their unwind edge. The code below tests to see whether
-  // DomBB dominates the value, so adjust DomBB to the normal destination block,
+  // Invoke instructions are special in that their result value is not available
+  // along their unwind edge. The code below tests to see whether DomBB
+  // dominates the value, so adjust DomBB to the normal destination block,
   // which is effectively where the value is first usable.
   BasicBlock *DomBB = Inst.getParent();
   if (InvokeInst *Inv = dyn_cast<InvokeInst>(&Inst))
     DomBB = Inv->getNormalDest();
-  if (auto *CPI = dyn_cast<CatchPadInst>(&Inst))
-    DomBB = CPI->getNormalDest();
 
   DomTreeNode *DomNode = DT.getNode(DomBB);
 

Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Fri Dec 11 23:38:55 2015
@@ -1338,19 +1338,22 @@ void llvm::removeUnwindEdge(BasicBlock *
   if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
     NewTI = CleanupReturnInst::Create(CRI->getCleanupPad(), nullptr, CRI);
     UnwindDest = CRI->getUnwindDest();
-  } else if (auto *CEP = dyn_cast<CleanupEndPadInst>(TI)) {
-    NewTI = CleanupEndPadInst::Create(CEP->getCleanupPad(), nullptr, CEP);
-    UnwindDest = CEP->getUnwindDest();
-  } else if (auto *CEP = dyn_cast<CatchEndPadInst>(TI)) {
-    NewTI = CatchEndPadInst::Create(CEP->getContext(), nullptr, CEP);
-    UnwindDest = CEP->getUnwindDest();
   } else if (auto *TPI = dyn_cast<TerminatePadInst>(TI)) {
     SmallVector<Value *, 3> TerminatePadArgs;
     for (Value *Operand : TPI->arg_operands())
       TerminatePadArgs.push_back(Operand);
-    NewTI = TerminatePadInst::Create(TPI->getContext(), nullptr,
+    NewTI = TerminatePadInst::Create(TPI->getParentPad(), nullptr,
                                      TerminatePadArgs, TPI);
     UnwindDest = TPI->getUnwindDest();
+  } else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(TI)) {
+    auto *NewCatchSwitch = CatchSwitchInst::Create(
+        CatchSwitch->getParentPad(), nullptr, CatchSwitch->getNumHandlers(),
+        CatchSwitch->getName(), CatchSwitch);
+    for (BasicBlock *PadBB : CatchSwitch->handlers())
+      NewCatchSwitch->addHandler(PadBB);
+
+    NewTI = NewCatchSwitch;
+    UnwindDest = CatchSwitch->getUnwindDest();
   } else {
     llvm_unreachable("Could not find unwind successor");
   }
@@ -1358,6 +1361,7 @@ void llvm::removeUnwindEdge(BasicBlock *
   NewTI->takeName(TI);
   NewTI->setDebugLoc(TI->getDebugLoc());
   UnwindDest->removePredecessor(BB);
+  TI->replaceAllUsesWith(NewTI);
   TI->eraseFromParent();
 }
 

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Fri Dec 11 23:38:55 2015
@@ -3254,8 +3254,8 @@ bool SimplifyCFGOpt::SimplifyCleanupRetu
   // updated to continue to the unwind destination of the cleanup pad being
   // simplified.
   BasicBlock *BB = RI->getParent();
-  Instruction *CPInst = dyn_cast<CleanupPadInst>(BB->getFirstNonPHI());
-  if (!CPInst)
+  CleanupPadInst *CPInst = RI->getCleanupPad();
+  if (CPInst->getParent() != BB)
     // This isn't an empty cleanup.
     return false;
 
@@ -3265,9 +3265,10 @@ bool SimplifyCFGOpt::SimplifyCleanupRetu
     if (!isa<DbgInfoIntrinsic>(I))
       return false;
 
-  // If the cleanup return we are simplifying unwinds to the caller, this
-  // will set UnwindDest to nullptr.
+  // If the cleanup return we are simplifying unwinds to the caller, this will
+  // set UnwindDest to nullptr.
   BasicBlock *UnwindDest = RI->getUnwindDest();
+  Instruction *DestEHPad = UnwindDest ? UnwindDest->getFirstNonPHI() : nullptr;
 
   // We're about to remove BB from the control flow.  Before we do, sink any
   // PHINodes into the unwind destination.  Doing this before changing the
@@ -3278,7 +3279,7 @@ bool SimplifyCFGOpt::SimplifyCleanupRetu
     // First, go through the PHI nodes in UnwindDest and update any nodes that
     // reference the block we are removing
     for (BasicBlock::iterator I = UnwindDest->begin(),
-                              IE = UnwindDest->getFirstNonPHI()->getIterator();
+                              IE = DestEHPad->getIterator();
          I != IE; ++I) {
       PHINode *DestPN = cast<PHINode>(I);
 
@@ -3322,7 +3323,7 @@ bool SimplifyCFGOpt::SimplifyCleanupRetu
     }
 
     // Sink any remaining PHI nodes directly into UnwindDest.
-    Instruction *InsertPt = UnwindDest->getFirstNonPHI();
+    Instruction *InsertPt = DestEHPad;
     for (BasicBlock::iterator I = BB->begin(),
                               IE = BB->getFirstNonPHI()->getIterator();
          I != IE;) {
@@ -3492,18 +3493,16 @@ bool SimplifyCFGOpt::SimplifyUnreachable
         }
     } else if ((isa<InvokeInst>(TI) &&
                 cast<InvokeInst>(TI)->getUnwindDest() == BB) ||
-               isa<CatchEndPadInst>(TI) || isa<TerminatePadInst>(TI)) {
+               isa<TerminatePadInst>(TI) || isa<CatchSwitchInst>(TI)) {
       removeUnwindEdge(TI->getParent());
       Changed = true;
-    } else if (isa<CleanupReturnInst>(TI) || isa<CleanupEndPadInst>(TI)) {
+    } else if (isa<CleanupReturnInst>(TI)) {
       new UnreachableInst(TI->getContext(), TI);
       TI->eraseFromParent();
       Changed = true;
     }
-    // TODO: If TI is a CatchPadInst, then (BB must be its normal dest and)
-    // we can eliminate it, redirecting its preds to its unwind successor,
-    // or to the next outer handler if the removed catch is the last for its
-    // catchendpad.
+    // TODO: We can remove a catchswitch if all it's catchpads end in
+    // unreachable.
   }
 
   // If this block is now dead, remove it.

Removed: llvm/trunk/test/Assembler/invalid-OperatorConstraint.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-OperatorConstraint.ll?rev=255421&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/invalid-OperatorConstraint.ll (original)
+++ llvm/trunk/test/Assembler/invalid-OperatorConstraint.ll (removed)
@@ -1,89 +0,0 @@
-; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s
-; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s
-; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s
-; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s
-; RUN: sed -e s/.T5:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s
-; RUN: sed -e s/.T6:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s
-; RUN: sed -e s/.T7:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK7 %s
-; RUN: sed -e s/.T8:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK8 %s
-; RUN: sed -e s/.T9:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK9 %s
-
-;T1: define void @f() {
-;T1:   entry:
-;T1:     ; operator constraint requires an operator
-;T1:     catchret undef to label %entry
-;T1:     ; CHECK1: [[@LINE-1]]:15: error: Catchpad value required in this position
-;T1: }
-
-;T2: define void @f() {
-;T2:   entry:
-;T2:     %x = cleanuppad []
-;T2:     ; catchret's first operand's operator must be catchpad
-;T2:     catchret %x to label %entry
-;T2:     ; CHECK2: [[@LINE-1]]:15: error: '%x' is not a catchpad
-;T2: }
-
-;T3: define void @f() {
-;T3:   entry:
-;T3:     ; catchret's first operand's operator must be catchpad
-;T3:     ; (forward reference case)
-;T3:     catchret %x to label %next
-;T3:     ; CHECK3: [[@LINE-1]]:15: error: '%x' is not a catchpad
-;T3:   next:
-;T3:     %x = cleanuppad []
-;T3:     ret void
-;T3: }
-
-;T4: define void @f() {
-;T4:   entry:
-;T4:     ; operator constraint requires an operator
-;T4:     cleanupret undef unwind label %entry
-;T4:     ; CHECK4: [[@LINE-1]]:17: error: Cleanuppad value required in this position
-;T4: }
-
-;T5: define void @f() {
-;T5:   entry:
-;T5:     %x = catchpad []
-;T5:             to label %next unwind label %entry
-;T5:   next:
-;T5:     ; cleanupret first operand's operator must be cleanuppad
-;T5:     cleanupret %x unwind to caller
-;T5:     ; CHECK5: [[@LINE-1]]:17: error: '%x' is not a cleanuppad
-;T5: }
-
-;T6: define void @f() {
-;T6:   entry:
-;T6:     ; cleanupret's first operand's operator must be cleanuppad
-;T6:     ; (forward reference case)
-;T6:     cleanupret %x unwind label %next
-;T6:     ; CHECK6: [[@LINE-1]]:17: error: '%x' is not a cleanuppad
-;T6:   next:
-;T6:     %x = catchpad [] to label %entry unwind label %next
-;T6: }
-
-;T7: define void @f() {
-;T7:   entry:
-;T7:     ; operator constraint requires an operator
-;T7:     cleanupendpad undef unwind to caller
-;T7:     ; CHECK7: [[@LINE-1]]:20: error: Cleanuppad value required in this position
-;T7: }
-
-;T8: define void @f() {
-;T8:   entry:
-;T8:     %x = catchpad []
-;T8:             to label %next unwind label %entry
-;T8:   next:
-;T8:     ; cleanupret first operand's operator must be cleanuppad
-;T8:     cleanupendpad %x unwind label next
-;T8:     ; CHECK8: [[@LINE-1]]:20: error: '%x' is not a cleanuppad
-;T8: }
-
-;T9: define void @f() {
-;T9:   entry:
-;T9:     ; cleanupret's first operand's operator must be cleanuppad
-;T9:     ; (forward reference case)
-;T9:     cleanupendpad %x unwind label %next
-;T9:     ; CHECK9: [[@LINE-1]]:20: error: '%x' is not a cleanuppad
-;T9:   next:
-;T9:     %x = catchpad [] to label %entry unwind label %next
-;T9: }

Modified: llvm/trunk/test/Bitcode/compatibility.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/compatibility.ll (original)
+++ llvm/trunk/test/Bitcode/compatibility.ll Fri Dec 11 23:38:55 2015
@@ -769,95 +769,91 @@ define i32 @instructions.win_eh.1() pers
 entry:
   %arg1 = alloca i32
   %arg2 = alloca i32
-  invoke void @f.ccc() to label %normal unwind label %catchpad1
-  invoke void @f.ccc() to label %normal unwind label %catchpad2
-  invoke void @f.ccc() to label %normal unwind label %catchpad3
+  invoke void @f.ccc() to label %normal unwind label %catchswitch1
+  invoke void @f.ccc() to label %normal unwind label %catchswitch2
+  invoke void @f.ccc() to label %normal unwind label %catchswitch3
+
+catchswitch1:
+  %cs1 = catchswitch within none [label %catchpad1] unwind label %terminate.1
 
 catchpad1:
-  catchpad [] to label %normal unwind label %exn.1
-  ; CHECK: catchpad []
-  ; CHECK-NEXT: to label %normal unwind label %exn.1
+  catchpad within %cs1 []
+  br label %normal
+  ; CHECK: catchpad within %cs1 []
+  ; CHECK-NEXT: br label %normal
+
+catchswitch2:
+  %cs2 = catchswitch within none [label %catchpad2] unwind to caller
 
 catchpad2:
-  catchpad [i32* %arg1] to label %normal unwind label %exn.2
-  ; CHECK: catchpad [i32* %arg1]
-  ; CHECK-NEXT: to label %normal unwind label %exn.2
+  catchpad within %cs2 [i32* %arg1]
+  br label %normal
+  ; CHECK: catchpad within %cs2 [i32* %arg1]
+  ; CHECK-NEXT: br label %normal
+
+catchswitch3:
+  %cs3 = catchswitch within none [label %catchpad3] unwind label %cleanuppad1
 
 catchpad3:
-  catchpad [i32* %arg1, i32* %arg2] to label %normal unwind label %exn.3
-  ; CHECK: catchpad [i32* %arg1, i32* %arg2] 
-  ; CHECK-NEXT: to label %normal unwind label %exn.3
-
-exn.1:
-  catchendpad unwind label %terminate.1
-  ; CHECK: catchendpad unwind label %terminate.1
-
-exn.2:
-  catchendpad unwind to caller
-  ; CHECK: catchendpad unwind to caller
-
-exn.3:
-  catchendpad unwind label %cleanuppad1
-  ; CHECK: catchendpad unwind label %cleanuppad1
+  catchpad within %cs3 [i32* %arg1, i32* %arg2]
+  br label %normal
+  ; CHECK: catchpad within %cs3 [i32* %arg1, i32* %arg2]
+  ; CHECK-NEXT: br label %normal
 
 cleanuppad1:
-  %clean.1 = cleanuppad []
-  ; CHECK: %clean.1 = cleanuppad []
-  invoke void @f.ccc() to label %normal unwind label %cleanupendpad1
-
-cleanupendpad1:
-  cleanupendpad %clean.1 unwind label %terminate.2
-  ; CHECK: cleanupendpad %clean.1 unwind label %terminate.2
+  %clean.1 = cleanuppad within none []
+  ; CHECK: %clean.1 = cleanuppad within none []
+  invoke void @f.ccc() to label %normal unwind label %terminate.2
 
 terminate.1:
-  terminatepad [] unwind to caller
-  ; CHECK: terminatepad [] unwind to caller
+  terminatepad within none [] unwind to caller
+  ; CHECK: terminatepad within none [] unwind to caller
 
 terminate.2:
-  terminatepad [i32* %arg1] unwind label %normal.pre
-  ; CHECK: terminatepad [i32* %arg1] unwind label %normal.pre
+  terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
+  ; CHECK: terminatepad within %clean.1 [i32* %arg1] unwind label %normal.pre
 
 normal.pre:
-  terminatepad [i32* %arg1, i32* %arg2] unwind to caller
-  ; CHECK: terminatepad [i32* %arg1, i32* %arg2] unwind to caller
+  terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
+  ; CHECK: terminatepad within %clean.1 [i32* %arg1, i32* %arg2] unwind to caller
 
 normal:
   ret i32 0
 }
-
+;
 define i32 @instructions.win_eh.2() personality i32 -4 {
 entry:
-  invoke void @f.ccc() to label %invoke.cont unwind label %catchpad
+  invoke void @f.ccc() to label %invoke.cont unwind label %catchswitch
 
 invoke.cont:
   invoke void @f.ccc() to label %continue unwind label %cleanup
 
 cleanup:
-  %clean = cleanuppad []
-  ; CHECK: %clean = cleanuppad []
-  cleanupret %clean unwind to caller
-  ; CHECK: cleanupret %clean unwind to caller
+  %clean = cleanuppad within none []
+  ; CHECK: %clean = cleanuppad within none []
+  cleanupret from %clean unwind to caller
+  ; CHECK: cleanupret from %clean unwind to caller
+
+catchswitch:
+  %cs = catchswitch within none [label %catchpad] unwind label %terminate
 
 catchpad:
-  %catch = catchpad [] to label %body unwind label %catchend
-  ; CHECK: %catch = catchpad []
-  ; CHECK-NEXT: to label %body unwind label %catchend
+  %catch = catchpad within %cs []
+  br label %body
+  ; CHECK: %catch = catchpad within %cs []
+  ; CHECK-NEXT: br label %body
 
 body:
-  invoke void @f.ccc() to label %continue unwind label %catchend
-  catchret %catch to label %return
-  ; CHECK: catchret %catch to label %return
+  invoke void @f.ccc() to label %continue unwind label %terminate
+  catchret from %catch to label %return
+  ; CHECK: catchret from %catch to label %return
 
 return:
   ret i32 0
 
-catchend:
-  catchendpad unwind label %terminate
-  ; CHECK: catchendpad unwind label %terminate
-
 terminate:
-  terminatepad [] unwind to caller
-  ; CHECK: terminatepad [] unwind to caller
+  terminatepad within %cs [] unwind to caller
+  ; CHECK: terminatepad within %cs [] unwind to caller
 
 continue:
   ret i32 0

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-cloning.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-cloning.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-cloning.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-cloning.ll Fri Dec 11 23:38:55 2015
@@ -1,6 +1,7 @@
-; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
+; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
 
 declare i32 @__CxxFrameHandler3(...)
+declare i32 @__C_specific_handler(...)
 
 declare void @f()
 declare i32 @g()
@@ -13,16 +14,16 @@ entry:
   ; %x def colors: {entry} subset of use colors; must spill
   %x = call i32 @g()
   invoke void @f()
-    to label %noreturn unwind label %catch
+    to label %noreturn unwind label %catch.switch
+catch.switch:
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchpad []
-    to label %noreturn unwind label %endcatch
+  catchpad within %cs []
+  br label %noreturn
 noreturn:
   ; %x use colors: {entry, cleanup}
   call void @h(i32 %x)
   unreachable
-endcatch:
-  catchendpad unwind to caller
 }
 ; Need two copies of the call to @h, one under entry and one under catch.
 ; Currently we generate a load for each, though we shouldn't need one
@@ -32,11 +33,11 @@ endcatch:
 ; CHECK:   %x = call i32 @g()
 ; CHECK:   invoke void @f()
 ; CHECK:     to label %[[EntryCopy:[^ ]+]] unwind label %catch
+; CHECK: catch.switch:
+; CHECK:   %cs = catchswitch within none [label %catch] unwind to caller
 ; CHECK: catch:
-; CHECK:   catchpad []
-; CHECK-NEXT: to label %[[CatchCopy:[^ ]+]] unwind
-; CHECK: [[CatchCopy]]:
-; CHECK:   call void @h(i32 %x)
+; CHECK:   catchpad within %cs []
+; CHECK-NEXT: call void @h(i32 %x)
 ; CHECK: [[EntryCopy]]:
 ; CHECK:   call void @h(i32 %x)
 
@@ -46,7 +47,7 @@ entry:
   invoke void @f()
     to label %exit unwind label %cleanup
 cleanup:
-  cleanuppad []
+  cleanuppad within none []
   br label %exit
 exit:
   call void @f()
@@ -60,7 +61,7 @@ exit:
 ; CHECK:   invoke void @f()
 ; CHECK:     to label %[[exit:[^ ]+]] unwind label %cleanup
 ; CHECK: cleanup:
-; CHECK:   cleanuppad []
+; CHECK:   cleanuppad within none []
 ; CHECK:   call void @f()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
@@ -71,16 +72,17 @@ exit:
 define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   invoke void @f()
-    to label %invoke.cont unwind label %catch
+    to label %invoke.cont unwind label %catch.switch
 invoke.cont:
   invoke void @f()
     to label %exit unwind label %cleanup
+catch.switch:
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchpad [] to label %shared unwind label %endcatch
-endcatch:
-  catchendpad unwind to caller
+  catchpad within %cs []
+  br label %shared
 cleanup:
-  cleanuppad []
+  cleanuppad within none []
   br label %shared
 shared:
   call void @f()
@@ -95,13 +97,11 @@ exit:
 ; CHECK:   invoke void @f()
 ; CHECK:     to label %[[exit:[^ ]+]] unwind
 ; CHECK: catch:
-; CHECK:   catchpad []
-; CHECK-NEXT: to label %[[shared:[^ ]+]] unwind
-; CHECK: cleanup:
-; CHECK:   cleanuppad []
-; CHECK:   call void @f()
+; CHECK:   catchpad within %cs []
+; CHECK-NEXT: call void @f()
 ; CHECK-NEXT: unreachable
-; CHECK: [[shared]]:
+; CHECK: cleanup:
+; CHECK:   cleanuppad within none []
 ; CHECK:   call void @f()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
@@ -111,12 +111,12 @@ exit:
 define void @test4() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   invoke void @f()
-    to label %shared unwind label %catch
+    to label %shared unwind label %catch.switch
+catch.switch:
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchpad []
-    to label %shared unwind label %endcatch
-endcatch:
-  catchendpad unwind to caller
+  catchpad within %cs []
+  br label %shared
 shared:
   %x = call i32 @g()
   %i = call i32 @g()
@@ -145,10 +145,9 @@ exit:
 ; from %shared to %exit.
 ; CHECK-LABEL: define void @test4(
 ; CHECK:  entry:
-; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch
+; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch.switch
 ; CHECK:  catch:
-; CHECK:    to label %[[shared_C:[^ ]+]] unwind label %endcatch
-; CHECK:  [[shared_C]]:
+; CHECK:    catchpad within %cs []
 ; CHECK:    [[x_C:%[^ ]+]] = call i32 @g()
 ; CHECK:    [[i_C:%[^ ]+]] = call i32 @g()
 ; CHECK:    [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
@@ -159,7 +158,7 @@ exit:
 ; CHECK:    [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0
 ; CHECK:    br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]]
 ; CHECK:  [[loop_C]]:
-; CHECK:    [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %[[shared_C]] ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
+; CHECK:    [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
 ; CHECK:    [[b_C:%[^ ]+]] = call i1 @b()
 ; CHECK:    br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
 ; CHECK:  [[loop_E]]:
@@ -194,27 +193,25 @@ exit:
 ; CHECK:    unreachable
 
 
-define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test5() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
     to label %exit unwind label %outer
 outer:
-  %o = cleanuppad []
+  %o = cleanuppad within none []
   %x = call i32 @g()
   invoke void @f()
-    to label %outer.ret unwind label %inner
+    to label %outer.ret unwind label %catch.switch
+catch.switch:
+  %cs = catchswitch within %o [label %inner] unwind to caller
 inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.endcatch
-inner.catch:
-  catchret %i to label %outer.post-inner
-inner.endcatch:
-  catchendpad unwind to caller
+  %i = catchpad within %cs []
+  catchret from %i to label %outer.post-inner
 outer.post-inner:
   call void @h(i32 %x)
   br label %outer.ret
 outer.ret:
-  cleanupret %o unwind to caller
+  cleanupret from %o unwind to caller
 exit:
   ret void
 }
@@ -225,17 +222,16 @@ exit:
 ; CHECK:      outer:
 ; CHECK:        %x = call i32 @g()
 ; CHECK-NEXT:   invoke void @f()
-; CHECK-NEXT:     to label %outer.ret unwind label %inner
+; CHECK-NEXT:     to label %outer.ret unwind label %catch.switch
 ; CHECK:      inner:
-; CHECK:          to label %inner.catch unwind label %inner.endcatch
-; CHECK:      inner.catch:
-; CHECK-NEXT:   catchret %i to label %outer.post-inner
+; CHECK-NEXT:   %i = catchpad within %cs []
+; CHECK-NEXT:   catchret from %i to label %outer.post-inner
 ; CHECK:      outer.post-inner:
 ; CHECK-NEXT:   call void @h(i32 %x)
 ; CHECK-NEXT:   br label %outer.ret
 
 
-define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test6() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
     to label %invoke.cont unwind label %left
@@ -243,15 +239,13 @@ invoke.cont:
   invoke void @f()
     to label %exit unwind label %right
 left:
-  cleanuppad []
+  cleanuppad within none []
   br label %shared
 right:
-  catchpad []
-    to label %right.catch unwind label %right.end
+  %cs = catchswitch within none [label %right.catch] unwind to caller
 right.catch:
+  catchpad within %cs []
   br label %shared
-right.end:
-  catchendpad unwind to caller
 shared:
   %x = call i32 @g()
   invoke void @f()
@@ -259,52 +253,32 @@ shared:
 shared.cont:
   unreachable
 inner:
-  %i = cleanuppad []
+  %i = cleanuppad within none []
   call void @h(i32 %x)
-  cleanupret %i unwind label %right.end
+  cleanupret from %i unwind to caller
 exit:
   ret void
 }
-; %inner is a cleanup which appears both as a child of
-; %left and as a child of %right.  Since statically we
-; need each funclet to have a single parent, we need to
-; clone the entire %inner funclet so we can have one
-; copy under each parent.  The cleanupret in %inner
-; unwinds to the catchendpad for %right, so the copy
-; of %inner under %right should include it; the copy
-; of %inner under %left should instead have an
-; `unreachable` inserted there, but the copy under
-; %left still needs to be created because it's possible
-; the dynamic path enters %left, then enters %inner,
-; then calls @h, and that the call to @h doesn't return.
 ; CHECK-LABEL: define void @test6(
 ; CHECK:     left:
 ; CHECK:       %x.for.left = call i32 @g()
 ; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:       catchpad
-; CHECK:           to label %right.catch unwind label %right.end
+; CHECK:           to label %shared.cont.for.left unwind label %inner
 ; CHECK:     right.catch:
+; CHECK:       catchpad
 ; CHECK:       %x = call i32 @g()
-; CHECK:           to label %shared.cont unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
+; CHECK:           to label %shared.cont unwind label %inner
 ; CHECK:     shared.cont:
 ; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_R:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 %x)
-; CHECK:       cleanupret [[I_R]] unwind label %right.end
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_L:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 %x.for.left)
+; CHECK:     shared.cont.for.left:
 ; CHECK:       unreachable
+; CHECK:     inner:
+; CHECK:       %i = cleanuppad within none []
+; CHECK:       call void @h(i32 %x1.wineh.reload)
+; CHECK:       cleanupret from %i unwind to caller
 
 
-define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test9() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
     to label %invoke.cont unwind label %left
@@ -312,176 +286,32 @@ invoke.cont:
   invoke void @f()
     to label %unreachable unwind label %right
 left:
-  cleanuppad []
-  invoke void @f() to label %unreachable unwind label %inner
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  invoke void @f() to label %unreachable unwind label %inner
-right.end:
-  catchendpad unwind to caller
-inner:
-  %i = cleanuppad []
-  %x = call i32 @g()
-  call void @h(i32 %x)
-  cleanupret %i unwind label %right.end
-unreachable:
-  unreachable
-}
-; Another case of a two-parent child (like @test6), this time
-; with the join at the entry itself instead of following a
-; non-pad join.
-; CHECK-LABEL: define void @test7(
-; CHECK:     invoke.cont:
-; CHECK:           to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
-; CHECK:     left:
-; CHECK:           to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:           to label %unreachable unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_R:\%.+]] = cleanuppad []
-; CHECK:       [[X_R:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X_R]])
-; CHECK:       cleanupret [[I_R]] unwind label %right.end
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_L:\%.+]] = cleanuppad []
-; CHECK:       [[X_L:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X_L]])
-; CHECK:       unreachable
-; CHECK:     unreachable:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-inner:
-  cleanuppad []
-  invoke void @f()
-    to label %unreachable unwind label %inner.child
-inner.child:
-  cleanuppad []
-  %x = call i32 @g()
-  call void @h(i32 %x)
-  unreachable
-unreachable:
-  unreachable
-}
-; %inner is a two-parent child which itself has a child; need
-; to make two copies of both the %inner and %inner.child.
-; CHECK-LABEL: define void @test8(
-; CHECK:     invoke.cont:
-; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
-; CHECK:     left:
-; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:               to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]]
-; CHECK:     [[INNER_CHILD_RIGHT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[INNER_CHILD_LEFT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
+  cleanuppad within none []
   call void @h(i32 1)
   invoke void @f()
     to label %unreachable unwind label %right
 right:
-  cleanuppad []
+  cleanuppad within none []
   call void @h(i32 2)
   invoke void @f()
     to label %unreachable unwind label %left
 unreachable:
   unreachable
 }
-; This is an irreducible loop with two funclets that enter each other;
-; need to make two copies of each funclet (one a child of root, the
-; other a child of the opposite funclet), but also make sure not to
-; clone self-descendants (if we tried to do that we'd need to make an
-; infinite number of them).  Presumably if optimizations ever generated
-; such a thing it would mean that one of the two cleanups was originally
-; the parent of the other, but that we'd somehow lost track in the CFG
-; of which was which along the way; generating each possibility lets
-; whichever case was correct execute correctly.
+; This is an irreducible loop with two funclets that enter each other.
 ; CHECK-LABEL: define void @test9(
 ; CHECK:     entry:
 ; CHECK:               to label %invoke.cont unwind label %[[LEFT:.+]]
 ; CHECK:     invoke.cont:
 ; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
-; CHECK:     [[LEFT_FROM_RIGHT:.+]]:
-; CHECK:       call void @h(i32 1)
-; CHECK:       call void @f()
-; CHECK:       unreachable
 ; CHECK:     [[LEFT]]:
 ; CHECK:       call void @h(i32 1)
 ; CHECK:       invoke void @f()
-; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]]
+; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]]
 ; CHECK:     [[RIGHT]]:
 ; CHECK:       call void @h(i32 2)
 ; CHECK:       invoke void @f()
-; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]]
-; CHECK:     [[RIGHT_FROM_LEFT]]:
-; CHECK:       call void @h(i32 2)
-; CHECK:       call void @f()
-; CHECK:       unreachable
+; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]]
 ; CHECK:     [[UNREACHABLE_RIGHT]]:
 ; CHECK:       unreachable
 ; CHECK:     [[UNREACHABLE_LEFT]]:
@@ -495,16 +325,16 @@ entry:
   invoke void @f()
     to label %unreachable unwind label %inner
 inner:
-  %cleanup = cleanuppad []
+  %cleanup = cleanuppad within none []
   ; make sure we don't overlook this cleanupret and try to process
   ; successor %outer as a child of inner.
-  cleanupret %cleanup unwind label %outer
+  cleanupret from %cleanup unwind label %outer
 outer:
-  %catch = catchpad [] to label %catch.body unwind label %endpad
+  %cs = catchswitch within none [label %catch.body] unwind to caller
+
 catch.body:
-  catchret %catch to label %exit
-endpad:
-  catchendpad unwind to caller
+  %catch = catchpad within %cs []
+  catchret from %catch to label %exit
 exit:
   ret void
 unreachable:
@@ -515,46 +345,40 @@ unreachable:
 ; CHECK-NEXT:   invoke
 ; CHECK-NEXT:     to label %unreachable unwind label %inner
 ; CHECK:      inner:
-; CHECK-NEXT:   %cleanup = cleanuppad
-; CHECK-NEXT:   cleanupret %cleanup unwind label %outer
+; CHECK-NEXT:   %cleanup = cleanuppad within none []
+; CHECK-NEXT:   cleanupret from %cleanup unwind label %outer
 ; CHECK:      outer:
-; CHECK-NEXT:   %catch = catchpad []
-; CHECK-NEXT:	      to label %catch.body unwind label %endpad
+; CHECK-NEXT:   %cs = catchswitch within none [label %catch.body] unwind to caller
 ; CHECK:      catch.body:
-; CHECK-NEXT:   catchret %catch to label %exit
-; CHECK:      endpad:
-; CHECK-NEXT:   catchendpad unwind to caller
+; CHECK-NEXT:   %catch = catchpad within %cs []
+; CHECK-NEXT:   catchret from %catch to label %exit
 ; CHECK:      exit:
 ; CHECK-NEXT:   ret void
 
-define void @test11() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test11() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
     to label %exit unwind label %cleanup.outer
 cleanup.outer:
-  %outer = cleanuppad []
+  %outer = cleanuppad within none []
   invoke void @f()
     to label %outer.cont unwind label %cleanup.inner
 outer.cont:
   br label %merge
 cleanup.inner:
-  %inner = cleanuppad []
+  %inner = cleanuppad within %outer []
   br label %merge
 merge:
-  invoke void @f()
-    to label %unreachable unwind label %merge.end
-unreachable:
+  call void @f()
   unreachable
-merge.end:
-  cleanupendpad %outer unwind to caller
 exit:
   ret void
 }
 ; merge.end will get cloned for outer and inner, but is implausible
-; from inner, so the invoke @f() in inner's copy of merge should be
+; from inner, so the call @f() in inner's copy of merge should be
 ; rewritten to call @f()
 ; CHECK-LABEL: define void @test11()
-; CHECK:      %inner = cleanuppad []
+; CHECK:      %inner = cleanuppad within %outer []
 ; CHECK-NEXT: call void @f()
 ; CHECK-NEXT: unreachable
 
@@ -566,10 +390,10 @@ cont:
   invoke void @f()
     to label %exit unwind label %right
 left:
-  cleanuppad []
+  cleanuppad within none []
   br label %join
 right:
-  cleanuppad []
+  cleanuppad within none []
   br label %join
 join:
   ; This call will get cloned; make sure we can handle cloning
@@ -587,68 +411,10 @@ entry:
   ret void
 
 unreachable:
-  cleanuppad []
+  cleanuppad within none []
   unreachable
 }
 
-define void @test14() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %catch1.pad
-catch1.pad:
-  %catch1 = catchpad [i32 1]
-    to label %catch1.body unwind label %catch2.pad
-catch1.body:
-  invoke void @h(i32 1)
-    to label %catch1.body2 unwind label %catch.end
-catch1.body2:
-  invoke void @f()
-    to label %catch1.ret unwind label %cleanup1.pad
-cleanup1.pad:
-  %cleanup1 = cleanuppad []
-  call void @f()
-  cleanupret %cleanup1 unwind label %catch.end
-catch1.ret:
-  catchret %catch1 to label %exit
-catch2.pad:
-  %catch2 = catchpad [i32 2]
-    to label %catch2.body unwind label %catch.end
-catch2.body:
-  invoke void @h(i32 2)
-    to label %catch2.body2 unwind label %catch.end
-catch2.body2:
-  invoke void @f()
-    to label %catch2.ret unwind label %cleanup2.pad
-cleanup2.pad:
-  %cleanup2 = cleanuppad []
-  call void @f()
-  cleanupret %cleanup2 unwind label %catch.end
-catch2.ret:
-  catchret %catch2 to label %exit
-catch.end:
-  catchendpad unwind to caller
-exit:
-  ret void
-}
-; Make sure we don't clone the catchendpad even though the
-; cleanupendpads targeting it would naively imply that it
-; should get their respective parent colors (catch1 and catch2),
-; as well as its properly getting the root function color.  The
-; references from the invokes ensure that if we did make clones
-; for each catch, they'd be reachable, as those invokes would get
-; rewritten
-; CHECK-LABEL: define void @test14()
-; CHECK-NOT:  catchendpad
-; CHECK:      invoke void @h(i32 1)
-; CHECK-NEXT:   unwind label %catch.end
-; CHECK-NOT:  catchendpad
-; CHECK:      invoke void @h(i32 2)
-; CHECK-NEXT:   unwind label %catch.end
-; CHECK-NOT:   catchendpad
-; CHECK:     catch.end:
-; CHECK-NEXT:  catchendpad
-; CHECK-NOT:   catchendpad
-
 ;; Debug info (from test12)
 
 ; Make sure the DISubprogram doesn't get cloned

Removed: llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll?rev=255421&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll (removed)
@@ -1,277 +0,0 @@
-; RUN: llc -mtriple=x86_64-pc-windows-coreclr -verify-machineinstrs < %s | FileCheck %s
-
-declare void @ProcessCLRException()
-declare void @f(i32)
-declare void @g(i8 addrspace(1)*)
-declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
-
-; Simplified IR for pseudo-C# like the following:
-; void test1() {
-;   try {
-;     f(1);
-;     try {
-;       f(2);
-;     } catch (type1) {
-;       f(3);
-;     } catch (type2) [
-;       f(4);
-;       try {
-;         f(5);
-;       } fault {
-;         f(6);
-;       }
-;     }
-;   } finally {
-;     f(7);
-;   }
-;   f(8);
-; }
-
-; CHECK-LABEL: test1:     # @test1
-; CHECK-NEXT: [[L_begin:.*func_begin.*]]:
-define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
-entry:
-; CHECK: # %entry
-; CHECK: leaq [[FPOffset:[0-9]+]](%rsp), %rbp
-; CHECK: .seh_endprologue
-; CHECK: movq %rsp, [[PSPSymOffset:[0-9]+]](%rsp)
-; CHECK: [[L_before_f1:.+]]:
-; CHECK-NEXT: movl $1, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f1:.+]]:
-  invoke void @f(i32 1)
-    to label %inner_try unwind label %finally.pad
-inner_try:
-; CHECK: # %inner_try
-; CHECK: [[L_before_f2:.+]]:
-; CHECK-NEXT: movl $2, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f2:.+]]:
-  invoke void @f(i32 2)
-    to label %finally.clone unwind label %catch1.pad
-catch1.pad:
-; CHECK: .seh_proc [[L_catch1:[^ ]+]]
-  %catch1 = catchpad [i32 1]
-    to label %catch1.body unwind label %catch2.pad
-catch1.body:
-; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
-;                        ^ all funclets use the same frame size
-; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
-;                              ^ establisher frame pointer passed in rcx
-; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
-; CHECK: leaq [[FPOffset]](%rcx), %rbp
-; CHECK: .seh_endprologue
-; CHECK: movq %rdx, %rcx
-;             ^ exception pointer passed in rdx
-; CHECK-NEXT: callq g
-  %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
-  call void @g(i8 addrspace(1)* %exn1)
-; CHECK: [[L_before_f3:.+]]:
-; CHECK-NEXT: movl $3, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f3:.+]]:
-  invoke void @f(i32 3)
-    to label %catch1.ret unwind label %catch.end
-catch1.ret:
-  catchret %catch1 to label %finally.clone
-catch2.pad:
-; CHECK: .seh_proc [[L_catch2:[^ ]+]]
-  %catch2 = catchpad [i32 2]
-    to label %catch2.body unwind label %catch.end
-catch2.body:
-; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
-;                        ^ all funclets use the same frame size
-; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
-;                              ^ establisher frame pointer passed in rcx
-; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
-; CHECK: leaq [[FPOffset]](%rcx), %rbp
-; CHECK: .seh_endprologue
-; CHECK: movq %rdx, %rcx
-;             ^ exception pointer passed in rdx
-; CHECK-NEXT: callq g
-  %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
-  call void @g(i8 addrspace(1)* %exn2)
-; CHECK: [[L_before_f4:.+]]:
-; CHECK-NEXT: movl $4, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f4:.+]]:
-  invoke void @f(i32 4)
-    to label %try_in_catch unwind label %catch.end
-try_in_catch:
-; CHECK: # %try_in_catch
-; CHECK: [[L_before_f5:.+]]:
-; CHECK-NEXT: movl $5, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f5:.+]]:
-  invoke void @f(i32 5)
-    to label %catch2.ret unwind label %fault.pad
-fault.pad:
-; CHECK: .seh_proc [[L_fault:[^ ]+]]
-  %fault = cleanuppad [i32 undef]
-; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
-;                        ^ all funclets use the same frame size
-; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
-;                              ^ establisher frame pointer passed in rcx
-; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
-; CHECK: leaq [[FPOffset]](%rcx), %rbp
-; CHECK: .seh_endprologue
-; CHECK: [[L_before_f6:.+]]:
-; CHECK-NEXT: movl $6, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f6:.+]]:
-  invoke void @f(i32 6)
-    to label %fault.ret unwind label %fault.end
-fault.ret:
-  cleanupret %fault unwind label %catch.end
-fault.end:
-  cleanupendpad %fault unwind label %catch.end
-catch2.ret:
-  catchret %catch2 to label %finally.clone
-catch.end:
-  catchendpad unwind label %finally.pad
-finally.clone:
-  call void @f(i32 7)
-  br label %tail
-finally.pad:
-; CHECK: .seh_proc [[L_finally:[^ ]+]]
-  %finally = cleanuppad []
-; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
-;                        ^ all funclets use the same frame size
-; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
-;                              ^ establisher frame pointer passed in rcx
-; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
-; CHECK: leaq [[FPOffset]](%rcx), %rbp
-; CHECK: .seh_endprologue
-; CHECK: [[L_before_f7:.+]]:
-; CHECK-NEXT: movl $7, %ecx
-; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f7:.+]]:
-  invoke void @f(i32 7)
-    to label %finally.ret unwind label %finally.end
-finally.ret:
-  cleanupret %finally unwind to caller
-finally.end:
-   cleanupendpad %finally unwind to caller
-tail:
-  call void @f(i32 8)
-  ret void
-; CHECK: [[L_end:.*func_end.*]]:
-}
-
-; Now check for EH table in xdata (following standard xdata)
-; CHECK-LABEL: .section .xdata
-; standard xdata comes here
-; CHECK:      .long 4{{$}}
-;                   ^ number of funclets
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
-;                   ^ offset from L_begin to start of 1st funclet
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
-;                   ^ offset from L_begin to start of 2nd funclet
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
-;                   ^ offset from L_begin to start of 3rd funclet
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset from L_begin to start of 4th funclet
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
-;                   ^ offset from L_begin to end of last funclet
-; CHECK-NEXT: .long 7
-;                   ^ number of EH clauses
-; Clause 1: call f(2) is guarded by catch1
-; CHECK-NEXT: .long 0
-;                   ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 1
-;                   ^ type token of catch (from catchpad)
-; Clause 2: call f(2) is also guarded by catch2
-; CHECK-NEXT: .long 0
-;                   ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 2
-;                   ^ type token of catch (from catchpad)
-; Clause 3: calls f(1) and f(2) are guarded by finally
-; CHECK-NEXT: .long 2
-;                   ^ flags (2 => finally handler)
-; CHECK-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
-;                   ^ type token slot (null for finally)
-; Clause 4: call f(3) is guarded by finally
-;           This is a "duplicate" because the protected range (f(3))
-;           is in funclet catch1 but the finally's immediate parent
-;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
-;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
-;                   ^ type token slot (null for finally)
-; Clause 5: call f(5) is guarded by fault
-; CHECK-NEXT: .long 4
-;                   ^ flags (4 => fault handler)
-; CHECK-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
-;                   ^ type token slot (null for fault)
-; Clause 6: calls f(4) and f(5) are guarded by finally
-;           This is a "duplicate" because the protected range (f(4)-f(5))
-;           is in funclet catch2 but the finally's immediate parent
-;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
-;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
-;                   ^ type token slot (null for finally)
-; Clause 7: call f(6) is guarded by finally
-;           This is a "duplicate" because the protected range (f(3))
-;           is in funclet catch1 but the finally's immediate parent
-;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
-;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
-;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
-;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
-;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
-;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
-;                   ^ type token slot (null for finally)

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-demotion.ll Fri Dec 11 23:38:55 2015
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
+; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
 
 declare i32 @__CxxFrameHandler3(...)
 
@@ -36,17 +36,15 @@ merge:
   ; CHECK: merge:
   ; CHECK-NOT: = phi
   %phi = phi i32 [ %x, %left ], [ %y, %right ]
-  %cp = catchpad [] to label %catch unwind label %catchend
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
+  %cp = catchpad within %cs1 []
   ; CHECK: catch:
   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
   ; CHECK-NEXT: call void @h(i32 [[Reload]])
   call void @h(i32 %phi)
-  catchret %cp to label %exit
-
-catchend:
-  catchendpad unwind to caller
+  catchret from %cp to label %exit
 
 exit:
   ret void
@@ -75,44 +73,42 @@ right:
 merge.inner:
   ; CHECK: merge.inner:
   ; CHECK-NOT: = phi
-  ; CHECK: catchpad []
+  ; CHECK: catchswitch within none
   %x = phi i32 [ 1, %left ], [ 2, %right ]
-  %cpinner = catchpad [] to label %catch.inner unwind label %catchend.inner
+  %cs1 = catchswitch within none [label %catch.inner] unwind label %merge.outer
 
 catch.inner:
+  %cpinner = catchpad within %cs1 []
   ; Need just one store here because only %y is affected
   ; CHECK: catch.inner:
   %z = call i32 @g()
   ; CHECK:   store i32 %z
   ; CHECK-NEXT: invoke void @f
   invoke void @f()
-          to label %catchret.inner unwind label %catchend.inner
+          to label %catchret.inner unwind label %merge.outer
 
 catchret.inner:
-  catchret %cpinner to label %exit
-catchend.inner:
-  ; CHECK-NOT: = phi
-  %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
-  catchendpad unwind label %merge.outer
+  catchret from %cpinner to label %exit
 
 merge.outer:
+  %y = phi i32 [ %x, %merge.inner ], [ %z, %catch.inner ]
   ; CHECK: merge.outer:
-  ; CHECK: [[CatchPad:%[^ ]+]] = catchpad []
-  %cpouter = catchpad [] to label %catch.outer unwind label %catchend.outer
-
-catchend.outer:
-  catchendpad unwind to caller
+  ; CHECK-NOT: = phi
+  ; CHECK: catchswitch within none
+  %cs2 = catchswitch within none [label %catch.outer] unwind to caller
 
 catch.outer:
+  %cpouter = catchpad within %cs2 []
+  ; CHECK: catch.outer:
+  ; CHECK: [[CatchPad:%[^ ]+]] = catchpad within %cs2 []
   ; Need to load x and y from two different slots since they're both live
   ; and can have different values (if we came from catch.inner)
-  ; CHECK: catch.outer:
   ; CHECK-DAG: load i32, i32* [[Slot1]]
   ; CHECK-DAG: load i32, i32* [[Slot2]]
-  ; CHECK: catchret [[CatchPad]] to label
+  ; CHECK: catchret from [[CatchPad]] to label
   call void @h(i32 %x)
   call void @h(i32 %y)
-  catchret %cpouter to label %exit
+  catchret from %cpouter to label %exit
 
 exit:
   ret void
@@ -145,13 +141,12 @@ right:
           to label %join unwind label %catchpad.inner
 catchpad.inner:
    ; CHECK: catchpad.inner:
-   ; CHECK-NEXT: catchpad []
+   ; CHECK-NEXT: catchswitch within none
    %phi.inner = phi i32 [ %l, %left ], [ %r, %right ]
-   %cp1 = catchpad [] to label %catch.inner unwind label %catchend.inner
+   %cs1 = catchswitch within none [label %catch.inner] unwind label %catchpad.outer
 catch.inner:
-   catchret %cp1 to label %join
-catchend.inner:
-   catchendpad unwind label  %catchpad.outer
+   %cp1 = catchpad within %cs1 []
+   catchret from %cp1 to label %join
 join:
   ; CHECK: join:
   ; CHECK-NOT: store
@@ -160,19 +155,19 @@ join:
    %j = call i32 @g()
    invoke void @f()
            to label %exit unwind label %catchpad.outer
+
 catchpad.outer:
    ; CHECK: catchpad.outer:
-   ; CHECK-NEXT: catchpad []
-   %phi.outer = phi i32 [ %phi.inner, %catchend.inner ], [ %j, %join ]
-   %cp2 = catchpad [] to label %catch.outer unwind label %catchend.outer
+   ; CHECK-NEXT: catchswitch within none
+   %phi.outer = phi i32 [ %phi.inner, %catchpad.inner ], [ %j, %join ]
+   %cs2 = catchswitch within none [label %catch.outer] unwind to caller
 catch.outer:
    ; CHECK: catch.outer:
    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
    ; CHECK:   call void @h(i32 [[Reload]])
+   %cp2 = catchpad within %cs2 []
    call void @h(i32 %phi.outer)
-   catchret %cp2 to label %exit
-catchend.outer:
-   catchendpad unwind to caller
+   catchret from %cp2 to label %exit
 exit:
    ret void
 }
@@ -198,10 +193,10 @@ invoke.cont:
 cleanup:
   ; cleanup phi can be loaded at cleanup entry
   ; CHECK: cleanup:
-  ; CHECK-NEXT: cleanuppad []
+  ; CHECK-NEXT: cleanuppad within none []
   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
-  %cp = cleanuppad []
+  %cp = cleanuppad within none []
   %b = call i1 @i()
   br i1 %b, label %left, label %right
 
@@ -222,7 +217,7 @@ merge:
   ; CHECK:      merge:
   ; CHECK-NEXT:   store i32 [[CleanupReload]], i32* [[CatchSlot:%[^ ]+]]
   ; CHECK-NEXT:   cleanupret
-  cleanupret %cp unwind label %catchpad
+  cleanupret from %cp unwind label %catchswitch
 
 invoke.cont2:
   ; need store for %phi.catch
@@ -230,23 +225,22 @@ invoke.cont2:
   ; CHECK-NEXT:   store i32 3, i32* [[CatchSlot]]
   ; CHECK-NEXT:   invoke void @f
   invoke void @f()
-          to label %exit unwind label %catchpad
+          to label %exit unwind label %catchswitch
 
-catchpad:
-  ; CHECK: catchpad:
-  ; CHECK-NEXT: catchpad []
+catchswitch:
+  ; CHECK: catchswitch:
+  ; CHECK-NEXT: catchswitch within none
   %phi.catch = phi i32 [ %phi.cleanup, %merge ], [ 3, %invoke.cont2 ]
-  %cp2 = catchpad [] to label %catch unwind label %catchend
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
   ; CHECK: catch:
+  ; CHECK:   catchpad within %cs1
   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
   ; CHECK:   call void @h(i32 [[CatchReload]]
+  %cp2 = catchpad within %cs1 []
   call void @h(i32 %phi.catch)
-  catchret %cp2 to label %exit
-
-catchend:
-  catchendpad unwind to caller
+  catchret from %cp2 to label %exit
 
 exit:
   ret void
@@ -262,17 +256,17 @@ entry:
   %x = invoke i32 @g()
           to label %loop unwind label %to_caller
 to_caller:
-  %cp1 = cleanuppad []
-  cleanupret %cp1 unwind to caller
+  %cp1 = cleanuppad within none []
+  cleanupret from %cp1 unwind to caller
 loop:
   invoke void @f()
           to label %loop unwind label %cleanup
 cleanup:
   ; CHECK: cleanup:
   ; CHECK:   call void @h(i32 %x)
-  %cp2 = cleanuppad []
+  %cp2 = cleanuppad within none []
   call void @h(i32 %x)
-  cleanupret %cp2 unwind to caller
+  cleanupret from %cp2 unwind to caller
 }
 
 ; CHECK-LABEL: @test7(
@@ -294,18 +288,21 @@ invoke.cont:
 catchpad:
   ; %x phi should be eliminated
   ; CHECK: catchpad:
-  ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad []
+  ; CHECK-NEXT: catchswitch within none
   %x = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
-  %cp = catchpad [] to label %catch unwind label %catchend
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 catch:
+  ; CHECK: catch:
+  ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
+  %cp = catchpad within %cs1 []
   %b = call i1 @i()
   br i1 %b, label %left, label %right
 left:
   ; Edge from %left to %join needs to be split so that
   ; the load of %x can be inserted *after* the catchret
   ; CHECK: left:
-  ; CHECK-NEXT: catchret %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
-  catchret %cp to label %join
+  ; CHECK-NEXT: catchret from %[[CatchPad]] to label %[[SplitLeft:[^ ]+]]
+  catchret from %cp to label %join
   ; CHECK: [[SplitLeft]]:
   ; CHECK:   [[LoadX:%[^ ]+]] = load i32, i32* [[SlotX]]
   ; CHECK:   br label %join
@@ -314,11 +311,9 @@ right:
   ; the load of %y can be inserted *after* the catchret
   ; CHECK: right:
   ; CHECK:   %y = call i32 @g()
-  ; CHECK:   catchret %[[CatchPad]] to label %join
+  ; CHECK:   catchret from %[[CatchPad]] to label %join
   %y = call i32 @g()
-  catchret %cp to label %join
-catchend:
-  catchendpad unwind to caller
+  catchret from %cp to label %join
 join:
   ; CHECK: join:
   ; CHECK:   %phi = phi i32 [ [[LoadX]], %[[SplitLeft]] ], [ %y, %right ]
@@ -340,20 +335,20 @@ done:
   ret void
 
 cleanup1:
-  ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad []
+  ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
   ; CHECK-NEXT: call void @f()
-  ; CHECK-NEXT: cleanupret [[CleanupPad1]]
-  %cp0 = cleanuppad []
+  ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
+  %cp0 = cleanuppad within none []
   br label %cleanupexit
 
 cleanup2:
-  ; CHECK: cleanuppad []
+  ; CHECK: cleanuppad within none []
   ; CHECK-NEXT: call void @f()
   ; CHECK-NEXT: unreachable
-  %cp1 = cleanuppad []
+  %cp1 = cleanuppad within none []
   br label %cleanupexit
 
 cleanupexit:
   call void @f()
-  cleanupret %cp0 unwind label %cleanup2
+  cleanupret from %cp0 unwind label %cleanup2
 }

Removed: llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll?rev=255421&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll (removed)
@@ -1,28 +0,0 @@
-; RUN: llc -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s
-
-declare void @ProcessCLRException()
-declare i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token)
-declare void @f()
-declare void @g(i32 addrspace(1)*)
-
-; CHECK-LABEL: test1: # @test1
-define void @test1() personality i8* bitcast (void ()* @ProcessCLRException to i8*) {
-entry:
-  invoke void @f()
-    to label %exit unwind label %catch.pad
-catch.pad:
-; CHECK: {{^[^: ]+}}: # %catch.pad
-  %catch = catchpad [i32 5]
-    to label %catch.body unwind label %catch.end
-catch.body:
-  %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
-  %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
-  ; CHECK: movq %rdx, %rcx
-  ; CHECK-NEXT: callq g
-  call void @g(i32 addrspace(1)* %cast_exn)
-  catchret %catch to label %exit
-catch.end:
-  catchendpad unwind to caller
-exit:
-  ret void
-}

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-intrinsics.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-intrinsics.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-intrinsics.ll Fri Dec 11 23:38:55 2015
@@ -15,13 +15,12 @@ entry:
   invoke void (...) @f(i32 1)
      to label %exit unwind label %catchpad
 catchpad:
-  %catch = catchpad [i32 1] to label %do_catch unwind label %catchend
+  %cs1 = catchswitch within none [label %do_catch] unwind to caller
 do_catch:
+  %catch = catchpad within %cs1 [i32 1]
   %exn = call i8* @llvm.eh.exceptionpointer.p0i8(token %catch)
   call void (...) @f(i8* %exn)
-  catchret %catch to label %exit
-catchend:
-  catchendpad unwind to caller
+  catchret from %catch to label %exit
 exit:
   ret void
 }
@@ -31,13 +30,12 @@ entry:
   invoke void (...) @f(i32 1)
      to label %exit unwind label %catchpad
 catchpad:
-  %catch = catchpad [i32 1] to label %do_catch unwind label %catchend
+  %cs1 = catchswitch within none [label %do_catch] unwind to caller
 do_catch:
+  %catch = catchpad within %cs1 [i32 1]
   %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
   call void (...) @f(i8 addrspace(1)* %exn)
-  catchret %catch to label %exit
-catchend:
-  catchendpad unwind to caller
+  catchret from %catch to label %exit
 exit:
   ret void
 }

Removed: llvm/trunk/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll?rev=255421&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-multi-parent-cloning.ll (removed)
@@ -1,1548 +0,0 @@
-; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare  < %s | FileCheck %s
-
-declare i32 @__CxxFrameHandler3(...)
-
-declare void @f()
-declare i32 @g()
-declare void @h(i32)
-declare i1 @b()
-
-define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = cleanuppad []
-  call void @h(i32 %x)
-  cleanupret %i unwind label %right.end
-exit:
-  ret void
-}
-; %inner is a cleanup which appears both as a child of
-; %left and as a child of %right.  Since statically we
-; need each funclet to have a single parent, we need to
-; clone the entire %inner funclet so we can have one
-; copy under each parent.  The cleanupret in %inner
-; unwinds to the catchendpad for %right, so the copy
-; of %inner under %right should include it; the copy
-; of %inner under %left should instead have an
-; `unreachable` inserted there, but the copy under
-; %left still needs to be created because it's possible
-; the dynamic path enters %left, then enters %inner,
-; then calls @h, and that the call to @h doesn't return.
-; CHECK-LABEL: define void @test1(
-; CHECK:     left:
-; CHECK:       cleanuppad
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:       %x = call i32 @g()
-; CHECK:           to label %shared.cont unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     shared.cont:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_R:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 %x)
-; CHECK:       cleanupret [[I_R]] unwind label %right.end
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_L:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-
-
-define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %right.end
-exit:
-  ret void
-}
-; In this case left and right are both parents of inner.  This differs from
-; @test1 in that inner is a catchpad rather than a cleanuppad, which makes
-; inner.end a block that gets cloned so that left and right each contain a
-; copy (catchendpad blocks are considered to be part of the parent funclet
-; of the associated catchpad). The catchendpad in %inner.end unwinds to
-; %right.end (which belongs to the entry funclet).
-; CHECK-LABEL: define void @test2(
-; CHECK:     left:
-; CHECK:       cleanuppad
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %[[RIGHT_END:.+]]
-; CHECK:     right.catch:
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind label %[[RIGHT_END]]
-
-define void @test3() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  %l = cleanuppad []
-  br label %shared
-left.end:
-  cleanupendpad %l unwind label %right
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; In this case, %left and %right are siblings with %entry as the parent of both,
-; while %left and %right are both parents of %inner.  The catchendpad in
-; %inner.end unwinds to %left.end.  When %inner is cloned a copy of %inner.end
-; will be made for both %left and %right, but because %left.end is a cleanup pad
-; and %right is a catch pad the unwind edge from the copy of %inner.end for
-; %right must be removed.
-; CHECK-LABEL: define void @test3(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_END:left.end.*]]:
-; CHECK:       cleanupendpad %l unwind label %right
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %[[RIGHT_END:.+]]
-; CHECK:     right.catch:
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-
-
-define void @test4() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %left.end
-left.catch:
-  br label %shared
-left.end:
-  catchendpad unwind label %right
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This is a variation of @test3 in which both %left and %right are catch pads.
-; In this case, %left and %right are siblings with %entry as the parent of both,
-; while %left and %right are both parents of %inner.  The catchendpad in
-; %inner.end unwinds to %left.end.  When %inner is cloned a copy of %inner.end
-; will be made for both %left and %right, but because the catchpad in %right
-; does not unwind to %left.end the unwind edge from the copy of %inner.end for
-; %right must be removed.
-; CHECK-LABEL: define void @test4(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     left.catch:
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind label %right
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %[[RIGHT_END:.+]]
-; CHECK:     right.catch:
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-
-
-define void @test5() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %left.end
-left.catch:
-  br label %shared
-left.end:
-  catchendpad unwind label %right
-right:
-  %r = cleanuppad []
-  br label %shared
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; Like @test3, %left and %right are siblings with %entry as the parent of both,
-; while %left and %right are both parents of %inner.  This case makes %left a
-; catch and %right a cleanup so that %inner unwinds to %left.end, which is a
-; block in %entry.  The %inner funclet is cloned for %left and %right, but the
-; copy of %inner.end for %right must have its unwind edge removed because the
-; catchendpad at %left.end is not compatible with %right.
-; CHECK-LABEL: define void @test5(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     left.catch:
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind label %right
-; CHECK:     right:
-; CHECK:       %r = cleanuppad []
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-
-define void @test6() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %left.end
-left.catch:
-  br label %shared
-left.end:
-  catchendpad unwind label %middle
-middle:
-  %m = catchpad []
-    to label %middle.catch unwind label %middle.end
-middle.catch:
-  catchret %m to label %exit
-middle.end:
-  catchendpad unwind label %right
-right:
-  %r = cleanuppad []
-  br label %shared
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This is like @test5 but it inserts another sibling between %left and %right.
-; In this case %left, %middle and %right are all siblings, while %left and
-; %right are both parents of %inner.  This checks the proper handling of the
-; catchendpad in %inner.end (which will be cloned so that %left and %right both
-; have copies) unwinding to a catchendpad that unwinds to a sibling.
-; CHECK-LABEL: define void @test6(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     left.catch:
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind label %middle
-; CHECK:     middle:
-; CHECK:       catchpad []
-; CHECK:         to label %middle.catch unwind label %middle.end
-; CHECK:     middle.catch:
-; CHECK:       catchret %m to label %exit
-; CHECK:     middle.end:
-; CHECK:       catchendpad unwind label %right
-; CHECK:     right:
-; CHECK:       %r = cleanuppad []
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-
-
-define void @test7() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %left.end
-left.catch:
-  br label %shared
-left.end:
-  catchendpad unwind label %right
-right:
-  %r = cleanuppad []
-  br label %shared
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %inner.sibling
-inner.sibling:
-  %is = cleanuppad []
-  call void @h(i32 0)
-  cleanupret %is unwind label %left.end
-exit:
-  ret void
-}
-; This is like @test5 but instead of unwinding to %left.end, the catchendpad
-; in %inner.end unwinds to a sibling cleanup pad. Both %inner (along with its
-; associated blocks) and %inner.sibling must be cloned for %left and %right.
-; The clones of %inner will be identical, but the copy of %inner.sibling for
-; %right must end with an unreachable instruction, because it cannot unwind to
-; %left.end.
-; CHECK-LABEL: define void @test7(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     left.catch:
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind label %[[RIGHT:.+]]
-; CHECK:     [[RIGHT]]:
-; CHECK:       [[R:\%.+]] = cleanuppad []
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind label %[[INNER_SIBLING_RIGHT:.+]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[INNER_SIBLING_LEFT:.+]]
-; CHECK:     [[INNER_SIBLING_RIGHT]]
-; CHECK:       [[IS_R:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_SIBLING_LEFT]]
-; CHECK:       [[IS_L:\%.+]] = cleanuppad []
-; CHECK:       call void @h(i32 0)
-; CHECK:       cleanupret [[IS_L]] unwind label %[[LEFT_END]]
-
-
-define void @test8() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
-  invoke void @f() to label %unreachable unwind label %inner
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  invoke void @f() to label %unreachable unwind label %inner
-right.end:
-  catchendpad unwind to caller
-inner:
-  %i = cleanuppad []
-  %x = call i32 @g()
-  call void @h(i32 %x)
-  cleanupret %i unwind label %right.end
-unreachable:
-  unreachable
-}
-; Another case of a two-parent child (like @test1), this time
-; with the join at the entry itself instead of following a
-; non-pad join.
-; CHECK-LABEL: define void @test8(
-; CHECK:     invoke.cont:
-; CHECK:           to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
-; CHECK:     left:
-; CHECK:           to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:           to label %unreachable unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_R:\%.+]] = cleanuppad []
-; CHECK:       [[X_R:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X_R]])
-; CHECK:       cleanupret [[I_R]] unwind label %right.end
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_L:\%.+]] = cleanuppad []
-; CHECK:       [[X_L:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X_L]])
-; CHECK:       unreachable
-; CHECK:     unreachable:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test9() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-inner:
-  cleanuppad []
-  invoke void @f()
-    to label %unreachable unwind label %inner.child
-inner.child:
-  cleanuppad []
-  %x = call i32 @g()
-  call void @h(i32 %x)
-  unreachable
-unreachable:
-  unreachable
-}
-; %inner is a two-parent child which itself has a child; need
-; to make two copies of both the %inner and %inner.child.
-; CHECK-LABEL: define void @test9(
-; CHECK:     invoke.cont:
-; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %right
-; CHECK:     left:
-; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:               to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_RIGHT:.+]] unwind label %[[INNER_CHILD_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:               to label %[[UNREACHABLE_INNER_LEFT:.+]] unwind label %[[INNER_CHILD_LEFT:.+]]
-; CHECK:     [[INNER_CHILD_RIGHT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[INNER_CHILD_LEFT]]:
-; CHECK:       [[TMP:\%.+]] = cleanuppad []
-; CHECK:       [[X:\%.+]] = call i32 @g()
-; CHECK:       call void @h(i32 [[X]])
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_INNER_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test10() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %unreachable unwind label %right
-left:
-  cleanuppad []
-  call void @h(i32 1)
-  invoke void @f()
-    to label %unreachable unwind label %right
-right:
-  cleanuppad []
-  call void @h(i32 2)
-  invoke void @f()
-    to label %unreachable unwind label %left
-unreachable:
-  unreachable
-}
-; This is an irreducible loop with two funclets that enter each other;
-; need to make two copies of each funclet (one a child of root, the
-; other a child of the opposite funclet), but also make sure not to
-; clone self-descendants (if we tried to do that we'd need to make an
-; infinite number of them).  Presumably if optimizations ever generated
-; such a thing it would mean that one of the two cleanups was originally
-; the parent of the other, but that we'd somehow lost track in the CFG
-; of which was which along the way; generating each possibility lets
-; whichever case was correct execute correctly.
-; CHECK-LABEL: define void @test10(
-; CHECK:     entry:
-; CHECK:               to label %invoke.cont unwind label %[[LEFT:.+]]
-; CHECK:     invoke.cont:
-; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
-; CHECK:     [[LEFT_FROM_RIGHT:.+]]:
-; CHECK:       call void @h(i32 1)
-; CHECK:       call void @f()
-; CHECK:       unreachable
-; CHECK:     [[LEFT]]:
-; CHECK:       call void @h(i32 1)
-; CHECK:       invoke void @f()
-; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT_FROM_LEFT:.+]]
-; CHECK:     [[RIGHT]]:
-; CHECK:       call void @h(i32 2)
-; CHECK:       invoke void @f()
-; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT_FROM_RIGHT]]
-; CHECK:     [[RIGHT_FROM_LEFT]]:
-; CHECK:       call void @h(i32 2)
-; CHECK:       call void @f()
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[UNREACHABLE_ENTRY]]:
-; CHECK:       unreachable
-
-
-define void @test11() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %left.sibling
-left.catch:
-  br label %shared
-left.sibling:
-  %ls = catchpad []
-    to label %left.sibling.catch unwind label %left.end
-left.sibling.catch:
-  catchret %ls to label %exit
-left.end:
-  catchendpad unwind label %right
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This is a variation of @test4 in which the shared child funclet unwinds to a
-; catchend pad that is the unwind destination of %left.sibling rather than %left
-; but is still a valid destination for %inner as reach from %left.
-; When %inner is cloned a copy of %inner.end will be made for both %left and
-; %right, but because the catchpad in %right does not unwind to %left.end the
-; unwind edge from the copy of %inner.end for %right must be removed.
-; CHECK-LABEL: define void @test11(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %left.sibling
-; CHECK:     left.catch:
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     left.sibling:
-; CHECK:       catchpad []
-; CHECK:           to label %left.sibling.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind label %right
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %[[RIGHT_END:.+]]
-; CHECK:     right.catch:
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-
-
-define void @test12() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  catchpad []
-    to label %left.catch unwind label %right
-left.catch:
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 %x)
-  unreachable
-inner.end:
-  catchendpad unwind label %right.end
-exit:
-  ret void
-}
-; In this case %left and %right are both parents of %inner, so %inner must be
-; cloned but the catchendpad unwind target in %inner.end is valid for both
-; parents, so the unwind edge should not be removed in either case.
-; CHECK-LABEL: define void @test12(
-; CHECK:     left:
-; CHECK:       catchpad []
-; CHECK:           to label %left.catch unwind label %right
-; CHECK:     left.catch:
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:           to label %right.catch unwind label %[[RIGHT_END:.+]]
-; CHECK:     right.catch:
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 %x)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 %x.for.left)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind label %[[RIGHT_END]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[RIGHT_END]]
-
-define void @test13() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  %l = catchpad []
-    to label %left.cont unwind label %left.end
-left.cont:
-  invoke void @f()
-    to label %left.ret unwind label %inner
-left.ret:
-  catchret %l to label %invoke.cont
-left.end:
-  catchendpad unwind to caller
-right:
-  %r = catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  invoke void @f()
-    to label %right.ret unwind label %inner
-right.ret:
-  catchret %r to label %exit
-right.end:
-  catchendpad unwind to caller
-shared:
-  call void @h(i32 0)
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 1)
-  catchret %i to label %shared
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This case tests the scenario where a funclet with multiple parents uses a
-; catchret to return to a block that may exist in either parent funclets.
-; Both %left and %right are parents of %inner.  During common block cloning
-; a clone of %shared will be made so that both %left and %right have a copy,
-; but the copy of %shared for one of the parent funclets will be unreachable
-; until the %inner funclet is cloned.  When the %inner.catch block is cloned
-; during the %inner funclet cloning, the catchret instruction should be updated
-; so that the catchret in the copy %inner.catch for %left returns to the copy of
-; %shared in %left and the catchret in the copy of %inner.catch for %right
-; returns to the copy of %shared for %right.
-; CHECK-LABEL: define void @test13(
-; CHECK:     left:
-; CHECK:       %l = catchpad []
-; CHECK:           to label %left.cont unwind label %left.end
-; CHECK:     left.cont:
-; CHECK:       invoke void @f()
-; CHECK:           to label %left.ret unwind label %[[INNER_LEFT:.+]]
-; CHECK:     left.ret:
-; CHECK:       catchret %l to label %invoke.cont
-; CHECK:     left.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     right:
-; CHECK:       %r = catchpad []
-; CHECK:           to label %right.catch unwind label %right.end
-; CHECK:     right.catch:
-; CHECK:       invoke void @f()
-; CHECK:           to label %right.ret unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     right.ret:
-; CHECK:       catchret %r to label %exit
-; CHECK:     right.end:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_RIGHT:.+]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[SHARED_LEFT:.+]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       %[[I_RIGHT:.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       %[[I_LEFT:.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 1)
-; CHECK:       catchret %[[I_RIGHT]] to label %[[SHARED_RIGHT]]
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 1)
-; CHECK:       catchret %[[I_LEFT]] to label %[[SHARED_LEFT]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-
-
-define void @test14() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  %l = catchpad []
-    to label %shared unwind label %left.end
-left.cont:
-  invoke void @f()
-    to label %left.ret unwind label %right
-left.ret: 
-  catchret %l to label %exit
-left.end:
-  catchendpad unwind to caller
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind label %left.end
-shared:
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 0)
-  catchret %i to label %left.cont
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This case tests another scenario where a funclet with multiple parents uses a
-; catchret to return to a block in one of the parent funclets.  Here %right and
-; %left are both parents of %inner and %left is a parent of %right.  The
-; catchret in %inner.catch will cause %left.cont and %left.ret to be cloned for
-; both %left and %right, but the catchret in %left.ret is invalid for %right
-; but the catchret instruction in the copy of %left.ret for %right will be
-; removed as an implausible terminator.
-; CHECK-LABEL: define void @test14(
-; CHECK:     left:
-; CHECK:       %l = catchpad []
-; CHECK:           to label %[[SHARED_LEFT:.+]] unwind label %[[LEFT_END:.+]]
-; CHECK:     [[LEFT_CONT:left.cont.*]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[LEFT_RET:.+]] unwind label %[[RIGHT:.+]]
-; CHECK:     [[LEFT_RET]]:
-; CHECK:       catchret %l to label %exit
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-; CHECK:     [[SHARED_LEFT]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       catchret [[I_LEFT]] to label %[[LEFT_CONT]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-
-define void @test15() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  %l = catchpad []
-    to label %left.catch unwind label %left.end
-left.catch:
-  invoke void @f()
-    to label %shared unwind label %right
-left.ret:
-  catchret %l to label %exit
-left.end:
-  catchendpad unwind to caller
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind label %left.end
-shared:
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 0)
-  catchret %i to label %left.ret
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This case is a variation of test14 but instead of returning to an invoke the
-; catchret in %inner.catch returns to a catchret instruction.
-; CHECK-LABEL: define void @test15(
-; CHECK:     left:
-; CHECK:       %l = catchpad []
-; CHECK:           to label %left.catch unwind label %[[LEFT_END:.+]]
-; CHECK:     left.catch:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_LEFT:.+]] unwind label %[[RIGHT:.+]]
-; CHECK:     [[LEFT_RET_RIGHT:.+]]:
-; CHECK:       unreachable
-; CHECK:     [[LEFT_RET_LEFT:.+]]:
-; CHECK:       catchret %l to label %exit
-; CHECK:     [[LEFT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-; CHECK:     [[SHARED_LEFT]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       catchret [[I_LEFT]] to label %[[LEFT_RET_LEFT]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       catchret [[I_RIGHT]] to label %[[LEFT_RET_RIGHT]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END]]
-
-
-define void @test16() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %exit unwind label %left
-left:
-  %l = cleanuppad []
-  br label %shared
-left.cont:
-  cleanupret %l unwind label %right
-left.end:
-  cleanupendpad %l unwind label %right
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.end
-inner.catch:
-  call void @h(i32 0)
-  catchret %i to label %left.cont
-inner.end:
-  catchendpad unwind label %left.end
-exit:
-  ret void
-}
-; This case is another variation of test14 but here the catchret in %inner.catch
-; returns to a cleanupret instruction.
-; CHECK-LABEL: define void @test16(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     [[LEFT_CONT_RIGHT:.+]]:
-; CHECK:       unreachable
-; CHECK:     [[LEFT_CONT_LEFT:.+]]:
-; CHECK:       cleanupret %l unwind label %[[RIGHT:.+]]
-; CHECK:     [[LEFT_END_LEFT:.+]]:
-; CHECK:       cleanupendpad %l unwind label %[[RIGHT]]
-; CHECK:     [[RIGHT]]:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       catchret [[I_RIGHT]] to label %[[LEFT_CONT_RIGHT]]
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       catchret [[I_LEFT]] to label %[[LEFT_CONT_LEFT]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind label %[[LEFT_END_LEFT]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind to caller
-
-
-define void @test17() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  %l = cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-unreachable:
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.sibling
-inner.catch:
-  call void @h(i32 0)
-  unreachable
-inner.sibling:
-  %is = catchpad []
-    to label %inner.sibling.catch unwind label %inner.end
-inner.sibling.catch:
-  invoke void @f()
-    to label %unreachable unwind label %inner.end
-inner.end:
-  catchendpad unwind label %right.end
-exit:
-  ret void
-}
-; This case tests the scenario where two catchpads with the same catchendpad
-; have multiple parents.  Both %left and %right are parents of %inner and
-; %inner.sibling so both of the inner funclets must be cloned.  Because
-; the catchendpad in %inner.end unwinds to the catchendpad for %right, the
-; unwind edge should be removed for the copy of %inner.end that is reached
-; from %left.  In addition, the %inner.siblin.catch block contains an invoke
-; that unwinds to the shared inner catchendpad.  The unwind destination for
-; this invoke should be updated to unwind to the correct cloned %inner.end
-; for each path to the funclet.
-; CHECK-LABEL: define void @test17(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_SIBLING_RIGHT]]:
-; CHECK:       [[IS_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_SIBLING_LEFT]]:
-; CHECK:       [[IS_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_SIBLING_CATCH_RIGHT]]:
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
-; CHECK:     [[INNER_SIBLING_CATCH_LEFT]]:
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind label %[[RIGHT_END]]
-
-
-define void @test18() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  %l = cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-unreachable:
-  unreachable
-inner:
-  %i = catchpad []
-    to label %inner.catch unwind label %inner.sibling
-inner.catch:
-  invoke void @f()
-    to label %unreachable unwind label %inner.end
-inner.sibling:
-  %is = catchpad []
-    to label %inner.sibling.catch unwind label %inner.end
-inner.sibling.catch:
-  call void @h(i32 0)
-  unreachable
-inner.end:
-  catchendpad unwind label %right.end
-exit:
-  ret void
-}
-; This is like test17 except that the inner invoke is moved from the
-; %inner.sibling funclet to %inner so that it is unwinding to a
-; catchendpad block that has not yet been cloned.  The unwind destination
-; of the invoke should still be updated to reach the correct copy of
-; %inner.end for the path by which it is reached.
-; CHECK-LABEL: define void @test18(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_RIGHT:.+]] unwind label %[[INNER_SIBLING_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_CATCH_LEFT:.+]] unwind label %[[INNER_SIBLING_LEFT:.+]]
-; CHECK:     [[INNER_CATCH_RIGHT]]:
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_CATCH_LEFT]]:
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_SIBLING_RIGHT]]:
-; CHECK:       [[IS_RIGHT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_SIBLING_CATCH_RIGHT:.+]] unwind label %[[INNER_END_RIGHT]]
-; CHECK:     [[INNER_SIBLING_LEFT]]:
-; CHECK:       [[IS_LEFT:\%.+]] = catchpad []
-; CHECK:           to label %[[INNER_SIBLING_CATCH_LEFT:.+]] unwind label %[[INNER_END_LEFT]]
-; CHECK:     [[INNER_SIBLING_CATCH_RIGHT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_SIBLING_CATCH_LEFT]]:
-; CHECK:       call void @h(i32 0)
-; CHECK:       unreachable
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       catchendpad unwind label %[[RIGHT_END]]
-
-
-define void @test19() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  %l = cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-unreachable:
-  unreachable
-inner:
-  %i = cleanuppad []
-  invoke void @f()
-    to label %unreachable unwind label %inner.end
-inner.end:
-  cleanupendpad %i unwind label %right.end
-exit:
-  ret void
-}
-; This case tests the scenario where an invoke in a funclet with multiple
-; parents unwinds to a cleanup end pad for the funclet.  The unwind destination
-; for the invoke should map to the correct copy of the cleanup end pad block.
-; CHECK-LABEL: define void @test19(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_END_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_END_LEFT:.+]]
-; CHECK:     [[INNER_END_RIGHT]]:
-; CHECK:       cleanupendpad [[I_RIGHT]] unwind label %[[RIGHT_END]]
-; CHECK:     [[INNER_END_LEFT]]:
-; CHECK:       cleanupendpad [[I_LEFT]] unwind to caller
-
-define void @test20() personality i32 (...)* @__CxxFrameHandler3 {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  %l = cleanuppad []
-  br label %shared
-right:
-  catchpad []
-    to label %right.catch unwind label %right.end
-right.catch:
-  br label %shared
-right.end:
-  catchendpad unwind to caller
-shared:
-  invoke void @f()
-    to label %unreachable unwind label %inner
-unreachable:
-  unreachable
-inner:
-  %i = cleanuppad []
-  invoke void @f()
-    to label %unreachable unwind label %inner.cleanup
-inner.cleanup:
-  cleanuppad []
-  call void @f()
-  unreachable
-exit:
-  ret void
-}
-; This tests the case where a funclet with multiple parents contains an invoke
-; instruction that unwinds to a child funclet.  Here %left and %right are both
-; parents of %inner.  Initially %inner is the only parent of %inner.cleanup but
-; after %inner is cloned, %inner.cleanup has multiple parents and so it must
-; also be cloned.
-; CHECK-LABEL: define void @test20(
-; CHECK:     left:
-; CHECK:       %l = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_LEFT:.+]] unwind label %[[INNER_LEFT:.+]]
-; CHECK:     right:
-; CHECK:       catchpad []
-; CHECK:           to label %[[RIGHT_CATCH:.+]] unwind label %[[RIGHT_END:.+]]
-; CHECK:     [[RIGHT_CATCH]]:
-; CHECK:       invoke void @f()
-; CHECK:           to label %[[SHARED_CONT_RIGHT:.+]] unwind label %[[INNER_RIGHT:.+]]
-; CHECK:     [[RIGHT_END]]:
-; CHECK:       catchendpad unwind to caller
-; CHECK:     [[SHARED_CONT_RIGHT]]:
-; CHECK:       unreachable
-; CHECK:     [[SHARED_CONT_LEFT]]:
-; CHECK:       unreachable
-; CHECK:     [[INNER_RIGHT]]:
-; CHECK:       [[I_RIGHT:\%.+]] = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[INNER_CLEANUP_RIGHT:.+]]
-; CHECK:     [[INNER_LEFT]]:
-; CHECK:       [[I_LEFT:\%.+]] = cleanuppad []
-; CHECK:       invoke void @f()
-; CHECK:         to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[INNER_CLEANUP_LEFT:.+]]
-; CHECK:     [[INNER_CLEANUP_RIGHT]]:
-; CHECK:       cleanuppad []
-; CHECK:       call void @f()
-; CHECK:       unreachable
-; CHECK:     [[INNER_CLEANUP_LEFT]]:
-; CHECK:       cleanuppad []
-; CHECK:       call void @f()
-; CHECK:       unreachable
-
-

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-no-demotion.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-no-demotion.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-no-demotion.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-no-demotion.ll Fri Dec 11 23:38:55 2015
@@ -2,6 +2,8 @@
 
 declare i32 @__CxxFrameHandler3(...)
 
+declare i32 @__C_specific_handler(...)
+
 declare void @f()
 
 declare i32 @g()
@@ -9,7 +11,7 @@ declare i32 @g()
 declare void @h(i32)
 
 ; CHECK-LABEL: @test1(
-define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test1() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
           to label %invoke.cont1 unwind label %left
@@ -23,11 +25,11 @@ invoke.cont2:
           to label %exit unwind label %inner
 
 left:
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   br label %shared
 
 right:
-  %1 = cleanuppad []
+  %1 = cleanuppad within none []
   br label %shared
 
 shared:
@@ -40,25 +42,20 @@ shared.cont:
 
 inner:
   %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
-  %i = cleanuppad []
+  %i = cleanuppad within none []
   call void @h(i32 %phi)
   unreachable
 
-; CHECK [[INNER_INVOKE_CONT2:inner.*]]:
-  ; CHECK: call void @h(i32 0)
-
-; CHECK [[INNER_RIGHT:inner.*]]:
-  ; CHECK: call void @h(i32 %x)
-
-; CHECK [[INNER_LEFT:inner.*]]:
-  ; CHECK: call void @h(i32 %x.for.left)
+; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
+; CHECK: %i = cleanuppad within none []
+; CHECK: call void @h(i32 %phi)
 
 exit:
   unreachable
 }
 
 ; CHECK-LABEL: @test2(
-define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
+define void @test2() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
           to label %invoke.cont unwind label %left
@@ -68,11 +65,11 @@ invoke.cont:
           to label %exit unwind label %right
 
 left:
-  cleanuppad []
+  cleanuppad within none []
   br label %shared
 
 right:
-  cleanuppad []
+  cleanuppad within none []
   br label %shared
 
 shared:
@@ -84,15 +81,13 @@ shared.cont:
   unreachable
 
 inner:
-  %i = cleanuppad []
+  %i = cleanuppad within none []
   call void @h(i32 %x)
   unreachable
 
-; CHECK [[INNER_RIGHT:inner.*]]:
-  ; CHECK: call void @h(i32 %x)
-
-; CHECK [[INNER_LEFT:inner.*]]:
-  ; CHECK: call void @h(i32 %x.for.left)
+; CHECK:  %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
+; CHECK:  %i = cleanuppad within none []
+; CHECK:  call void @h(i32 %x1)
 
 exit:
   unreachable
@@ -108,10 +103,47 @@ invoke.cont:
   ret void
 
 terminate:
-; CHECK:  cleanuppad []
+; CHECK:  cleanuppad within none []
 ; CHECK:  call void @__std_terminate()
 ; CHECK:  unreachable
-  terminatepad [void ()* @__std_terminate] unwind to caller
+  terminatepad within none [void ()* @__std_terminate] unwind to caller
+}
+
+; CHECK-LABEL: @test4(
+define void @test4(i1 %x) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @f()
+          to label %invoke.cont1 unwind label %left
+
+invoke.cont1:
+  invoke void @f()
+          to label %exit unwind label %right
+
+left:
+  %0 = cleanuppad within none []
+  br label %shared
+
+right:
+  %1 = cleanuppad within none []
+  br i1 %x, label %shared, label %right.other
+
+right.other:
+  br label %shared
+
+shared:
+  %phi = phi i32 [ 1, %left ], [ 0, %right ], [ -1, %right.other ]
+  call void @h(i32 %phi)
+  unreachable
+
+; CHECK: %0 = cleanuppad within none []
+; CHECK: call void @h(i32 1)
+
+; CHECK: %1 = cleanuppad within none []
+; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ]
+; CHECK: call void @h(i32 %phi)
+
+exit:
+  unreachable
 }
 
 declare void @__std_terminate()

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering-cleanups.ll Fri Dec 11 23:38:55 2015
@@ -7,38 +7,6 @@ declare void @dummy_filter()
 
 declare void @f(i32)
 
-; CHECK-LABEL: define void @test1(
-;Cxx: define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
-;SEH: define void @test1() personality i32 (...)* @_except_handler3 {
-entry:
-  ; CHECK: entry:
-  ; CHECK:  store i32 0
-  ; CHECK:  invoke void @f(i32 0)
-  invoke void @f(i32 0)
-    to label %exit unwind label %cleanup.pad
-cleanup.pad:
-  ; CHECK: cleanup.pad:
-  ; CHECK:   store i32 1
-  ; CHECK:   invoke void @f(i32 1)
-  %cleanup = cleanuppad []
-  invoke void @f(i32 1)
-    to label %cleanup.ret unwind label %catch.pad
-catch.pad:
-;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null]
-;SEH: %catch = catchpad [void ()* @dummy_filter]
-        to label %catch.body unwind label %catch.end
-catch.body:
-  catchret %catch to label %cleanup.ret
-catch.end:
-  catchendpad unwind label %cleanup.end
-cleanup.ret:
-  cleanupret %cleanup unwind to caller
-cleanup.end:
-  cleanupendpad %cleanup unwind to caller
-exit:
-  ret void
-}
-
 ; CHECK-LABEL: define void @test2(
 ;Cxx: define void @test2(i1 %b) personality i32 (...)* @__CxxFrameHandler3 {
 ;SEH: define void @test2(i1 %b) personality i32 (...)* @_except_handler3 {
@@ -49,20 +17,18 @@ entry:
   invoke void @f(i32 1)
     to label %exit unwind label %cleanup.pad
 cleanup.pad:
-  %cleanup = cleanuppad []
+  %cleanup = cleanuppad within none []
   br i1 %b, label %left, label %right
 left:
-  cleanupret %cleanup unwind label %catch.pad
+  cleanupret from %cleanup unwind label %catch.pad
 right:
-  cleanupret %cleanup unwind label %catch.pad
+  cleanupret from %cleanup unwind label %catch.pad
 catch.pad:
-;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null]
-;SEH: %catch = catchpad [void ()* @dummy_filter]
-        to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
 catch.body:
-  catchret %catch to label %exit
-catch.end:
-  catchendpad unwind to caller
+;Cxx: %catch = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+;SEH: %catch = catchpad within %cs1 [void ()* @dummy_filter]
+  catchret from %catch to label %exit
 exit:
   ret void
 }
@@ -72,29 +38,25 @@ exit:
 ;SEH: define void @test3() personality i32 (...)* @_except_handler3 {
 entry:
   ; CHECK: entry:
-  ; CHECK:   store i32 1
+  ; CHECK:   store i32 0
   ; CHECK:   invoke void @f(i32 1)
   invoke void @f(i32 1)
     to label %exit unwind label %cleanup.pad
 cleanup.pad:
   ; CHECK: cleanup.pad:
-  ; CHECK:   store i32 0
+  ; CHECK:   store i32 1
   ; CHECK:   invoke void @f(i32 0)
-  %cleanup = cleanuppad []
+  %cleanup = cleanuppad within none []
   invoke void @f(i32 0)
-    to label %unreachable unwind label %cleanup.end
+    to label %unreachable unwind label %catch.pad
 unreachable:
   unreachable
-cleanup.end:
-  cleanupendpad %cleanup unwind label %catch.pad
 catch.pad:
-;Cxx: %catch = catchpad [i8* null, i32 u0x40, i8* null]
-;SEH: %catch = catchpad [void ()* @dummy_filter]
-        to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
 catch.body:
-  catchret %catch to label %exit
-catch.end:
-  catchendpad unwind to caller
+;Cxx: %catch = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+;SEH: %catch = catchpad within %cs1 [void ()* @dummy_filter]
+  catchret from %catch to label %exit
 exit:
   ret void
 }

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-statenumbering.ll Fri Dec 11 23:38:55 2015
@@ -37,9 +37,10 @@ entry:
           to label %unreachable.for.entry unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
   ; CHECK: catch:
   ; CHECK:   store i32 2
   ; CHECK:   invoke void @_CxxThrowException(
@@ -47,34 +48,22 @@ catch:
           to label %unreachable unwind label %catch.dispatch.1
 
 catch.dispatch.1:                                 ; preds = %catch
-  %2 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch.3 unwind label %catchendblock.2
-
+  %cs2 = catchswitch within %1 [label %catch.3] unwind to caller
 catch.3:                                          ; preds = %catch.dispatch.1
+  %2 = catchpad within %cs2 [i8* null, i32 u0x40, i8* null]
   ; CHECK: catch.3:
   ; CHECK:   store i32 3
-  ; CHECK:   invoke void @g(i32 1)
-  invoke void @g(i32 1)
-          to label %invoke.cont unwind label %catchendblock.2
-
-invoke.cont:                                      ; preds = %catch.3
-  catchret %2 to label %try.cont
+  ; CHECK:   call void @g(i32 1)
+  call void @g(i32 1)
+  catchret from %2 to label %try.cont
 
-try.cont:                                         ; preds = %invoke.cont
+try.cont:                                         ; preds = %catch.3
   ; CHECK: try.cont:
   ; CHECK:   store i32 1
-  ; CHECK:   invoke void @g(i32 2)
-  invoke void @g(i32 2)
-          to label %invoke.cont.4 unwind label %catchendblock
-
-invoke.cont.4:                                    ; preds = %try.cont
+  ; CHECK:   call void @g(i32 2)
+  call void @g(i32 2)
   unreachable
 
-catchendblock.2:                                  ; preds = %catch.3, %catch.dispatch.1
-  catchendpad unwind label %catchendblock
-
-catchendblock:                                    ; preds = %catchendblock.2, %try.cont, %catch.dispatch
-  catchendpad unwind to caller
-
 unreachable:                                      ; preds = %catch
   unreachable
 

Modified: llvm/trunk/test/CodeGen/X86/branchfolding-catchpads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/branchfolding-catchpads.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/branchfolding-catchpads.ll (original)
+++ llvm/trunk/test/CodeGen/X86/branchfolding-catchpads.ll Fri Dec 11 23:38:55 2015
@@ -19,24 +19,18 @@ if.else:
           to label %cleanup unwind label %catch.dispatch
 
 catch.dispatch:
-  catchpad [i8* null, i32 8, i8* null]
-          to label %catch unwind label %catch.dispatch.2
+  %cs = catchswitch within none [ label %catch, label %catch.2 ] unwind to caller
 
 catch:
-  invoke void @throw() noreturn
-          to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
-  catchpad [i8* null, i32 64, i8* null]
-          to label %catch.2 unwind label %catchendblock
+  catchpad within %cs [i8* null, i32 8, i8* null]
+  call void @throw() noreturn
+  br label %unreachable
 
 catch.2:
+  catchpad within %cs [i8* null, i32 64, i8* null]
   store i8 1, i8* %b
-  invoke void @throw() noreturn
-          to label %unreachable unwind label %catchendblock
-
-catchendblock:
-  catchendpad unwind to caller
+  call void @throw() noreturn
+  br label %unreachable
 
 cleanup:
   %retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ]
@@ -67,31 +61,22 @@ if.else:
           to label %cleanup unwind label %catch.dispatch
 
 catch.dispatch:
-  catchpad [i8* null, i32 8, i8* null]
-          to label %catch unwind label %catch.dispatch.2
+  %cs = catchswitch within none [ label %catch, label %catch.2, label %catch.3 ] unwind to caller
 
 catch:
-  invoke void @throw() noreturn
-          to label %unreachable unwind label %catchendblock
-
-catch.dispatch.2:
-  %c2 = catchpad [i8* null, i32 32, i8* null]
-          to label %catch.2 unwind label %catch.dispatch.3
+  catchpad within %cs [i8* null, i32 8, i8* null]
+  call void @throw() noreturn
+  br label %unreachable
 
 catch.2:
+  %c2 = catchpad within %cs [i8* null, i32 32, i8* null]
   store i8 1, i8* %b
-  catchret %c2 to label %cleanup
-
-catch.dispatch.3:
-  %c3 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch.3 unwind label %catchendblock
+  catchret from %c2 to label %cleanup
 
 catch.3:
+  %c3 = catchpad within %cs [i8* null, i32 64, i8* null]
   store i8 2, i8* %b
-  catchret %c3 to label %cleanup
-
-catchendblock:
-  catchendpad unwind to caller
+  catchret from %c3 to label %cleanup
 
 cleanup:
   %retval = phi i16 [ %call1, %if.then ], [ %call2, %if.else ], [ -1, %catch.2 ], [ -1, %catch.3 ]

Modified: llvm/trunk/test/CodeGen/X86/catchpad-realign-savexmm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchpad-realign-savexmm.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchpad-realign-savexmm.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchpad-realign-savexmm.ll Fri Dec 11 23:38:55 2015
@@ -14,19 +14,17 @@ define void @f() personality i32 (...)*
   %v1 = fadd double %v, 1.0
   store double %v1, double* @fp_global
   invoke void @g()
-      to label %return unwind label %catch
+      to label %return unwind label %catch.dispatch
 
 return:
   ret void
 
-catch:
-  %p = catchpad [i8* null, i32 64, i8* null]
-      to label %catchit unwind label %endpad
+catch.dispatch:
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
-catchit:
-  catchret %p to label %return
-endpad:
-  catchendpad unwind to caller
+catch:
+  %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  catchret from %p to label %return
 }
 
 ; CHECK: f: # @f

Modified: llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchpad-regmask.ll Fri Dec 11 23:38:55 2015
@@ -41,14 +41,14 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %idxprom1 = sext i32 %idx2 to i64
   %arrayidx2 = getelementptr inbounds [4 x i32], [4 x i32]* @array, i64 0, i64 %idxprom1
   store i32 222, i32* %arrayidx2, align 4, !tbaa !2
-  catchret %0 to label %try.cont
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %catch
   %idxprom3 = sext i32 %idx3 to i64
@@ -56,9 +56,6 @@ try.cont:
   store i32 333, i32* %arrayidx4, align 4, !tbaa !2
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
-
 unreachable:                                      ; preds = %entry
   unreachable
 }
@@ -98,20 +95,17 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   store i32 222, i32* @imported, align 4, !tbaa !2
-  catchret %0 to label %try.cont
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %catch
   store i32 333, i32* @imported, align 4, !tbaa !2
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
-
 unreachable:                                      ; preds = %entry
   unreachable
 }

Modified: llvm/trunk/test/CodeGen/X86/catchpad-weight.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchpad-weight.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchpad-weight.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchpad-weight.ll Fri Dec 11 23:38:55 2015
@@ -2,7 +2,7 @@
 
 ; Check if the edge weight to the catchpad is calculated correctly.
 
-; CHECK: Successors according to CFG: BB#3(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#4(0x00000400 / 0x80000000 = 0.00%) BB#6(0x00000200 / 0x80000000 = 0.00%) BB#8(0x00000100 / 0x80000000 = 0.00%)
+; CHECK: Successors according to CFG: BB#2(0x7ffff100 / 0x80000000 = 100.00%) BB#1(0x00000800 / 0x80000000 = 0.00%) BB#3(0x00000400 / 0x80000000 = 0.00%) BB#4(0x00000200 / 0x80000000 = 0.00%) BB#5(0x00000100 / 0x80000000 = 0.00%)
 
 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64--windows-msvc18.0.0"
@@ -31,11 +31,11 @@ entry:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %1 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
-          to label %catch.5 unwind label %catch.dispatch.1
+  %cs1 = catchswitch within none [label %catch.5] unwind label %catch.dispatch.1
 
 catch.5:                                          ; preds = %catch.dispatch
-  catchret %1 to label %try.cont
+  %1 = catchpad within %cs1 [%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8", i32 0, i8* null]
+  catchret from %1 to label %try.cont
 
 try.cont:                                         ; preds = %entry, %catch, %catch.3, %catch.5
   call void @"\01??1HasDtor@@QEAA at XZ"(%struct.HasDtor* nonnull %o) #4
@@ -43,26 +43,23 @@ try.cont:
   ret i32 0
 
 catch.dispatch.1:                                 ; preds = %catch.dispatch
-  %2 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
-          to label %catch.3 unwind label %catch.dispatch.2
+  %cs2 = catchswitch within none [label %catch.3] unwind label %catch.dispatch.2
 
 catch.3:                                          ; preds = %catch.dispatch.1
-  catchret %2 to label %try.cont
+  %2 = catchpad within %cs2 [%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8", i32 0, i8* null]
+  catchret from %2 to label %try.cont
 
 catch.dispatch.2:                                 ; preds = %catch.dispatch.1
-  %3 = catchpad [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs3 = catchswitch within none [label %catch] unwind label %ehcleanup
 
 catch:                                            ; preds = %catch.dispatch.2
-  catchret %3 to label %try.cont
-
-catchendblock:                                    ; preds = %catch.dispatch.2
-  catchendpad unwind label %ehcleanup
+  %3 = catchpad within %cs3 [%rtti.TypeDescriptor7* @"\01??_R0?AUC@@@8", i32 0, i8* null]
+  catchret from %3 to label %try.cont
 
 ehcleanup:                                        ; preds = %catchendblock
-  %4 = cleanuppad []
+  %4 = cleanuppad within none []
   call void @"\01??1HasDtor@@QEAA at XZ"(%struct.HasDtor* nonnull %o) #4
-  cleanupret %4 unwind to caller
+  cleanupret from %4 unwind to caller
 }
 
 ; Function Attrs: nounwind argmemonly

Modified: llvm/trunk/test/CodeGen/X86/catchret-empty-fallthrough.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchret-empty-fallthrough.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchret-empty-fallthrough.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchret-empty-fallthrough.ll Fri Dec 11 23:38:55 2015
@@ -19,14 +19,11 @@ try:
           to label %fallthrough unwind label %dispatch
 
 dispatch:                                         ; preds = %try
-  %0 = catchpad [i8* null]
-          to label %catch unwind label %catchendblock.i.i
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %dispatch
-  catchret %0 to label %return
-
-catchendblock.i.i:                                ; preds = %dispatch
-  catchendpad unwind to caller
+  %0 = catchpad within %cs1 [i8* null]
+  catchret from %0 to label %return
 
 fallthrough:                                      ; preds = %try
   unreachable

Modified: llvm/trunk/test/CodeGen/X86/catchret-fallthrough.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/catchret-fallthrough.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/catchret-fallthrough.ll (original)
+++ llvm/trunk/test/CodeGen/X86/catchret-fallthrough.ll Fri Dec 11 23:38:55 2015
@@ -18,14 +18,11 @@ entry:
           to label %invoke.cont.3 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %0 to label %nrvo.skipdtor
-
-catchendblock:                                    ; preds = %catch, %catch.dispatch
-  catchendpad unwind to caller
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  catchret from %0 to label %nrvo.skipdtor
 
 invoke.cont.3:                                    ; preds = %entry
   store i32 123, i32* @some_global

Modified: llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll (original)
+++ llvm/trunk/test/CodeGen/X86/cleanuppad-inalloca.ll Fri Dec 11 23:38:55 2015
@@ -29,9 +29,9 @@ invoke.cont:
   ret void
 
 ehcleanup:                                        ; preds = %entry
-  %2 = cleanuppad []
+  %2 = cleanuppad within none []
   call x86_thiscallcc void @"\01??1A@@QAE at XZ"(%struct.A* %0)
-  cleanupret %2 unwind to caller
+  cleanupret from %2 unwind to caller
 }
 
 ; CHECK: _passes_two:

Modified: llvm/trunk/test/CodeGen/X86/cleanuppad-large-codemodel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-large-codemodel.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cleanuppad-large-codemodel.ll (original)
+++ llvm/trunk/test/CodeGen/X86/cleanuppad-large-codemodel.ll Fri Dec 11 23:38:55 2015
@@ -9,9 +9,9 @@ entry:
   invoke void @bar()
     to label %exit unwind label %cleanup
 cleanup:
-  %c = cleanuppad []
+  %c = cleanuppad within none []
   call void @bar()
-  cleanupret %c unwind to caller
+  cleanupret from %c unwind to caller
 exit:
   ret void
 }

Modified: llvm/trunk/test/CodeGen/X86/cleanuppad-realign.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cleanuppad-realign.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/cleanuppad-realign.ll (original)
+++ llvm/trunk/test/CodeGen/X86/cleanuppad-realign.ll Fri Dec 11 23:38:55 2015
@@ -17,9 +17,9 @@ invoke.cont:
   ret void
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   call void @Dtor(i64* %o)
-  cleanupret %0 unwind to caller
+  cleanupret from %0 unwind to caller
 }
 
 ; X86-LABEL: _realigned_cleanup: # @realigned_cleanup

Modified: llvm/trunk/test/CodeGen/X86/funclet-layout.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/funclet-layout.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/funclet-layout.ll (original)
+++ llvm/trunk/test/CodeGen/X86/funclet-layout.ll Fri Dec 11 23:38:55 2015
@@ -15,21 +15,21 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:
-  %cp = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
-  br i1 %B, label %catchret, label %catch
+  %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  br label %catch.loop
+
+catch.loop:
+  br i1 %B, label %catchret, label %catch.loop
 
 catchret:
-  catchret %cp to label %try.cont
+  catchret from %cp to label %try.cont
 
 try.cont:
   ret void
 
-catchendblock:
-  catchendpad unwind to caller
-
 unreachable:
   unreachable
 }
@@ -55,54 +55,50 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
           to label %unreachable unwind label %catch.dispatch.1
 
 catch.dispatch.1:                                 ; preds = %catch
-  %1 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch.3 unwind label %catchendblock.2
+  %cs2 = catchswitch within %0 [label %catch.3] unwind to caller
 
 catch.3:                                          ; preds = %catch.dispatch.1
-  catchret %1 to label %try.cont
+  %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+  catchret from %1 to label %try.cont
 
 try.cont:                                         ; preds = %catch.3
-  catchret %0 to label %try.cont.5
+  catchret from %0 to label %try.cont.5
 
 try.cont.5:                                       ; preds = %try.cont
   ret i32 0
 
-catchendblock.2:                                  ; preds = %catch.dispatch.1
-  catchendpad unwind label %catchendblock
-
-catchendblock:                                    ; preds = %catchendblock.2, %catch.dispatch
-  catchendpad unwind to caller
-
 unreachable:                                      ; preds = %catch, %entry
   unreachable
-
 }
 
 ; CHECK-LABEL: test2:
 
-; The entry funclet contains %entry and %try.cont.5
+; The parent function contains %entry and %try.cont.5
+; CHECK: .seh_proc
 ; CHECK: # %entry
 ; CHECK: # %try.cont.5
 ; CHECK: retq
 
-; The outer catch funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The inner catch funclet contains %catch.3
+; CHECK: .seh_proc
+; CHECK: # %catch.3{{$}}
+; CHECK: retq
+
+; The outer catch funclet contains %catch
+; CHECK: .seh_proc
+; CHECK: # %catch{{$}}
 ; CHECK: callq _CxxThrowException
 ; CHECK: # %unreachable
 ; CHECK: ud2
 
-; The inner catch funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
-; CHECK: retq
-
 
 define void @test3(i1 %V) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
 entry:
@@ -110,24 +106,21 @@ entry:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch.2 unwind label %catch.dispatch.1
+  %cs1 = catchswitch within none [label %catch.2] unwind label %catch.dispatch.1
 
 catch.2:                                          ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
   tail call void @exit(i32 0) #2
   unreachable
 
 catch.dispatch.1:                                 ; preds = %catch.dispatch
-  %1 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs2 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch.1
+  %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
   tail call void @exit(i32 0) #2
   unreachable
 
-catchendblock:                                    ; preds = %catch.dispatch.1
-  catchendpad unwind to caller
-
 try.cont:                                         ; preds = %entry
   br i1 %V, label %exit_one, label %exit_two
 
@@ -150,13 +143,13 @@ exit_two:
 ; CHECK-NOT: # exit_two
 ; CHECK: ud2
 
-; The catch(...) funclet contains %catch.dispatch
-; CHECK: # %catch.dispatch{{$}}
+; The catch(...) funclet contains %catch.2
+; CHECK: # %catch.2{{$}}
 ; CHECK: callq exit
 ; CHECK: ud2
 
-; The catch(int) funclet contains %catch.dispatch.1
-; CHECK: # %catch.dispatch.1
+; The catch(int) funclet contains %catch
+; CHECK: # %catch{{$}}
 ; CHECK: callq exit
 ; CHECK: ud2
 

Modified: llvm/trunk/test/CodeGen/X86/late-address-taken.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/late-address-taken.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/late-address-taken.ll (original)
+++ llvm/trunk/test/CodeGen/X86/late-address-taken.ll Fri Dec 11 23:38:55 2015
@@ -22,19 +22,17 @@ body:
   invoke void @f()
           to label %exit unwind label %catch.pad
 catch.pad:
-  %catch = catchpad [i32 33554467]
-          to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
 catch.body:
-  catchret %catch to label %exit
-catch.end:
-  catchendpad unwind to caller
+  %catch = catchpad within %cs1 [i32 33554467]
+  catchret from %catch to label %exit
 exit:
   ret void
 }
 ; CHECK-LABEL: catchret:  # @catchret
 ; CHECK: [[Exit:^[^ :]+]]: # Block address taken
 ; CHECK-NEXT:              # %exit
-; CHECK: # %catch.pad
+; CHECK: # %catch.body
 ; CHECK: .seh_endprolog
 ; CHECK: leaq [[Exit]](%rip), %rax
 ; CHECK: retq # CATCHRET

Modified: llvm/trunk/test/CodeGen/X86/seh-catch-all-win32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-catch-all-win32.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-catch-all-win32.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-catch-all-win32.ll Fri Dec 11 23:38:55 2015
@@ -22,16 +22,13 @@ entry:
           to label %__try.cont unwind label %lpad
 
 lpad:                                             ; preds = %entry
-  %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
-          to label %__except unwind label %endpad
+  %cs1 = catchswitch within none [label %__except] unwind to caller
 
 __except:                                         ; preds = %lpad
+  %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
   %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
-  catchret %p to label %__try.cont
-
-endpad:                                        ; preds = %lpad
-  catchendpad unwind to caller
+  catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
   ret i32 0
@@ -73,7 +70,7 @@ entry:
 ; CHECK: popl %edi
 ; CHECK: popl %ebx
 ; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad{{$}}
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except{{$}}
 ;       stackrestore
 ; CHECK: movl -24(%ebp), %esp
 ;       EH state -1

Modified: llvm/trunk/test/CodeGen/X86/seh-catch-all.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-catch-all.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-catch-all.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-catch-all.ll Fri Dec 11 23:38:55 2015
@@ -16,16 +16,13 @@ __try.cont:
   ret i32 0
 
 lpad:
-  %p = catchpad [i8* null, i32 64, i8* null]
-          to label %catchall unwind label %endpad
+  %cs1 = catchswitch within none [label %catchall] unwind to caller
 
 catchall:
+  %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %code = call i32 @llvm.eh.exceptioncode(token %p)
   call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
-  catchret %p to label %__try.cont
-
-endpad:
-  catchendpad unwind to caller
+  catchret from %p to label %__try.cont
 }
 
 ; Check that we can get the exception code from eax to the printf.
@@ -33,7 +30,7 @@ endpad:
 ; CHECK-LABEL: main:
 ; CHECK: callq crash
 ; CHECK: retq
-; CHECK: .LBB0_2: # %lpad
+; CHECK: .LBB0_2: # %catchall
 ; CHECK: leaq str(%rip), %rcx
 ; CHECK: movl %eax, %edx
 ; CHECK: callq printf

Modified: llvm/trunk/test/CodeGen/X86/seh-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-catchpad.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-catchpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-catchpad.ll Fri Dec 11 23:38:55 2015
@@ -45,13 +45,6 @@ entry:
   %call = invoke i32 @do_div(i32 1, i32 0) #4
           to label %__try.cont.12 unwind label %catch.dispatch
 
-catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null]
-          to label %__except unwind label %catchendblock
-
-__except:                                         ; preds = %catch.dispatch
-  catchret %0 to label %__except.2
-
 __except.2:                                       ; preds = %__except
   %call4 = invoke i32 @do_div(i32 1, i32 0) #4
           to label %invoke.cont.3 unwind label %ehcleanup
@@ -60,24 +53,6 @@ invoke.cont.3:
   invoke fastcc void @"\01?fin$0 at 0@main@@"() #4
           to label %__try.cont.12 unwind label %catch.dispatch.7
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %catch.dispatch.7
-
-ehcleanup:                                        ; preds = %__except.2
-  %1 = cleanuppad []
-  invoke fastcc void @"\01?fin$0 at 0@main@@"() #4
-          to label %invoke.cont.6 unwind label %ehcleanup.end
-
-invoke.cont.6:                                    ; preds = %ehcleanup
-  cleanupret %1 unwind label %catch.dispatch.7
-
-catch.dispatch.7:                                 ; preds = %invoke.cont.3, %invoke.cont.6, %ehcleanup.end, %catchendblock
-  %2 = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@main@@" to i8*)]
-          to label %__except.ret unwind label %catchendblock.8
-
-__except.ret:                                     ; preds = %catch.dispatch.7
-  catchret %2 to label %__except.9
-
 __except.9:                                       ; preds = %__except.ret
   %call11 = tail call i32 @puts(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @"\01??_C at _06IBDBCMGJ@caught?$AA@", i64 0, i64 0))
   br label %__try.cont.12
@@ -85,11 +60,27 @@ __except.9:
 __try.cont.12:                                    ; preds = %invoke.cont.3, %entry, %__except.9
   ret i32 0
 
-catchendblock.8:                                  ; preds = %catch.dispatch.7
-  catchendpad unwind to caller
+catch.dispatch:                                   ; preds = %entry
+  %cs1 = catchswitch within none [label %__except] unwind label %catch.dispatch.7
+
+__except:                                         ; preds = %catch.dispatch
+  %cp1 = catchpad within %cs1 [i8* null]
+  catchret from %cp1 to label %__except.2
 
-ehcleanup.end:                                    ; preds = %ehcleanup
-  cleanupendpad %1 unwind label %catch.dispatch.7
+ehcleanup:                                        ; preds = %__except.2
+  %cp2 = cleanuppad within none []
+  invoke fastcc void @"\01?fin$0 at 0@main@@"() #4
+          to label %invoke.cont.6 unwind label %catch.dispatch.7
+
+invoke.cont.6:                                    ; preds = %ehcleanup
+  cleanupret from %cp2 unwind label %catch.dispatch.7
+
+catch.dispatch.7:
+  %cs2 = catchswitch within none [label %__except.ret] unwind to caller
+
+__except.ret:                                     ; preds = %catch.dispatch.7
+  %cp3 = catchpad within %cs2 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@main@@" to i8*)]
+  catchret from %cp3 to label %__except.9
 }
 
 ; CHECK: main:                                   # @main
@@ -112,7 +103,7 @@ ehcleanup.end:
 ; CHECK:         addq    $32, %rsp
 ; CHECK:         popq    %rbp
 ; CHECK:         retq
-; CHECK: .LBB1_[[except1bb:[0-9]+]]:                                # %catch.dispatch
+; CHECK: .LBB1_[[except1bb:[0-9]+]]:                                # %__except
 ; CHECK: .Ltmp2:
 ; CHECK:         movl    $1, %ecx
 ; CHECK:         xorl    %edx, %edx
@@ -120,7 +111,7 @@ ehcleanup.end:
 ; CHECK: .Ltmp3:
 ; CHECK:         callq   "?fin$0 at 0@main@@"
 ; CHECK:         jmp     .LBB1_[[epilogue]]
-; CHECK: .LBB1_[[except2bb:[0-9]+]]:                                # %catch.dispatch.7
+; CHECK: .LBB1_[[except2bb:[0-9]+]]:                                # %__except.ret
 ; CHECK:         leaq    "??_C at _06IBDBCMGJ@caught?$AA@"(%rip), %rcx
 ; CHECK:         callq   puts
 ; CHECK:         jmp     .LBB1_[[epilogue]]
@@ -143,18 +134,18 @@ ehcleanup.end:
 ; CHECK-NEXT:         .long   .Ltmp2 at IMGREL+1
 ; CHECK-NEXT:         .long   .Ltmp3 at IMGREL+1
 ; CHECK-NEXT:         .long   "?filt$0 at 0@main@@"@IMGREL
-; CHECK-NEXT:         .long   .LBB1_5 at IMGREL
+; CHECK-NEXT:         .long   .LBB1_3 at IMGREL
 ; CHECK-NEXT:         .long   .Ltmp6 at IMGREL+1
 ; CHECK-NEXT:         .long   .Ltmp7 at IMGREL+1
 ; CHECK-NEXT:         .long   "?filt$0 at 0@main@@"@IMGREL
-; CHECK-NEXT:         .long   .LBB1_5 at IMGREL
+; CHECK-NEXT:         .long   .LBB1_3 at IMGREL
 ; CHECK-NEXT: .Llsda_end0:
 
 ; CHECK:         .text
 ; CHECK:         .seh_endproc
 
-; CHECK: "?dtor$3@?0?main at 4HA":
-; CHECK: .seh_proc "?dtor$3@?0?main at 4HA"
+; CHECK: "?dtor$[[finbb]]@?0?main at 4HA":
+; CHECK: .seh_proc "?dtor$[[finbb]]@?0?main at 4HA"
 ; CHECK:         .seh_handler __C_specific_handler, @unwind, @except
 ; CHECK: .LBB1_[[finbb]]:                                # %ehcleanup
 ; CHECK:         movq    %rdx, 16(%rsp)

Modified: llvm/trunk/test/CodeGen/X86/seh-except-finally.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-except-finally.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-except-finally.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-except-finally.ll Fri Dec 11 23:38:55 2015
@@ -49,37 +49,24 @@ invoke.cont2:
   br label %__try.cont
 
 __finally:                                             ; preds = %entry
-  %cleanuppad = cleanuppad []
+  %cleanuppad = cleanuppad within none []
   %locals = call i8* @llvm.localaddress()
   invoke void @"\01?fin$0 at 0@use_both@@"(i1 zeroext true, i8* %locals) #5
-          to label %invoke.cont3 unwind label %cleanupendpad
+          to label %invoke.cont3 unwind label %catch.dispatch
 
 invoke.cont3:                                     ; preds = %__finally
-  cleanupret %cleanuppad unwind label %catch.dispatch
-
-cleanupendpad:
-  cleanupendpad %cleanuppad unwind label %catch.dispatch
+  cleanupret from %cleanuppad unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %invoke.cont3, %lpad1
-  %catchpad = catchpad [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@use_both@@" to i8*)]
-          to label %__except unwind label %catchendpad
+  %cs1 = catchswitch within none [label %__except] unwind to caller
 
 __except:                                         ; preds = %catch.dispatch
+  %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@use_both@@" to i8*)]
   %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C at _08MLCMLGHM@__except?$AA@", i32 0, i32 0))
-  catchret %catchpad to label %__try.cont
-
-catchendpad:
-  catchendpad unwind to caller
+  catchret from %catchpad to label %__try.cont
 
 __try.cont:                                       ; preds = %__except, %invoke.cont2
   ret void
-
-eh.resume:                                        ; preds = %catch.dispatch
-  %exn = load i8*, i8** %exn.slot
-  %sel4 = load i32, i32* %ehselector.slot
-  %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0
-  %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %sel4, 1
-  resume { i8*, i32 } %lpad.val5
 }
 
 ; CHECK-LABEL: use_both:

Modified: llvm/trunk/test/CodeGen/X86/seh-exception-code.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-exception-code.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-exception-code.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-exception-code.ll Fri Dec 11 23:38:55 2015
@@ -14,11 +14,11 @@ entry:
           to label %__try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %pad = catchpad [i8* null]
-          to label %__except unwind label %catchendblock
+  %cs = catchswitch within none [label %__except] unwind to caller
 
 __except:                                         ; preds = %catch.dispatch
-  catchret %pad to label %__except.1
+  %pad = catchpad within %cs [i8* null]
+  catchret from %pad to label %__except.1
 
 __except.1:                                       ; preds = %__except
   %code = call i32 @llvm.eh.exceptioncode(token %pad)
@@ -27,15 +27,12 @@ __except.1:
 
 __try.cont:                                       ; preds = %entry, %__except.1
   ret void
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: ehcode:
 ; CHECK: xorl %ecx, %ecx
 ; CHECK: callq f
 
-; CHECK: # %catch.dispatch
+; CHECK: # %__except
 ; CHECK: movl %eax, %ecx
 ; CHECK-NEXT: callq f

Modified: llvm/trunk/test/CodeGen/X86/seh-finally.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-finally.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-finally.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-finally.ll Fri Dec 11 23:38:55 2015
@@ -17,15 +17,9 @@ invoke.cont:
   ret i32 0
 
 lpad:                                             ; preds = %entry
-  %p = cleanuppad []
-  %call2 = invoke i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
-          to label %invoke.cont1 unwind label %endpad
-
-invoke.cont1:                                     ; preds = %lpad
-  cleanupret %p unwind to caller
-
-endpad:                                   ; preds = %lpad
-  cleanupendpad %p unwind to caller
+  %p = cleanuppad within none []
+  %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
+  cleanupret from %p unwind to caller
 }
 
 ; X64-LABEL: main:

Modified: llvm/trunk/test/CodeGen/X86/seh-safe-div-win32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-safe-div-win32.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-safe-div-win32.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-safe-div-win32.ll Fri Dec 11 23:38:55 2015
@@ -31,28 +31,22 @@ entry:
           to label %__try.cont unwind label %lpad0
 
 lpad0:
-  %p0 = catchpad [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
-          to label %handler0 unwind label %endpad0
+  %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
 
 handler0:
+  %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
   call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
   store i32 -1, i32* %r, align 4
-  catchret %p0 to label %__try.cont
-
-endpad0:
-  catchendpad unwind label %lpad1
+  catchret from %p0 to label %__try.cont
 
 lpad1:
-  %p1 = catchpad [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
-          to label %handler1 unwind label %endpad1
+  %cs1 = catchswitch within none [label %handler1] unwind to caller
 
 handler1:
+  %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
   call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
   store i32 -2, i32* %r, align 4
-  catchret %p1 to label %__try.cont
-
-endpad1:
-  catchendpad unwind to caller
+  catchret from %p1 to label %__try.cont
 
 __try.cont:
   %safe_ret = load i32, i32* %r, align 4
@@ -71,13 +65,13 @@ __try.cont:
 
 ; Landing pad code
 
-; CHECK: [[lpad0:LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:LBB0_[0-9]+]]: # %handler0
 ; 	Restore SP
 ; CHECK: movl {{.*}}(%ebp), %esp
 ; CHECK: calll _puts
 ; CHECK: jmp [[cont_bb]]
 
-; CHECK: [[lpad1:LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:LBB0_[0-9]+]]: # %handler1
 ; 	Restore SP
 ; CHECK: movl {{.*}}(%ebp), %esp
 ; CHECK: calll _puts
@@ -87,10 +81,10 @@ __try.cont:
 ; CHECK: L__ehtable$safe_div:
 ; CHECK-NEXT: .long -1
 ; CHECK-NEXT: .long _safe_div_filt1
-; CHECK-NEXT: .long [[lpad1]]
+; CHECK-NEXT: .long [[handler1]]
 ; CHECK-NEXT: .long 0
 ; CHECK-NEXT: .long _safe_div_filt0
-; CHECK-NEXT: .long [[lpad0]]
+; CHECK-NEXT: .long [[handler0]]
 
 define void @try_body(i32* %r, i32* %n, i32* %d) {
 entry:

Modified: llvm/trunk/test/CodeGen/X86/seh-safe-div.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-safe-div.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-safe-div.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-safe-div.ll Fri Dec 11 23:38:55 2015
@@ -30,28 +30,22 @@ entry:
           to label %__try.cont unwind label %lpad0
 
 lpad0:
-  %p0 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
-          to label %handler0 unwind label %endpad0
+  %cs0 = catchswitch within none [label %handler0] unwind label %lpad1
 
 handler0:
+  %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
   call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
   store i32 -1, i32* %r, align 4
-  catchret %p0 to label %__try.cont
-
-endpad0:
-  catchendpad unwind label %lpad1
+  catchret from %p0 to label %__try.cont
 
 lpad1:
-  %p1 = catchpad [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
-          to label %handler1 unwind label %endpad1
+  %cs1 = catchswitch within none [label %handler1] unwind to caller
 
 handler1:
+  %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
   call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
   store i32 -2, i32* %r, align 4
-  catchret %p1 to label %__try.cont
-
-endpad1:
-  catchendpad unwind to caller
+  catchret from %p1 to label %__try.cont
 
 __try.cont:
   %safe_ret = load i32, i32* %r, align 4
@@ -73,12 +67,12 @@ __try.cont:
 
 ; Landing pad code
 
-; CHECK: [[lpad0:\.LBB0_[0-9]+]]: # %lpad0
+; CHECK: [[handler0:\.LBB0_[0-9]+]]: # %handler0
 ; CHECK: callq puts
 ; CHECK: movl $-1, [[rloc]]
 ; CHECK: jmp [[cont_bb]]
 
-; CHECK: [[lpad1:\.LBB0_[0-9]+]]: # %lpad1
+; CHECK: [[handler1:\.LBB0_[0-9]+]]: # %handler1
 ; CHECK: callq puts
 ; CHECK: movl $-2, [[rloc]]
 ; CHECK: jmp [[cont_bb]]
@@ -89,11 +83,11 @@ __try.cont:
 ; CHECK-NEXT: .long .Ltmp0 at IMGREL+1
 ; CHECK-NEXT: .long .Ltmp1 at IMGREL+1
 ; CHECK-NEXT: .long safe_div_filt0 at IMGREL
-; CHECK-NEXT: .long [[lpad0]]@IMGREL
+; CHECK-NEXT: .long [[handler0]]@IMGREL
 ; CHECK-NEXT: .long .Ltmp0 at IMGREL+1
 ; CHECK-NEXT: .long .Ltmp1 at IMGREL+1
 ; CHECK-NEXT: .long safe_div_filt1 at IMGREL
-; CHECK-NEXT: .long [[lpad1]]@IMGREL
+; CHECK-NEXT: .long [[handler1]]@IMGREL
 ; CHECK-NEXT: .Llsda_end0:
 ; CHECK: .text
 ; CHECK: .seh_endproc

Modified: llvm/trunk/test/CodeGen/X86/seh-stack-realign.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-stack-realign.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/seh-stack-realign.ll (original)
+++ llvm/trunk/test/CodeGen/X86/seh-stack-realign.ll Fri Dec 11 23:38:55 2015
@@ -23,16 +23,13 @@ entry:
           to label %__try.cont unwind label %lpad
 
 lpad:                                             ; preds = %entry
-  %p = catchpad [i8* bitcast (i32 ()* @"filt$main" to i8*)]
-          to label %__except unwind label %endpad
+  %cs1 = catchswitch within none [label %__except] unwind to caller
 
 __except:                                         ; preds = %lpad
+  %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
   %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
-  catchret %p to label %__try.cont
-
-endpad:
-  catchendpad unwind to caller
+  catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
   ret i32 0
@@ -63,7 +60,7 @@ entry:
 ; CHECK: movl $0, 40(%esi)
 ; CHECK: calll _crash
 ; CHECK: retl
-; CHECK: LBB0_[[lpbb:[0-9]+]]: # %lpad
+; CHECK: LBB0_[[lpbb:[0-9]+]]: # %__except
 ;       Restore ESP
 ; CHECK: movl -24(%ebp), %esp
 ;       Restore ESI

Modified: llvm/trunk/test/CodeGen/X86/tail-dup-catchret.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tail-dup-catchret.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tail-dup-catchret.ll (original)
+++ llvm/trunk/test/CodeGen/X86/tail-dup-catchret.ll Fri Dec 11 23:38:55 2015
@@ -8,19 +8,16 @@ entry:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %0 to label %try.cont
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %entry, %catch
   %b.0 = phi i1 [ false, %catch ], [ true, %entry ]
   tail call void @h(i1 zeroext %b.0)
   ret void
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: _f:

Modified: llvm/trunk/test/CodeGen/X86/tail-merge-wineh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tail-merge-wineh.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tail-merge-wineh.ll (original)
+++ llvm/trunk/test/CodeGen/X86/tail-merge-wineh.ll Fri Dec 11 23:38:55 2015
@@ -54,11 +54,11 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind label %catch.dispatch.7
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %1 to label %catchret.dest
+  %1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  catchret from %1 to label %catchret.dest
 
 catchret.dest:                                    ; preds = %catch
   br label %try.cont
@@ -70,11 +70,11 @@ try.cont:
           to label %unreachable unwind label %catch.dispatch.2
 
 catch.dispatch.2:                                 ; preds = %try.cont
-  %3 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch.4 unwind label %catchendblock.3
+  %cs2 = catchswitch within none [label %catch.4] unwind label %catch.dispatch.7
 
 catch.4:                                          ; preds = %catch.dispatch.2
-  catchret %3 to label %catchret.dest.5
+  %3 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  catchret from %3 to label %catchret.dest.5
 
 catchret.dest.5:                                  ; preds = %catch.4
   br label %try.cont.6
@@ -82,15 +82,12 @@ catchret.dest.5:
 try.cont.6:                                       ; preds = %catchret.dest.5
   br label %try.cont.11
 
-catchendblock.3:                                  ; preds = %catch.dispatch.2
-  catchendpad unwind label %catch.dispatch.7
-
-catch.dispatch.7:                                 ; preds = %catchendblock.3, %catchendblock
-  %4 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch.9 unwind label %catchendblock.8
+catch.dispatch.7:
+  %cs3 = catchswitch within none [label %catch.9] unwind to caller
 
 catch.9:                                          ; preds = %catch.dispatch.7
-  catchret %4 to label %catchret.dest.10
+  %4 = catchpad within %cs3 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  catchret from %4 to label %catchret.dest.10
 
 catchret.dest.10:                                 ; preds = %catch.9
   br label %try.cont.11
@@ -98,12 +95,6 @@ catchret.dest.10:
 try.cont.11:                                      ; preds = %catchret.dest.10, %try.cont.6
   ret void
 
-catchendblock.8:                                  ; preds = %catch.dispatch.7
-  catchendpad unwind to caller
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %catch.dispatch.7
-
 unreachable:                                      ; preds = %try.cont, %entry
   unreachable
 }

Modified: llvm/trunk/test/CodeGen/X86/win-catchpad-csrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad-csrs.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-catchpad-csrs.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-catchpad-csrs.ll Fri Dec 11 23:38:55 2015
@@ -16,7 +16,7 @@ declare void @useints(...)
 declare void @f(i32 %p)
 declare i32 @__CxxFrameHandler3(...)
 
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   %a = call i32 @getint()
   %b = call i32 @getint()
@@ -26,22 +26,16 @@ entry:
   invoke void @f(i32 1)
           to label %try.cont unwind label %catch.dispatch
 
-catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch unwind label %catchendblock
-
-catch:
-  invoke void @f(i32 2)
-          to label %invoke.cont.2 unwind label %catchendblock
-
-invoke.cont.2:                                    ; preds = %catch
-  catchret %0 to label %try.cont
-
-try.cont:                                         ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
   ret i32 0
 
-catchendblock:                                    ; preds = %catch,
-  catchendpad unwind to caller
+catch.dispatch:
+  %cs = catchswitch within none [label %handler1] unwind to caller
+
+handler1:
+  %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  call void @f(i32 2)
+  catchret from %h1 to label %try.cont
 }
 
 ; X86-LABEL: _try_catch_catch:
@@ -71,7 +65,7 @@ catchendblock:
 ; X86: jmp [[contbb]]
 
 ; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
 ; X86: pushl %ebp
 ; X86-NOT: pushl
 ; X86: subl $16, %esp
@@ -120,7 +114,7 @@ catchendblock:
 ; X64: retq
 
 ; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5
@@ -159,18 +153,15 @@ entry:
   invoke void @f(i32 1)
           to label %try.cont unwind label %catch.dispatch
 
-catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch unwind label %catchendblock
+catch.dispatch:
+  %cs = catchswitch within none [label %handler1] unwind to caller
 
-catch:
-  catchret %0 to label %try.cont
+handler1:
+  %0 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  catchret from %0 to label %try.cont
 
-try.cont:                                         ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
   ret i32 0
-
-catchendblock:                                    ; preds = %catch,
-  catchendpad unwind to caller
 }
 
 ; X64-LABEL: try_one_csr:
@@ -198,7 +189,7 @@ catchendblock:
 ; X64: retq
 
 ; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_one_csr at 4HA":
-; X64: LBB1_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catch1bb]]: # %handler1{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5
@@ -226,18 +217,15 @@ entry:
   invoke void @f(i32 1)
           to label %try.cont unwind label %catch.dispatch
 
-catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-          to label %catch unwind label %catchendblock
+catch.dispatch:
+  %cs = catchswitch within none [label %handler1] unwind to caller
 
-catch:
-  catchret %0 to label %try.cont
+handler1:
+  %cp1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  catchret from %cp1 to label %try.cont
 
-try.cont:                                         ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
   ret i32 0
-
-catchendblock:                                    ; preds = %catch,
-  catchendpad unwind to caller
 }
 
 ; X64-LABEL: try_no_csr:
@@ -259,7 +247,7 @@ catchendblock:
 ; X64: retq
 
 ; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_no_csr at 4HA":
-; X64: LBB2_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB2_[[catch1bb]]: # %handler1{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5

Added: llvm/trunk/test/CodeGen/X86/win-catchpad-nested-cxx.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad-nested-cxx.ll?rev=255422&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-catchpad-nested-cxx.ll (added)
+++ llvm/trunk/test/CodeGen/X86/win-catchpad-nested-cxx.ll Fri Dec 11 23:38:55 2015
@@ -0,0 +1,105 @@
+; RUN: llc -verify-machineinstrs -mtriple=i686-pc-windows-msvc < %s \
+; RUN:     | FileCheck --check-prefix=CHECK --check-prefix=X86 %s
+; RUN: llc -verify-machineinstrs -mtriple=x86_64-pc-windows-msvc < %s \
+; RUN:     | FileCheck --check-prefix=CHECK --check-prefix=X64 %s
+
+; Loosely based on IR for this C++ source code:
+;   void f(int p);
+;   void try_in_catch() {
+;     try {
+;       f(1);
+;     } catch (...) {
+;       try {
+;         f(2);
+;       } catch (...) {
+;         f(3);
+;       }
+;     }
+;   }
+
+declare void @f(i32 %p)
+declare i32 @__CxxFrameHandler3(...)
+
+define i32 @try_in_catch() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @f(i32 1)
+          to label %try.cont unwind label %catch.dispatch.1
+try.cont:
+  ret i32 0
+
+catch.dispatch.1:
+  %cs1 = catchswitch within none [label %handler1] unwind to caller
+handler1:
+  %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  invoke void @f(i32 2)
+          to label %catchret1 unwind label %catch.dispatch.2
+catchret1:
+  catchret from %h1 to label %try.cont
+
+catch.dispatch.2:
+  %cs2 = catchswitch within %h1 [label %handler2] unwind to caller
+handler2:
+  %h2 = catchpad within %cs2 [i8* null, i32 64, i8* null]
+  call void @f(i32 3)
+  catchret from %h2 to label %catchret1
+}
+
+; X86-LABEL: L__ehtable$try_in_catch:
+; X64-LABEL: $cppxdata$try_in_catch:
+; CHECK-NEXT: .long   429065506
+; CHECK-NEXT: .long   4
+; CHECK-NEXT: .long   ($stateUnwindMap$try_in_catch)
+; CHECK-NEXT: .long   2
+; CHECK-NEXT: .long   ($tryMap$try_in_catch)
+; ip2state num + ptr
+; X86-NEXT: .long   0
+; X86-NEXT: .long   0
+; X64-NEXT: .long   7
+; X64-NEXT: .long   ($ip2state$try_in_catch)
+; unwindhelp offset
+; X64-NEXT: .long   40
+; CHECK-NEXT: .long   0
+; EHFlags
+; CHECK-NEXT: .long   1
+
+; CHECK: $tryMap$try_in_catch:
+; CHECK-NEXT: .long   2
+; CHECK-NEXT: .long   2
+; CHECK-NEXT: .long   3
+; CHECK-NEXT: .long   1
+; CHECK-NEXT: .long   ($handlerMap$0$try_in_catch)
+; CHECK-NEXT: .long   0
+; CHECK-NEXT: .long   0
+; CHECK-NEXT: .long   3
+; CHECK-NEXT: .long   1
+; CHECK-NEXT: .long   ($handlerMap$1$try_in_catch)
+
+; CHECK: $handlerMap$0$try_in_catch:
+; CHECK-NEXT:   .long   64
+; CHECK-NEXT:   .long   0
+; CHECK-NEXT:   .long   0
+; CHECK-NEXT:   .long   "?catch${{[0-9]+}}@?0?try_in_catch at 4HA"
+; X64-NEXT:   .long   56
+
+; CHECK: $handlerMap$1$try_in_catch:
+; CHECK-NEXT:   .long   64
+; CHECK-NEXT:   .long   0
+; CHECK-NEXT:   .long   0
+; CHECK-NEXT:   .long   "?catch${{[0-9]+}}@?0?try_in_catch at 4HA"
+; X64-NEXT:   .long   56
+
+; X64: $ip2state$try_in_catch:
+; X64-NEXT: .long   .Lfunc_begin0 at IMGREL
+; X64-NEXT: .long   -1
+; X64-NEXT: .long   .Ltmp0 at IMGREL+1
+; X64-NEXT: .long   0
+; X64-NEXT: .long   .Ltmp1 at IMGREL+1
+; X64-NEXT: .long   -1
+; X64-NEXT: .long   "?catch$2@?0?try_in_catch at 4HA"@IMGREL
+; X64-NEXT: .long   1
+; X64-NEXT: .long   .Ltmp2 at IMGREL+1
+; X64-NEXT: .long   2
+; X64-NEXT: .long   .Ltmp3 at IMGREL+1
+; X64-NEXT: .long   1
+; X64-NEXT: .long   "?catch$4@?0?try_in_catch at 4HA"@IMGREL
+; X64-NEXT: .long   3

Modified: llvm/trunk/test/CodeGen/X86/win-catchpad-nested.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad-nested.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-catchpad-nested.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-catchpad-nested.ll Fri Dec 11 23:38:55 2015
@@ -7,26 +7,25 @@ declare void @f()
 define void @test1() personality void ()* @ProcessCLRException {
 entry:
   invoke void @f()
-          to label %exit unwind label %outer.pad
-outer.pad:
-  %outer = catchpad [i32 1]
-          to label %outer.catch unwind label %outer.end
+          to label %exit unwind label %catch.dispatch.1
+exit:
+  ret void
+
+catch.dispatch.1:
+  %cs1 = catchswitch within none [label %outer.catch] unwind to caller
+
 outer.catch:
+  %cp1 = catchpad within %cs1 [i32 1]
   invoke void @f()
-          to label %outer.ret unwind label %inner.pad
-inner.pad:
-  %inner = catchpad [i32 2]
-          to label %inner.ret unwind label %inner.end
-inner.ret:
-  catchret %inner to label %outer.ret
-inner.end:
-  catchendpad unwind label %outer.end
+          to label %outer.ret unwind label %catch.dispatch.2
 outer.ret:
-  catchret %outer to label %exit
-outer.end:
-  catchendpad unwind to caller
-exit:
-  ret void
+  catchret from %cp1 to label %exit
+
+catch.dispatch.2:
+  %cs2 = catchswitch within %cp1 [label %inner.catch] unwind to caller
+inner.catch:
+  %cp2 = catchpad within %cs2 [i32 2]
+  catchret from %cp2 to label %outer.ret
 }
 
 ; Check the catchret targets
@@ -37,7 +36,7 @@ exit:
 ; CHECK-NEXT:                  # %outer.ret
 ; CHECK-NEXT: leaq [[Exit]](%rip), %rax
 ; CHECK:      retq   # CATCHRET
-; CHECK: {{^[^: ]+}}: # %inner.pad
+; CHECK: {{^[^: ]+}}: # %inner.catch
 ; CHECK: .seh_endprolog
 ; CHECK-NEXT: leaq [[OuterRet]](%rip), %rax
 ; CHECK:      retq   # CATCHRET

Modified: llvm/trunk/test/CodeGen/X86/win-catchpad-varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad-varargs.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-catchpad-varargs.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-catchpad-varargs.ll Fri Dec 11 23:38:55 2015
@@ -13,20 +13,17 @@ entry:
           to label %return unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %ap1 = bitcast i8** %ap to i8*
   call void @llvm.va_start(i8* %ap1)
   %argp.cur = load i8*, i8** %ap
   %1 = bitcast i8* %argp.cur to i32*
   %arg2 = load i32, i32* %1
   call void @llvm.va_end(i8* %ap1)
-  catchret %0 to label %return
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
+  catchret from %0 to label %return
 
 return:                                           ; preds = %entry, %catch
   %retval.0 = phi i32 [ %arg2, %catch ], [ -1, %entry ]

Modified: llvm/trunk/test/CodeGen/X86/win-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-catchpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-catchpad.ll Fri Dec 11 23:38:55 2015
@@ -28,7 +28,7 @@ declare void @f(i32 %p, i32* %l)
 declare i1 @getbool()
 declare i32 @__CxxFrameHandler3(...)
 
-define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @try_catch_catch() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   %e.addr = alloca i32
   %local = alloca i32
@@ -36,33 +36,21 @@ entry:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i32* %e.addr]
-          to label %catch unwind label %catch.dispatch.2
+  %cs = catchswitch within none [label %handler1, label %handler2] unwind to caller
 
-catch:                                            ; preds = %catch.dispatch
+handler1:
+  %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i32* %e.addr]
   %e = load i32, i32* %e.addr
-  invoke void @f(i32 %e, i32* %local)
-          to label %invoke.cont.2 unwind label %catchendblock
+  call void @f(i32 %e, i32* %local)
+  catchret from %h1 to label %try.cont
 
-invoke.cont.2:                                    ; preds = %catch
-  catchret %0 to label %try.cont
+handler2:
+  %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
+  call void @f(i32 3, i32* %local)
+  catchret from %h2 to label %try.cont
 
-catch.dispatch.2:                                   ; preds = %catch.dispatch
-  %1 = catchpad [i8* null, i32 u0x40, i8* null]
-          to label %catch.2 unwind label %catchendblock
-
-catch.2:                                            ; preds = %catch.dispatch.2
-  invoke void @f(i32 3, i32* %local)
-          to label %invoke.cont.3 unwind label %catchendblock
-
-invoke.cont.3:                                    ; preds = %catch.2
-  catchret %1 to label %try.cont
-
-try.cont:                                         ; preds = %entry, %invoke.cont.2, %invoke.cont.3
+try.cont:
   ret i32 0
-
-catchendblock:                                    ; preds = %catch, %catch.2, %catch.dispatch.2
-  catchendpad unwind to caller
 }
 
 ; X86-LABEL: _try_catch_catch:
@@ -76,25 +64,25 @@ catchendblock:
 ; X86: retl
 
 ; X86: [[restorebb1:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT:                        # %invoke.cont.2
+; X86-NEXT:                        # %handler1
 ; X86-NEXT: addl $12, %ebp
 ; X86: jmp [[contbb]]
 
 ; FIXME: These should be de-duplicated.
 ; X86: [[restorebb2:LBB0_[0-9]+]]: # Block address taken
-; X86-NEXT:                        # %invoke.cont.3
+; X86-NEXT:                        # %handler2
 ; X86-NEXT: addl $12, %ebp
 ; X86: jmp [[contbb]]
 
 ; X86: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X86: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X86: LBB0_[[catch1bb]]: # %handler1{{$}}
 ; X86: pushl %ebp
 ; X86: subl $8, %esp
 ; X86: addl $12, %ebp
 ; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl -32(%ebp), %[[e_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: movl -32(%ebp), %[[e_reg:[a-z]+]]
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
 ; X86-DAG: movl %[[addr_reg]], 4(%esp)
 ; X86-DAG: movl %[[e_reg]], (%esp)
 ; X86: calll _f
@@ -104,13 +92,13 @@ catchendblock:
 ; X86-NEXT: retl
 
 ; X86: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X86: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X86: LBB0_[[catch2bb]]: # %handler2{{$}}
 ; X86: pushl %ebp
 ; X86: subl $8, %esp
 ; X86: addl $12, %ebp
 ; X86: movl %esp, -[[sp_offset]](%ebp)
-; X86: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
-; X86: movl $1, -{{[0-9]+}}(%ebp)
+; X86-DAG: leal -[[local_offs]](%ebp), %[[addr_reg:[a-z]+]]
+; X86-DAG: movl $1, -{{[0-9]+}}(%ebp)
 ; X86-DAG: movl %[[addr_reg]], 4(%esp)
 ; X86-DAG: movl $3, (%esp)
 ; X86: calll _f
@@ -151,7 +139,7 @@ catchendblock:
 ; X64: retq
 
 ; X64: "?catch$[[catch1bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X64: LBB0_[[catch1bb]]: # %catch.dispatch{{$}}
+; X64: LBB0_[[catch1bb]]: # %handler1{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5
@@ -159,7 +147,6 @@ catchendblock:
 ; X64: .seh_stackalloc 32
 ; X64: leaq 48(%rdx), %rbp
 ; X64: .seh_endprologue
-; X64-DAG: .Ltmp4
 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
 ; X64-DAG: movl -12(%rbp), %ecx
 ; X64: callq f
@@ -169,7 +156,7 @@ catchendblock:
 ; X64-NEXT: retq
 
 ; X64: "?catch$[[catch2bb:[0-9]+]]@?0?try_catch_catch at 4HA":
-; X64: LBB0_[[catch2bb]]: # %catch.dispatch.2{{$}}
+; X64: LBB0_[[catch2bb]]: # %handler2{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5
@@ -180,7 +167,6 @@ catchendblock:
 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
 ; X64-DAG: movl $3, %ecx
 ; X64: callq f
-; X64: .Ltmp3
 ; X64: leaq [[contbb]](%rip), %rax
 ; X64-NEXT: addq $32, %rsp
 ; X64-NEXT: popq %rbp
@@ -192,7 +178,7 @@ catchendblock:
 ; X64-NEXT: .long   ($stateUnwindMap$try_catch_catch)@IMGREL
 ; X64-NEXT: .long   1
 ; X64-NEXT: .long   ($tryMap$try_catch_catch)@IMGREL
-; X64-NEXT: .long   4
+; X64-NEXT: .long   5
 ; X64-NEXT: .long   ($ip2state$try_catch_catch)@IMGREL
 ; X64-NEXT: .long   40
 ; X64-NEXT: .long   0
@@ -222,33 +208,35 @@ catchendblock:
 ; X64-NEXT: .long   -1
 ; X64-NEXT: .long   .Ltmp0 at IMGREL+1
 ; X64-NEXT: .long   0
-; X64-NEXT: .long   .Ltmp4 at IMGREL+1
-; X64-NEXT: .long   1
-; X64-NEXT: .long   .Ltmp3 at IMGREL+1
+; X64-NEXT: .long   .Ltmp1 at IMGREL+1
 ; X64-NEXT: .long   -1
+; X64-NEXT: .long   "?catch$[[catch1bb]]@?0?try_catch_catch at 4HA"@IMGREL
+; X64-NEXT: .long   1
+; X64-NEXT: .long   "?catch$[[catch2bb]]@?0?try_catch_catch at 4HA"@IMGREL
+; X64-NEXT: .long   1
 
 
-define i32 @branch_to_normal_dest() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+define i32 @branch_to_normal_dest() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   invoke void @f(i32 1, i32* null)
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
+  %cp1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
+  br label %loop
+
+loop:
   %V = call i1 @getbool()
-  br i1 %V, label %catch, label %catch.done
+  br i1 %V, label %loop, label %catch.done
 
 catch.done:
-  catchret %0 to label %try.cont
+  catchret from %cp1 to label %try.cont
 
 try.cont:
   ret i32 0
-
-catchendblock:
-  catchendpad unwind to caller
 }
 
 ; X86-LABEL: _branch_to_normal_dest:
@@ -262,17 +250,16 @@ catchendblock:
 ; X86-NEXT: addl $12, %ebp
 ; X86: jmp [[contbb]]
 
-; X86: "?catch$[[catchdispbb:[0-9]+]]@?0?branch_to_normal_dest at 4HA":
-; X86: LBB1_[[catchdispbb]]: # %catch.dispatch{{$}}
+; X86: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest at 4HA":
+; X86: LBB1_[[catchbb]]: # %catch{{$}}
 ; X86: pushl %ebp
 ; X86: subl $8, %esp
 ; X86: addl $12, %ebp
-
-; X86: LBB1_[[catchbb:[0-9]+]]: # %catch
-; X86: movl    $-1, -16(%ebp)
+; X86: LBB1_[[loopbb:[0-9]+]]: # %loop
+; X86: movl    $1, -16(%ebp)
 ; X86: calll   _getbool
 ; X86: testb   $1, %al
-; X86: jne LBB1_[[catchbb]]
+; X86: jne LBB1_[[loopbb]]
 ; X86: # %catch.done
 ; X86-NEXT: movl $[[restorebb]], %eax
 ; X86-NEXT: addl $8, %esp
@@ -284,7 +271,7 @@ catchendblock:
 ; X86-NEXT:   .long   64
 ; X86-NEXT:   .long   0
 ; X86-NEXT:   .long   0
-; X86-NEXT:   .long   "?catch$[[catchdispbb]]@?0?branch_to_normal_dest at 4HA"
+; X86-NEXT:   .long   "?catch$[[catchbb]]@?0?branch_to_normal_dest at 4HA"
 
 ; X64-LABEL: branch_to_normal_dest:
 ; X64: # %entry
@@ -305,7 +292,7 @@ catchendblock:
 ; X64: retq
 
 ; X64: "?catch$[[catchbb:[0-9]+]]@?0?branch_to_normal_dest at 4HA":
-; X64: LBB1_[[catchbb]]: # %catch.dispatch{{$}}
+; X64: LBB1_[[catchbb]]: # %catch{{$}}
 ; X64: movq %rdx, 16(%rsp)
 ; X64: pushq %rbp
 ; X64: .seh_pushreg 5
@@ -313,7 +300,7 @@ catchendblock:
 ; X64: .seh_stackalloc 32
 ; X64: leaq 48(%rdx), %rbp
 ; X64: .seh_endprologue
-; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %catch
+; X64: .LBB1_[[normal_dest_bb:[0-9]+]]: # %loop
 ; X64: callq   getbool
 ; X64: testb   $1, %al
 ; X64: jne     .LBB1_[[normal_dest_bb]]
@@ -329,7 +316,7 @@ catchendblock:
 ; X64-NEXT: .long   ($stateUnwindMap$branch_to_normal_dest)@IMGREL
 ; X64-NEXT: .long   1
 ; X64-NEXT: .long   ($tryMap$branch_to_normal_dest)@IMGREL
-; X64-NEXT: .long   3
+; X64-NEXT: .long   4
 ; X64-NEXT: .long   ($ip2state$branch_to_normal_dest)@IMGREL
 ; X64-NEXT: .long   40
 ; X64-NEXT: .long   0
@@ -362,3 +349,5 @@ catchendblock:
 ; X64-NEXT: .long   0
 ; X64-NEXT: .long   .Ltmp[[after_call]]@IMGREL+1
 ; X64-NEXT: .long   -1
+; X64-NEXT: .long   "?catch$[[catchbb]]@?0?branch_to_normal_dest at 4HA"@IMGREL
+; X64-NEXT: .long   1

Modified: llvm/trunk/test/CodeGen/X86/win-cleanuppad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-cleanuppad.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-cleanuppad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-cleanuppad.ll Fri Dec 11 23:38:55 2015
@@ -14,9 +14,9 @@ invoke.cont:
   ret void
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   call x86_thiscallcc void @"\01??1Dtor@@QAE at XZ"(%struct.Dtor* %o) #2
-  cleanupret %0 unwind to caller
+  cleanupret from %0 unwind to caller
 }
 
 ; CHECK: simple_cleanup:                         # @simple_cleanup
@@ -77,14 +77,14 @@ invoke.cont.2:
   ret void
 
 cleanup.inner:                                        ; preds = %invoke.cont
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   call x86_thiscallcc void @"\01??1Dtor@@QAE at XZ"(%struct.Dtor* %o2) #2
-  cleanupret %0 unwind label %cleanup.outer
+  cleanupret from %0 unwind label %cleanup.outer
 
 cleanup.outer:                                      ; preds = %invoke.cont.1, %cleanup.inner, %entry
-  %1 = cleanuppad []
+  %1 = cleanuppad within none []
   call x86_thiscallcc void @"\01??1Dtor@@QAE at XZ"(%struct.Dtor* %o1) #2
-  cleanupret %1 unwind to caller
+  cleanupret from %1 unwind to caller
 }
 
 ; X86-LABEL: _nested_cleanup:

Modified: llvm/trunk/test/CodeGen/X86/win-funclet-cfi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-funclet-cfi.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-funclet-cfi.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-funclet-cfi.ll Fri Dec 11 23:38:55 2015
@@ -9,24 +9,21 @@ entry:
           to label %unreachable unwind label %cleanupblock
 
 cleanupblock:
-  %cleanp = cleanuppad []
+  %cleanp = cleanuppad within none []
   call void @g()
-  cleanupret %cleanp unwind label %catch.dispatch
+  cleanupret from %cleanp unwind label %catch.dispatch
 
 catch.dispatch:
-  %cp = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
+  %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
   call void @g()
-  catchret %cp to label %try.cont
+  catchret from %cp to label %try.cont
 
 try.cont:
   ret void
 
-catchendblock:
-  catchendpad unwind to caller
-
 unreachable:
   unreachable
 }
@@ -70,7 +67,7 @@ declare i32 @__CxxFrameHandler3(...)
 ; CHECK: "?catch$[[catch:[0-9]+]]@?0??f@@YAXXZ at 4HA":
 ; CHECK: .seh_proc "?catch$[[catch]]@?0??f@@YAXXZ at 4HA"
 ; CHECK-NEXT: .seh_handler __CxxFrameHandler3, @unwind, @except
-; CHECK: LBB0_[[catch]]: # %catch.dispatch{{$}}
+; CHECK: LBB0_[[catch]]: # %catch{{$}}
 
 ; Emit CFI for pushing RBP.
 ; CHECK: movq    %rdx, 16(%rsp)

Modified: llvm/trunk/test/CodeGen/X86/win-mixed-ehpersonality.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-mixed-ehpersonality.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win-mixed-ehpersonality.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win-mixed-ehpersonality.ll Fri Dec 11 23:38:55 2015
@@ -18,12 +18,10 @@ cont:
   ret i32 0
 
 lpad:
-  %p = catchpad [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
-      to label %catch unwind label %endpad
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchret %p to label %ret1
-endpad:
-  catchendpad unwind to caller
+  %p = catchpad within %cs [i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)]
+  catchret from %p to label %ret1
 
 ret1:
   ret i32 1
@@ -39,7 +37,7 @@ define internal i32 @filt_g(i8*, i8*) {
 ; CHECK: xorl %eax, %eax
 ; CHECK: .LBB0_[[epilogue:[0-9]+]]
 ; CHECK: retq
-; CHECK: # %lpad
+; CHECK: # %catch{{$}}
 ; CHECK: movl $1, %eax
 ; CHECK: jmp .LBB0_[[epilogue]]
 

Modified: llvm/trunk/test/CodeGen/X86/win32-eh-states.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-eh-states.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-eh-states.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-eh-states.ll Fri Dec 11 23:38:55 2015
@@ -1,4 +1,5 @@
-; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck %s
+; RUN: llc -mtriple=i686-pc-windows-msvc   < %s | FileCheck %s --check-prefix=X86
+; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s --check-prefix=X64
 
 ; Based on this source:
 ; extern "C" void may_throw(int);
@@ -40,59 +41,167 @@ invoke.cont:
           to label %try.cont.9 unwind label %lpad
 
 try.cont.9:                                       ; preds = %invoke.cont.3, %invoke.cont, %catch.7
-  ; FIXME: Something about our CFG breaks TailDuplication. This empy asm blocks
-  ; it so we can focus on testing the state numbering.
-  call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"()
   ret void
 
 lpad:                                             ; preds = %catch, %entry
-  %p1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-      to label %catch unwind label %end.inner.catch
+  %cs1 = catchswitch within none [label %catch] unwind label %lpad.1
 
 catch:                                            ; preds = %lpad.1
+  %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
   invoke void @may_throw(i32 3)
-          to label %invoke.cont.3 unwind label %end.inner.catch
+          to label %invoke.cont.3 unwind label %lpad.1
 
 invoke.cont.3:                                    ; preds = %catch
-  catchret %p1 to label %try.cont.9
-
-
-end.inner.catch:
-  catchendpad unwind label %lpad.1
+  catchret from %p1 to label %try.cont.9
 
 lpad.1:                                           ; preds = %invoke.cont
-  %p2 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
-      to label %catch.7 unwind label %eh.resume
+  %cs2 = catchswitch within none [label %catch.7] unwind to caller
 
 catch.7:
-  invoke void @may_throw(i32 4)
-          to label %invoke.cont.10 unwind label %eh.resume
+  %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
+  call void @may_throw(i32 4)
+  catchret from %p2 to label %try.cont.9
+}
+
+; X86-LABEL: _f:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$f, {{.*}}
+;
+; X86: movl $0, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $3, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $4, (%esp)
+; X86: calll _may_throw
+
+
+; X64-LABEL: f:
+; X64-LABEL: $ip2state$f:
+; X64-NEXT:   .long .Lfunc_begin0 at IMGREL
+; X64-NEXT:   .long -1
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long 0
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long 1
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long -1
+; X64-NEXT:   .long "?catch${{.*}}@?0?f at 4HA"@IMGREL
+; X64-NEXT:   .long 2
+; X64-NEXT:   .long "?catch${{.*}}@?0?f at 4HA"@IMGREL
+; X64-NEXT:   .long 3
 
-invoke.cont.10:
-  catchret %p2 to label %try.cont.9
+; Based on this source:
+; extern "C" void may_throw(int);
+; struct S { ~S(); };
+; void g() {
+;   S x;
+;   try {
+;     may_throw(-1);
+;   } catch (...) {
+;     may_throw(0);
+;     {
+;       S y;
+;       may_throw(1);
+;     }
+;     may_throw(2);
+;   }
+; }
 
-eh.resume:                                        ; preds = %catch.dispatch.4
-  catchendpad unwind to caller
+%struct.S = type { i8 }
+declare void @"\01??1S@@QEAA at XZ"(%struct.S*)
+
+define void @g() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %x = alloca %struct.S, align 1
+  %y = alloca %struct.S, align 1
+  invoke void @may_throw(i32 -1)
+          to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %0 = catchswitch within none [label %catch] unwind label %ehcleanup5
+
+catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %0 [i8* null, i32 64, i8* null]
+  invoke void @may_throw(i32 0)
+          to label %invoke.cont unwind label %ehcleanup5
+
+invoke.cont:                                      ; preds = %catch
+  invoke void @may_throw(i32 1)
+          to label %invoke.cont2 unwind label %ehcleanup
+
+invoke.cont2:                                     ; preds = %invoke.cont
+  invoke void @"\01??1S@@QEAA at XZ"(%struct.S* nonnull %y)
+          to label %invoke.cont3 unwind label %ehcleanup5
+
+invoke.cont3:                                     ; preds = %invoke.cont2
+  invoke void @may_throw(i32 2)
+          to label %invoke.cont4 unwind label %ehcleanup5
+
+invoke.cont4:                                     ; preds = %invoke.cont3
+  catchret from %1 to label %try.cont
+
+try.cont:                                         ; preds = %invoke.cont4
+  call void @"\01??1S@@QEAA at XZ"(%struct.S* nonnull %x)
+  ret void
+
+ehcleanup:                                        ; preds = %invoke.cont
+  %2 = cleanuppad within %1 []
+  call void @"\01??1S@@QEAA at XZ"(%struct.S* nonnull %y)
+  cleanupret from %2 unwind label %ehcleanup5
+
+ehcleanup5:                                       ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
+  %3 = cleanuppad within none []
+  call void @"\01??1S@@QEAA at XZ"(%struct.S* nonnull %x)
+  cleanupret from %3 unwind to caller
+
+unreachable:                                      ; preds = %entry
+  unreachable
 }
 
-; CHECK-LABEL: _f:
-; CHECK: movl $-1, [[state:[-0-9]+]](%ebp)
-; CHECK: movl $___ehhandler$f, {{.*}}
-;
-; CHECK: movl $0, [[state]](%ebp)
-; CHECK: movl $1, (%esp)
-; CHECK: calll _may_throw
-;
-; CHECK: movl $1, [[state]](%ebp)
-; CHECK: movl $2, (%esp)
-; CHECK: calll _may_throw
-;
-; CHECK: movl $2, [[state]](%ebp)
-; CHECK: movl $3, (%esp)
-; CHECK: calll _may_throw
-;
-; CHECK: movl $3, [[state]](%ebp)
-; CHECK: movl $4, (%esp)
-; CHECK: calll _may_throw
+; X86-LABEL: _g:
+; X86: movl $-1, [[state:[-0-9]+]](%ebp)
+; X86: movl $___ehhandler$g, {{.*}}
+;
+; X86: movl $1, [[state]](%ebp)
+; X86: movl $-1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $0, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $3, [[state]](%ebp)
+; X86: movl $1, (%esp)
+; X86: calll _may_throw
+;
+; X86: movl $2, [[state]](%ebp)
+; X86: movl $2, (%esp)
+; X86: calll _may_throw
+
+; X64-LABEL: g:
+; X64-LABEL: $ip2state$g:
+; X64-NEXT:   .long .Lfunc_begin1 at IMGREL
+; X64-NEXT:   .long -1
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long 1
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long -1
+; X64-NEXT:   .long "?catch${{.*}}@?0?g at 4HA"@IMGREL
+; X64-NEXT:   .long 2
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long 3
+; X64-NEXT:   .long .Ltmp{{.*}}@IMGREL+1
+; X64-NEXT:   .long 2
+
 
-; CHECK: .safeseh ___ehhandler$f
+; X86: .safeseh ___ehhandler$f
+; X86: .safeseh ___ehhandler$g

Modified: llvm/trunk/test/CodeGen/X86/win32-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-eh.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-eh.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-eh.ll Fri Dec 11 23:38:55 2015
@@ -19,12 +19,10 @@ entry:
 cont:
   ret void
 lpad:
-  %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
-      to label %catch unwind label %endpad
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchret %p to label %cont
-endpad:
-  catchendpad unwind to caller
+  %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+  catchret from %p to label %cont
 }
 
 ; CHECK-LABEL: _use_except_handler3:
@@ -45,7 +43,7 @@ endpad:
 ; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], %fs:0
 ; CHECK: retl
-; CHECK: LBB1_2: # %lpad{{$}}
+; CHECK: LBB1_2: # %catch{{$}}
 
 ; CHECK: .section .xdata,"dr"
 ; CHECK-LABEL: L__ehtable$use_except_handler3:
@@ -60,12 +58,10 @@ entry:
 cont:
   ret void
 lpad:
-  %p = catchpad [i8* bitcast (i32 ()* @catchall_filt to i8*)]
-      to label %catch unwind label %endpad
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchret %p to label %cont
-endpad:
-  catchendpad unwind to caller
+  %p = catchpad within %cs [i8* bitcast (i32 ()* @catchall_filt to i8*)]
+  catchret from %p to label %cont
 }
 
 ; CHECK-LABEL: _use_except_handler4:
@@ -86,7 +82,7 @@ endpad:
 ; CHECK: movl -28(%ebp), %[[next:[^ ,]*]]
 ; CHECK: movl %[[next]], %fs:0
 ; CHECK: retl
-; CHECK: LBB2_2: # %lpad{{$}}
+; CHECK: LBB2_2: # %catch{{$}}
 
 ; CHECK: .section .xdata,"dr"
 ; CHECK-LABEL: L__ehtable$use_except_handler4:
@@ -105,14 +101,10 @@ cont:
   ret void
 
 catchall:
-  %p = catchpad [i8* null, i32 64, i8* null]
-      to label %catch unwind label %endcatch
-
+  %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchret %p to label %cont
-
-endcatch:
-  catchendpad unwind to caller
+  %p = catchpad within %cs [i8* null, i32 64, i8* null]
+  catchret from %p to label %cont
 }
 
 ; CHECK-LABEL: _use_CxxFrameHandler3:

Modified: llvm/trunk/test/CodeGen/X86/win32-seh-catchpad-realign.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-seh-catchpad-realign.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-seh-catchpad-realign.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-seh-catchpad-realign.ll Fri Dec 11 23:38:55 2015
@@ -15,17 +15,14 @@ entry:
           to label %__try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %pad = catchpad [i8* bitcast (i32 ()* @"\01?filt$0 at 0@realigned_try@@" to i8*)]
-          to label %__except.ret unwind label %catchendblock
+  %cs1 = catchswitch within none [label %__except.ret] unwind to caller
 
 __except.ret:                                     ; preds = %catch.dispatch
-  catchret %pad to label %__try.cont
+  %pad = catchpad within %cs1 [i8* bitcast (i32 ()* @"\01?filt$0 at 0@realigned_try@@" to i8*)]
+  catchret from %pad to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except.ret
   ret void
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
 }
 
 ; Function Attrs: nounwind argmemonly
@@ -69,7 +66,7 @@ declare i32 @_except_handler3(...)
 ; CHECK: popl    %ebp
 ; CHECK: retl
 ;
-; CHECK: LBB0_1:                                 # %catch.dispatch
+; CHECK: LBB0_1:                                 # %__except.ret
 ; Restore ESP
 ; CHECK: movl    -24(%ebp), %esp
 ; Recompute ESI by subtracting 60 from the end of the registration node.

Modified: llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll Fri Dec 11 23:38:55 2015
@@ -11,10 +11,11 @@ entry:
           to label %invoke.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+  %cs1 = catchswitch within none [label %__except.ret] unwind to caller
 
 __except.ret:                                     ; preds = %catch.dispatch
-  catchret %0 to label %__except
+  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
+  catchret from %0 to label %__except
 
 __except:                                         ; preds = %__except.ret
   call void @f(i32 2)
@@ -24,9 +25,6 @@ __try.cont:
   call void @f(i32 3)
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
-
 invoke.cont:                                      ; preds = %entry
   br label %__try.cont
 }
@@ -77,81 +75,69 @@ entry:
           to label %__try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+  %cs1 = catchswitch within none [label %__except.ret] unwind label %catch.dispatch.11
 
 __except.ret:                                     ; preds = %catch.dispatch
-  catchret %0 to label %__try.cont
+  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %0 to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except.ret
   invoke void @crash() #3
           to label %__try.cont.9 unwind label %catch.dispatch.5
 
 catch.dispatch.5:                                 ; preds = %__try.cont
-  %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
+  %cs2 = catchswitch within none [label %__except.ret.7] unwind label %catch.dispatch.11
 
 __except.ret.7:                                   ; preds = %catch.dispatch.5
-  catchret %1 to label %__try.cont.9
+  %1 = catchpad within %cs2 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %1 to label %__try.cont.9
 
 __try.cont.9:                                     ; preds = %__try.cont, %__except.ret.7
   invoke void @crash() #3
           to label %__try.cont.15 unwind label %catch.dispatch.11
 
 catch.dispatch.11:                                ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
-  %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
+  %cs3 = catchswitch within none [label %__except.ret.13] unwind label %catch.dispatch.17
 
 __except.ret.13:                                  ; preds = %catch.dispatch.11
-  catchret %2 to label %__try.cont.15
+  %2 = catchpad within %cs3 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %2 to label %__try.cont.15
 
 __try.cont.15:                                    ; preds = %__try.cont.9, %__except.ret.13
   invoke void @crash() #3
           to label %__try.cont.35 unwind label %catch.dispatch.17
 
 catch.dispatch.17:                                ; preds = %catchendblock.12, %__try.cont.15
-  %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
+  %cs4 = catchswitch within none [label %__except.ret.19] unwind to caller
 
 __except.ret.19:                                  ; preds = %catch.dispatch.17
-  catchret %3 to label %__except.20
+  %3 = catchpad within %cs4 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %3 to label %__except.20
 
 __except.20:                                      ; preds = %__except.ret.19
   invoke void @crash() #3
           to label %__try.cont.27 unwind label %catch.dispatch.23
 
 catch.dispatch.23:                                ; preds = %__except.20
-  %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
+  %cs5 = catchswitch within none [label %__except.ret.25] unwind to caller
 
 __except.ret.25:                                  ; preds = %catch.dispatch.23
-  catchret %4 to label %__try.cont.27
+  %4 = catchpad within %cs5 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %4 to label %__try.cont.27
 
 __try.cont.27:                                    ; preds = %__except.20, %__except.ret.25
   invoke void @crash() #3
           to label %__try.cont.35 unwind label %catch.dispatch.30
 
 catch.dispatch.30:                                ; preds = %__try.cont.27
-  %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
+  %cs6 = catchswitch within none [label %__except.ret.32] unwind to caller
 
 __except.ret.32:                                  ; preds = %catch.dispatch.30
-  catchret %5 to label %__try.cont.35
+  %5 = catchpad within %cs6 [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)]
+  catchret from %5 to label %__try.cont.35
 
 __try.cont.35:                                    ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
   ret void
-
-catchendblock.31:                                 ; preds = %catch.dispatch.30
-  catchendpad unwind to caller
-
-catchendblock.24:                                 ; preds = %catch.dispatch.23
-  catchendpad unwind to caller
-
-catchendblock.18:                                 ; preds = %catch.dispatch.17
-  catchendpad unwind to caller
-
-catchendblock.12:                                 ; preds = %catch.dispatch.11
-  catchendpad unwind label %catch.dispatch.17
-
-catchendblock.6:                                  ; preds = %catch.dispatch.5
-  catchendpad unwind label %catch.dispatch.11
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %catch.dispatch.11
 }
 
 ; This table is equivalent to the one produced by MSVC, even if it isn't in
@@ -162,19 +148,19 @@ catchendblock:
 ; CHECK:         .long   -1
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
-; CHECK:         .long   -1
+; CHECK:         .long   0
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
-; CHECK:         .long   -1
+; CHECK:         .long   1
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
-; CHECK:         .long   2
+; CHECK:         .long   1
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
-; CHECK:         .long   3
+; CHECK:         .long   -1
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
-; CHECK:         .long   3
+; CHECK:         .long   -1
 ; CHECK:         .long   _nested_exceptions_filter_catchall
 ; CHECK:         .long   LBB
 
@@ -203,21 +189,19 @@ entry:
           to label %__except unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+  %cs1 = catchswitch within none [label %__except.ret] unwind to caller
 
 __except.ret:                                     ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
   call void @f(i32 2)
-  catchret %0 to label %__except
+  catchret from %0 to label %__except
 
 __except:
   ret void
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: _code_in_catchpad:
-; CHECK: # %catch.dispatch
+; CHECK: # %__except.ret
 ; CHECK-NEXT:         movl    -24(%ebp), %esp
 ; CHECK-NEXT:         addl    $12, %ebp
 ; CHECK-NEXT:         movl    $-1, -16(%ebp)

Removed: llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll?rev=255421&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll (removed)
@@ -1,89 +0,0 @@
-; RUN: llc < %s | FileCheck %s
-
-target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
-target triple = "i686-pc-windows-msvc"
-
-define void @nested_finally() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
-entry:
-  invoke void @f(i32 1) #3
-          to label %invoke.cont unwind label %ehcleanup
-
-invoke.cont:                                      ; preds = %entry
-  invoke void @f(i32 2) #3
-          to label %invoke.cont.1 unwind label %ehcleanup.3
-
-invoke.cont.1:                                    ; preds = %invoke.cont
-  call void @f(i32 3) #3
-  ret void
-
-ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
-  invoke void @f(i32 2) #3
-          to label %invoke.cont.2 unwind label %ehcleanup.end
-
-invoke.cont.2:                                    ; preds = %ehcleanup
-  cleanupret %0 unwind label %ehcleanup.3
-
-ehcleanup.end:                                    ; preds = %ehcleanup
-  cleanupendpad %0 unwind label %ehcleanup.3
-
-ehcleanup.3:                                      ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
-  %1 = cleanuppad []
-  invoke void @f(i32 3) #3
-          to label %invoke.cont.4 unwind label %ehcleanup.end.5
-
-invoke.cont.4:                                    ; preds = %ehcleanup.3
-  cleanupret %1 unwind to caller
-
-ehcleanup.end.5:                                  ; preds = %ehcleanup.3
-  cleanupendpad %1 unwind to caller
-}
-
-declare void @f(i32) #0
-
-declare i32 @_except_handler3(...)
-
-attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { noinline nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #2 = { nounwind readnone }
-attributes #3 = { noinline }
-
-; CHECK: _nested_finally:
-; CHECK: movl $-1, -[[state:[0-9]+]](%ebp)
-; CHECK: movl {{.*}}, %fs:0
-; CHECK: movl $1, -[[state]](%ebp)
-; CHECK: movl $1, (%esp)
-; CHECK: calll _f
-; CHECK: movl $0, -[[state]](%ebp)
-; CHECK: movl $2, (%esp)
-; CHECK: calll _f
-; CHECK: movl $-1, -[[state]](%ebp)
-; CHECK: movl $3, (%esp)
-; CHECK: calll _f
-; CHECK: retl
-
-; CHECK: LBB0_[[inner:[0-9]+]]: # %ehcleanup
-; CHECK: pushl %ebp
-; CHECK: addl $12, %ebp
-; CHECK: movl $0, -[[state]](%ebp)
-; CHECK: movl $2, (%esp)
-; CHECK: calll _f
-; CHECK: popl %ebp
-; CHECK: retl
-
-; CHECK: LBB0_[[outer:[0-9]+]]: # %ehcleanup.3
-; CHECK: pushl %ebp
-; CHECK: addl $12, %ebp
-; CHECK: movl $-1, -[[state]](%ebp)
-; CHECK: movl $3, (%esp)
-; CHECK: calll _f
-; CHECK: popl %ebp
-; CHECK: retl
-
-; CHECK: L__ehtable$nested_finally:
-; CHECK:        .long   -1
-; CHECK:        .long   0
-; CHECK:        .long   LBB0_[[outer]]
-; CHECK:        .long   0
-; CHECK:        .long   0
-; CHECK:        .long   LBB0_[[inner]]

Copied: llvm/trunk/test/CodeGen/X86/win32-seh-nested-finally.ll (from r255418, llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-seh-nested-finally.ll?p2=llvm/trunk/test/CodeGen/X86/win32-seh-nested-finally.ll&p1=llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll&r1=255418&r2=255422&rev=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-seh-cleanupendpad.ll (original)
+++ llvm/trunk/test/CodeGen/X86/win32-seh-nested-finally.ll Fri Dec 11 23:38:55 2015
@@ -17,26 +17,17 @@ invoke.cont.1:
   ret void
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   invoke void @f(i32 2) #3
-          to label %invoke.cont.2 unwind label %ehcleanup.end
+          to label %invoke.cont.2 unwind label %ehcleanup.3
 
 invoke.cont.2:                                    ; preds = %ehcleanup
-  cleanupret %0 unwind label %ehcleanup.3
-
-ehcleanup.end:                                    ; preds = %ehcleanup
-  cleanupendpad %0 unwind label %ehcleanup.3
+  cleanupret from %0 unwind label %ehcleanup.3
 
 ehcleanup.3:                                      ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
-  %1 = cleanuppad []
-  invoke void @f(i32 3) #3
-          to label %invoke.cont.4 unwind label %ehcleanup.end.5
-
-invoke.cont.4:                                    ; preds = %ehcleanup.3
-  cleanupret %1 unwind to caller
-
-ehcleanup.end.5:                                  ; preds = %ehcleanup.3
-  cleanupendpad %1 unwind to caller
+  %1 = cleanuppad within none []
+  call void @f(i32 3) #3
+  cleanupret from %1 unwind to caller
 }
 
 declare void @f(i32) #0

Copied: llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll (from r255418, llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll?p2=llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll&p1=llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll&r1=255418&r2=255422&rev=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-coreclr.ll (original)
+++ llvm/trunk/test/CodeGen/X86/wineh-coreclr.ll Fri Dec 11 23:38:55 2015
@@ -13,7 +13,7 @@ declare i8 addrspace(1)* @llvm.eh.except
 ;       f(2);
 ;     } catch (type1) {
 ;       f(3);
-;     } catch (type2) [
+;     } catch (type2) {
 ;       f(4);
 ;       try {
 ;         f(5);
@@ -50,10 +50,10 @@ inner_try:
   invoke void @f(i32 2)
     to label %finally.clone unwind label %catch1.pad
 catch1.pad:
-; CHECK: .seh_proc [[L_catch1:[^ ]+]]
-  %catch1 = catchpad [i32 1]
-    to label %catch1.body unwind label %catch2.pad
+  %cs1 = catchswitch within none [label %catch1.body, label %catch2.body] unwind label %finally.pad
 catch1.body:
+  %catch1 = catchpad within %cs1 [i32 1]
+; CHECK: .seh_proc [[L_catch1:[^ ]+]]
 ; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
 ;                        ^ all funclets use the same frame size
 ; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -71,14 +71,12 @@ catch1.body:
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f3:.+]]:
   invoke void @f(i32 3)
-    to label %catch1.ret unwind label %catch.end
+    to label %catch1.ret unwind label %finally.pad
 catch1.ret:
-  catchret %catch1 to label %finally.clone
-catch2.pad:
-; CHECK: .seh_proc [[L_catch2:[^ ]+]]
-  %catch2 = catchpad [i32 2]
-    to label %catch2.body unwind label %catch.end
+  catchret from %catch1 to label %finally.clone
 catch2.body:
+  %catch2 = catchpad within %cs1 [i32 2]
+; CHECK: .seh_proc [[L_catch2:[^ ]+]]
 ; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
 ;                        ^ all funclets use the same frame size
 ; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -96,7 +94,7 @@ catch2.body:
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f4:.+]]:
   invoke void @f(i32 4)
-    to label %try_in_catch unwind label %catch.end
+    to label %try_in_catch unwind label %finally.pad
 try_in_catch:
 ; CHECK: # %try_in_catch
 ; CHECK: [[L_before_f5:.+]]:
@@ -107,7 +105,7 @@ try_in_catch:
     to label %catch2.ret unwind label %fault.pad
 fault.pad:
 ; CHECK: .seh_proc [[L_fault:[^ ]+]]
-  %fault = cleanuppad [i32 undef]
+  %fault = cleanuppad within none [i32 undef]
 ; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
 ;                        ^ all funclets use the same frame size
 ; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -120,21 +118,17 @@ fault.pad:
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f6:.+]]:
   invoke void @f(i32 6)
-    to label %fault.ret unwind label %fault.end
+    to label %fault.ret unwind label %finally.pad
 fault.ret:
-  cleanupret %fault unwind label %catch.end
-fault.end:
-  cleanupendpad %fault unwind label %catch.end
+  cleanupret from %fault unwind label %finally.pad
 catch2.ret:
-  catchret %catch2 to label %finally.clone
-catch.end:
-  catchendpad unwind label %finally.pad
+  catchret from %catch2 to label %finally.clone
 finally.clone:
   call void @f(i32 7)
   br label %tail
 finally.pad:
 ; CHECK: .seh_proc [[L_finally:[^ ]+]]
-  %finally = cleanuppad []
+  %finally = cleanuppad within none []
 ; CHECK: .seh_stackalloc [[FuncletFrameSize:[0-9]+]]
 ;                        ^ all funclets use the same frame size
 ; CHECK: movq [[PSPSymOffset]](%rcx), %rcx
@@ -142,136 +136,132 @@ finally.pad:
 ; CHECK: movq %rcx, [[PSPSymOffset]](%rsp)
 ; CHECK: leaq [[FPOffset]](%rcx), %rbp
 ; CHECK: .seh_endprologue
-; CHECK: [[L_before_f7:.+]]:
 ; CHECK-NEXT: movl $7, %ecx
 ; CHECK-NEXT: callq f
-; CHECK-NEXT: [[L_after_f7:.+]]:
-  invoke void @f(i32 7)
-    to label %finally.ret unwind label %finally.end
-finally.ret:
-  cleanupret %finally unwind to caller
-finally.end:
-   cleanupendpad %finally unwind to caller
+  call void @f(i32 7)
+  cleanupret from %finally unwind to caller
 tail:
   call void @f(i32 8)
   ret void
 ; CHECK: [[L_end:.*func_end.*]]:
 }
 
+; FIXME: Verify that the new clauses are correct and re-enable these checks.
+
 ; Now check for EH table in xdata (following standard xdata)
-; CHECK-LABEL: .section .xdata
+; CHECKX-LABEL: .section .xdata
 ; standard xdata comes here
-; CHECK:      .long 4{{$}}
+; CHECKX:      .long 4{{$}}
 ;                   ^ number of funclets
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
 ;                   ^ offset from L_begin to start of 1st funclet
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
 ;                   ^ offset from L_begin to start of 2nd funclet
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
 ;                   ^ offset from L_begin to start of 3rd funclet
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset from L_begin to start of 4th funclet
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
 ;                   ^ offset from L_begin to end of last funclet
-; CHECK-NEXT: .long 7
+; CHECKX-NEXT: .long 7
 ;                   ^ number of EH clauses
 ; Clause 1: call f(2) is guarded by catch1
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch1]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch1]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 1
+; CHECKX-NEXT: .long 1
 ;                   ^ type token of catch (from catchpad)
 ; Clause 2: call f(2) is also guarded by catch2
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ flags (0 => catch handler)
-; CHECK-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f2]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_catch2]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_catch2]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 2
+; CHECKX-NEXT: .long 2
 ;                   ^ type token of catch (from catchpad)
 ; Clause 3: calls f(1) and f(2) are guarded by finally
-; CHECK-NEXT: .long 2
+; CHECKX-NEXT: .long 2
 ;                   ^ flags (2 => finally handler)
-; CHECK-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f1]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f2]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ type token slot (null for finally)
 ; Clause 4: call f(3) is guarded by finally
 ;           This is a "duplicate" because the protected range (f(3))
 ;           is in funclet catch1 but the finally's immediate parent
 ;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
+; CHECKX-NEXT: .long 10
 ;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f3]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f3]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ type token slot (null for finally)
 ; Clause 5: call f(5) is guarded by fault
-; CHECK-NEXT: .long 4
+; CHECKX-NEXT: .long 4
 ;                   ^ flags (4 => fault handler)
-; CHECK-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f5]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_fault]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_fault]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ type token slot (null for fault)
 ; Clause 6: calls f(4) and f(5) are guarded by finally
 ;           This is a "duplicate" because the protected range (f(4)-f(5))
 ;           is in funclet catch2 but the finally's immediate parent
 ;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
+; CHECKX-NEXT: .long 10
 ;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f4]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f5]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ type token slot (null for finally)
 ; Clause 7: call f(6) is guarded by finally
 ;           This is a "duplicate" because the protected range (f(3))
 ;           is in funclet catch1 but the finally's immediate parent
 ;           is the main function, not that funclet.
-; CHECK-NEXT: .long 10
+; CHECKX-NEXT: .long 10
 ;                   ^ flags (2 => finally handler | 8 => duplicate)
-; CHECK-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_before_f6]]-[[L_begin]])+1
 ;                   ^ offset of start of clause
-; CHECK-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
+; CHECKX-NEXT: .long ([[L_after_f6]]-[[L_begin]])+1
 ;                   ^ offset of end of clause
-; CHECK-NEXT: .long [[L_finally]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_finally]]-[[L_begin]]
 ;                   ^ offset of start of handler
-; CHECK-NEXT: .long [[L_end]]-[[L_begin]]
+; CHECKX-NEXT: .long [[L_end]]-[[L_begin]]
 ;                   ^ offset of end of handler
-; CHECK-NEXT: .long 0
+; CHECKX-NEXT: .long 0
 ;                   ^ type token slot (null for finally)

Copied: llvm/trunk/test/CodeGen/X86/wineh-exceptionpointer.ll (from r255418, llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/wineh-exceptionpointer.ll?p2=llvm/trunk/test/CodeGen/X86/wineh-exceptionpointer.ll&p1=llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll&r1=255418&r2=255422&rev=255422&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-exceptionpointer.ll (original)
+++ llvm/trunk/test/CodeGen/X86/wineh-exceptionpointer.ll Fri Dec 11 23:38:55 2015
@@ -11,18 +11,16 @@ entry:
   invoke void @f()
     to label %exit unwind label %catch.pad
 catch.pad:
-; CHECK: {{^[^: ]+}}: # %catch.pad
-  %catch = catchpad [i32 5]
-    to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
 catch.body:
-  %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
-  %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
+  ; CHECK: {{^[^: ]+}}: # %catch.body
   ; CHECK: movq %rdx, %rcx
   ; CHECK-NEXT: callq g
+  %catch = catchpad within %cs1 [i32 5]
+  %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
+  %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
   call void @g(i32 addrspace(1)* %cast_exn)
-  catchret %catch to label %exit
-catch.end:
-  catchendpad unwind to caller
+  catchret from %catch to label %exit
 exit:
   ret void
 }

Modified: llvm/trunk/test/Feature/exception.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/exception.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Feature/exception.ll (original)
+++ llvm/trunk/test/Feature/exception.ll Fri Dec 11 23:38:55 2015
@@ -31,8 +31,8 @@ entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
 pad:
-  %cp = cleanuppad [i7 4]
-  cleanupret %cp unwind to caller
+  %cp = cleanuppad within none [i7 4]
+  cleanupret from %cp unwind to caller
 exit:
   ret void
 }
@@ -43,9 +43,9 @@ entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
 cleanup:
-  cleanupret %cp unwind label %pad
+  cleanupret from %cp unwind label %pad
 pad:
-  %cp = cleanuppad []
+  %cp = cleanuppad within none []
   br label %cleanup
 exit:
   ret void
@@ -57,9 +57,9 @@ entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
 cleanup:
-  cleanupret %0 unwind label %pad
+  cleanupret from %0 unwind label %pad
 pad:
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   br label %cleanup
 exit:
   ret void
@@ -70,12 +70,10 @@ entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
 pad:
-  %cp = catchpad [i7 4]
-          to label %catch unwind label %endpad
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchret %cp to label %exit
-endpad:
-  catchendpad unwind to caller
+  %cp = catchpad within %cs1 [i7 4]
+  catchret from %cp to label %exit
 exit:
   ret void
 }
@@ -85,13 +83,13 @@ define void @catchret1() personality i32
 entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
-catch:
-  catchret %cp to label %exit
+catchret:
+  catchret from %cp to label %exit
 pad:
-  %cp = catchpad []
-          to label %catch unwind label %endpad
-endpad:
-  catchendpad unwind to caller
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+catch:
+  %cp = catchpad within %cs1 [i7 4]
+  br label %catchret
 exit:
   ret void
 }
@@ -101,13 +99,13 @@ define void @catchret2() personality i32
 entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %pad
-catch:
-  catchret %0 to label %exit
+catchret:
+  catchret from %0 to label %exit
 pad:
-  %0 = catchpad []
-          to label %catch unwind label %endpad
-endpad:
-  catchendpad unwind to caller
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+catch:
+  %0 = catchpad within %cs1 [i7 4]
+  br label %catchret
 exit:
   ret void
 }
@@ -117,9 +115,10 @@ entry:
   invoke void @_Z3quxv() optsize
           to label %exit unwind label %bb2
 bb2:
-  catchpad [i7 4] to label %exit unwind label %bb3
-bb3:
-  catchendpad unwind to caller
+  %cs1 = catchswitch within none [label %catch] unwind to caller
+catch:
+  catchpad within %cs1 [i7 4]
+  br label %exit
 exit:
   ret i8 0
 }
@@ -132,7 +131,7 @@ try.cont:
   invoke void @_Z3quxv() optsize
           to label %try.cont unwind label %bb
 bb:
-  terminatepad [i7 4] unwind label %bb
+  terminatepad within none [i7 4] unwind label %bb
 }
 
 define void @terminatepad1() personality i32 (...)* @__gxx_personality_v0 {
@@ -143,7 +142,7 @@ try.cont:
   invoke void @_Z3quxv() optsize
           to label %try.cont unwind label %bb
 bb:
-  terminatepad [i7 4] unwind to caller
+  terminatepad within none [i7 4] unwind to caller
 }
 
 define void @cleanuppad() personality i32 (...)* @__gxx_personality_v0 {
@@ -154,78 +153,6 @@ try.cont:
   invoke void @_Z3quxv() optsize
           to label %try.cont unwind label %bb
 bb:
-  cleanuppad [i7 4]
-  ret void
-}
-
-define void @catchendpad0() personality i32 (...)* @__gxx_personality_v0 {
-entry:
-  br label %try.cont
-
-try.cont:
-  invoke void @_Z3quxv() optsize
-          to label %try.cont unwind label %bb
-bb:
-  catchendpad unwind label %bb
-}
-
-define void @catchendpad1() personality i32 (...)* @__gxx_personality_v0 {
-entry:
-  br label %try.cont
-
-try.cont:
-  invoke void @_Z3quxv() optsize
-          to label %try.cont unwind label %bb
-bb:
-  catchendpad unwind to caller
-}
-
-define void @cleanupendpad0() personality i32 (...)* @__gxx_personality_v0 {
-entry:
-  invoke void @_Z3quxv() optsize
-          to label %exit unwind label %pad
-pad:
-  %cp = cleanuppad [i7 4]
-  invoke void @_Z3quxv() optsize
-          to label %stop unwind label %endpad
-stop:
-  unreachable
-endpad:
-  cleanupendpad %cp unwind label %pad
-exit:
-  ret void
-}
-
-; forward ref by name
-define void @cleanupendpad1() personality i32 (...)* @__gxx_personality_v0 {
-entry:
-  invoke void @_Z3quxv() optsize
-          to label %exit unwind label %pad
-endpad:
-  cleanupendpad %cp unwind to caller
-pad:
-  %cp = cleanuppad []
-  invoke void @_Z3quxv() optsize
-          to label %stop unwind label %endpad
-stop:
-  unreachable
-exit:
-  ret void
-}
-
-; forward ref by ID
-define void @cleanupendpad2() personality i32 (...)* @__gxx_personality_v0 {
-entry:
-  invoke void @_Z3quxv() optsize
-          to label %exit unwind label %pad
-endpad:
-  cleanupendpad %0 unwind label %pad
-pad:
-  %0 = cleanuppad []
-  invoke void @_Z3quxv() optsize
-          to label %stop unwind label %endpad
-stop:
-  unreachable
-exit:
+  cleanuppad within none [i7 4]
   ret void
 }

Modified: llvm/trunk/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll (original)
+++ llvm/trunk/test/Transforms/CodeGenPrepare/catchpad-phi-cast.ll Fri Dec 11 23:38:55 2015
@@ -18,9 +18,6 @@ declare void @llvm.dbg.value(metadata, i
 
 ; CHECK-LABEL: @test(
 define void @test(i32* %addr) personality i32 (...)* @__CxxFrameHandler3 {
-; CHECK: entry:
-; CHECK-NEXT: %x = getelementptr i32, i32* %addr, i32 1
-; CHECK-NEXT: %p1 = bitcast i32* %x to i8*
 entry:
   %x = getelementptr i32, i32* %addr, i32 1
   %p1 = bitcast i32* %x to i8*
@@ -29,7 +26,6 @@ entry:
 
 ; CHECK: invoke.cont:
 ; CHECK-NEXT: %y = getelementptr i32, i32* %addr, i32 2
-; CHECK-NEXT: %p2 = bitcast i32* %y to i8*
 invoke.cont:
   %y = getelementptr i32, i32* %addr, i32 2
   %p2 = bitcast i32* %y to i8*
@@ -40,23 +36,31 @@ done:
   ret void
 
 catch1:
-  %cp1 = catchpad [] to label %catch.dispatch unwind label %catchend1
+  %cs1 = catchswitch within none [label %handler1] unwind to caller
+
+handler1:
+  %cp1 = catchpad within %cs1 []
+  br label %catch.shared
+; CHECK: handler1:
+; CHECK-NEXT: catchpad within %cs1
+; CHECK: %[[p1:[0-9]+]] = bitcast i32* %x to i8*
 
 catch2:
-  %cp2 = catchpad [] to label %catch.dispatch unwind label %catchend2
+  %cs2 = catchswitch within none [label %handler2] unwind to caller
 
-; CHECK: catch.dispatch:
-; CHECK-NEXT: %p = phi i8* [ %p1, %catch1 ], [ %p2, %catch2 ]
-catch.dispatch:
-  %p = phi i8* [ %p1, %catch1 ], [ %p2, %catch2 ]
+handler2:
+  %cp2 = catchpad within %cs2 []
+  br label %catch.shared
+; CHECK: handler2:
+; CHECK: catchpad within %cs2
+; CHECK: %[[p2:[0-9]+]] = bitcast i32* %y to i8*
+
+; CHECK: catch.shared:
+; CHECK-NEXT: %p = phi i8* [ %[[p1]], %handler1 ], [ %[[p2]], %handler2 ]
+catch.shared:
+  %p = phi i8* [ %p1, %handler1 ], [ %p2, %handler2 ]
   call void @g(i8* %p)
   unreachable
-
-catchend1:
-  catchendpad unwind to caller
-
-catchend2:
-  catchendpad unwind to caller
 }
 
 ; CodeGenPrepare will want to hoist these llvm.dbg.value calls to the phi, but
@@ -75,24 +79,22 @@ ret:
 
 catch.dispatch:
   %p = phi i8* [%a, %entry], [%b, %next]
-  %cp1 = catchpad [] to label %catch unwind label %catchend
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:
+  %cp1 = catchpad within %cs1 []
   tail call void @llvm.dbg.value(metadata i8* %p, i64 0, metadata !11, metadata !13), !dbg !14
-  invoke void @g(i8* %p) to label %catchret unwind label %catchend
-catchret:
-  catchret %cp1 to label %ret
+  call void @g(i8* %p)
+  catchret from %cp1 to label %ret
 
 ; CHECK: catch.dispatch:
 ; CHECK-NEXT: phi i8
-; CHECK-NEXT: catchpad
+; CHECK-NEXT: catchswitch
 ; CHECK-NOT: llvm.dbg.value
 
 ; CHECK: catch:
+; CHECK-NEXT: catchpad
 ; CHECK-NEXT: call void @llvm.dbg.value
-
-catchend:
-  catchendpad unwind to caller
 }
 
 !llvm.dbg.cu = !{!0}

Modified: llvm/trunk/test/Transforms/GVN/funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/funclet.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GVN/funclet.ll (original)
+++ llvm/trunk/test/Transforms/GVN/funclet.ll Fri Dec 11 23:38:55 2015
@@ -17,12 +17,12 @@ entry:
           to label %unreachable unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %catchpad = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %catchpad = catchpad within %cs1 [i8* null, i32 64, i8* null]
   store i8 5, i8* %b
-  catchret %catchpad to label %try.cont
+  catchret from %catchpad to label %try.cont
 
 try.cont:                                         ; preds = %catch
   %load_b = load i8, i8* %b
@@ -30,9 +30,6 @@ try.cont:
   %add = add i8 %load_b, %load_c
   ret i8 %add
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
-
 unreachable:                                      ; preds = %entry
   unreachable
 }

Modified: llvm/trunk/test/Transforms/GVN/pre-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pre-load.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GVN/pre-load.ll (original)
+++ llvm/trunk/test/Transforms/GVN/pre-load.ll Fri Dec 11 23:38:55 2015
@@ -399,7 +399,7 @@ define void @test12(i32* %p) personality
 ; CHECK-LABEL: @test12(
 block1:
   invoke void @f()
-          to label %block2 unwind label %catch
+          to label %block2 unwind label %catch.dispatch
 
 block2:
   invoke void @f()
@@ -408,31 +408,25 @@ block2:
 block3:
   ret void
 
-catch:
-  %c = catchpad []
-    to label %catch.dispatch unwind label %catchend
-
 catch.dispatch:
-  catchret %c to label %block2
+  %cs1 = catchswitch within none [label %catch] unwind label %cleanup2
 
-; CHECK: catchend:
-; CHECK-NOT: load
-; CHECK-NEXT: catchendpad
-catchend:
-  catchendpad unwind label %cleanup2
+catch:
+  %c = catchpad within %cs1 []
+  catchret from %c to label %block2
 
 cleanup:
-  %c1 = cleanuppad []
+  %c1 = cleanuppad within none []
   store i32 0, i32* %p
-  cleanupret %c1 unwind label %cleanup2
+  cleanupret from %c1 unwind label %cleanup2
 
 ; CHECK: cleanup2:
 ; CHECK-NOT: phi
-; CHECK-NEXT: %c2 = cleanuppad []
+; CHECK-NEXT: %c2 = cleanuppad within none []
 ; CHECK-NEXT: %NOTPRE = load i32, i32* %p
 cleanup2:
-  %c2 = cleanuppad []
+  %c2 = cleanuppad within none []
   %NOTPRE = load i32, i32* %p
   call void @g(i32 %NOTPRE)
-  cleanupret %c2 unwind to caller
+  cleanupret from %c2 unwind to caller
 }

Modified: llvm/trunk/test/Transforms/Inline/PR25155.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/PR25155.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/PR25155.ll (original)
+++ llvm/trunk/test/Transforms/Inline/PR25155.ll Fri Dec 11 23:38:55 2015
@@ -8,21 +8,23 @@ entry:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %entry
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   invoke void @dtor()
-          to label %invoke.cont.1 unwind label %catchendblock
+          to label %invoke.cont.1 unwind label %ehcleanup
 
 invoke.cont.1:                                    ; preds = %catch
-  catchret %0 to label %try.cont
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %entry, %invoke.cont.1
   ret void
 
-catchendblock:                                    ; preds = %catch, %catch.dispatch
-  catchendpad unwind to caller
+ehcleanup:
+  %cp2 = cleanuppad within none []
+  call void @g()
+  cleanupret from %cp2 unwind to caller
 }
 
 ; CHECK-LABEL:  define void @f(
@@ -31,10 +33,7 @@ catchendblock:
 ; CHECK:                 to label %dtor.exit unwind label %terminate.i
 
 ; CHECK:       terminate.i:
-; CHECK-NEXT:    terminatepad [void ()* @terminate] unwind label %catchendblock
-
-; CHECK:       catchendblock:
-; CHECK-NEXT:    catchendpad unwind to caller
+; CHECK-NEXT:    terminatepad within %0 [void ()* @terminate] unwind label %ehcleanup
 
 declare i32 @__CxxFrameHandler3(...)
 
@@ -47,7 +46,7 @@ invoke.cont:
   ret void
 
 terminate:                                        ; preds = %entry
-  terminatepad [void ()* @terminate] unwind to caller
+  terminatepad within none [void ()* @terminate] unwind to caller
 }
 
 declare void @g()

Modified: llvm/trunk/test/Transforms/InstCombine/token.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/token.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/token.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/token.ll Fri Dec 11 23:38:55 2015
@@ -9,14 +9,14 @@ bb:
   unreachable
 
 unreachable:
-  %cl = cleanuppad []
-  cleanupret %cl unwind to caller
+  %cl = cleanuppad within none []
+  cleanupret from %cl unwind to caller
 }
 
 ; CHECK-LABEL: define void @test1(
 ; CHECK: unreachable:
-; CHECK:   %cl = cleanuppad []
-; CHECK:   cleanupret %cl unwind to caller
+; CHECK:   %cl = cleanuppad within none []
+; CHECK:   cleanupret from %cl unwind to caller
 
 define void @test2(i8 %A, i8 %B) personality i32 (...)* @__CxxFrameHandler3 {
 bb:
@@ -33,19 +33,15 @@ cont:
 
 catch:
   %phi = phi i32 [ %X, %bb ], [ %Y, %cont ]
-  %cl = catchpad []
-   to label %doit
-   unwind label %endpad
+  %cs = catchswitch within none [label %doit] unwind to caller
 
 doit:
+  %cl = catchpad within %cs []
   call void @g(i32 %phi)
   unreachable
 
 unreachable:
   unreachable
-
-endpad:
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: define void @test2(
@@ -73,19 +69,15 @@ cont2:
 
 catch:
   %phi = phi i32 [ %X, %bb ], [ %Y, %cont ], [ %Y, %cont2 ]
-  %cl = catchpad []
-   to label %doit
-   unwind label %endpad
+  %cs = catchswitch within none [label %doit] unwind to caller
 
 doit:
+  %cl = catchpad within %cs []
   call void @g(i32 %phi)
   unreachable
 
 unreachable:
   unreachable
-
-endpad:
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: define void @test3(

Modified: llvm/trunk/test/Transforms/LoopStrengthReduce/funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/funclet.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopStrengthReduce/funclet.ll (original)
+++ llvm/trunk/test/Transforms/LoopStrengthReduce/funclet.ll Fri Dec 11 23:38:55 2015
@@ -20,19 +20,17 @@ throw:
 
 pad:                                              ; preds = %throw
   %phi2 = phi i8* [ %tmp96, %throw ]
-  terminatepad [] unwind label %blah
+  terminatepad within none [] unwind label %blah
 
 blah:
-  catchpad [] to label %unreachable unwind label %blah3
+  %cs = catchswitch within none [label %unreachable] unwind label %blah2
 
 unreachable:
+  catchpad within %cs []
   unreachable
 
-blah3:
-  catchendpad unwind label %blah2
-
 blah2:
-  %cleanuppadi4.i.i.i = cleanuppad []
+  %cleanuppadi4.i.i.i = cleanuppad within none []
   br label %loop_body
 
 loop_body:                                        ; preds = %iter, %pad
@@ -45,11 +43,11 @@ iter:
   br i1 undef, label %unwind_out, label %loop_body
 
 unwind_out:                                       ; preds = %iter, %loop_body
-  cleanupret %cleanuppadi4.i.i.i unwind to caller
+  cleanupret from %cleanuppadi4.i.i.i unwind to caller
 }
 
 ; CHECK-LABEL: define void @f(
-; CHECK: cleanuppad []
+; CHECK: cleanuppad within none []
 ; CHECK-NEXT: ptrtoint i8* %phi2 to i32
 
 define void @g() personality i32 (...)* @_except_handler3 {
@@ -63,20 +61,18 @@ throw:
 
 pad:
   %phi2 = phi i8* [ %tmp96, %throw ]
-  catchpad [] to label %unreachable unwind label %blah
+  %cs = catchswitch within none [label %unreachable, label %blah] unwind to caller
 
 unreachable:
+  catchpad within %cs []
   unreachable
 
 blah:
-  %catchpad = catchpad [] to label %loop_body unwind label %blah3
-
-
-blah3:
-  catchendpad unwind to caller ;label %blah2
+  %catchpad = catchpad within %cs []
+  br label %loop_body
 
 unwind_out:
-  catchret %catchpad to label %leave
+  catchret from %catchpad to label %leave
 
 leave:
   ret void
@@ -93,10 +89,7 @@ iter:
 
 ; CHECK-LABEL: define void @g(
 ; CHECK: blah:
-; CHECK-NEXT: catchpad []
-; CHECK-NEXT: to label %loop_body.preheader
-
-; CHECK: loop_body.preheader:
+; CHECK-NEXT: catchpad within %cs []
 ; CHECK-NEXT: ptrtoint i8* %phi2 to i32
 
 
@@ -110,29 +103,25 @@ throw:
           to label %throw unwind label %pad
 
 pad:
-  catchpad [] to label %unreachable unwind label %blug
+  %cs = catchswitch within none [label %unreachable, label %blug] unwind to caller
 
 unreachable:
+  catchpad within %cs []
   unreachable
 
 blug:
   %phi2 = phi i8* [ %tmp96, %pad ]
-  %catchpad = catchpad [] to label %blah2 unwind label %blah3
-
-blah2:
+  %catchpad = catchpad within %cs []
   br label %loop_body
 
-blah3:
-  catchendpad unwind to caller ;label %blah2
-
 unwind_out:
-  catchret %catchpad to label %leave
+  catchret from %catchpad to label %leave
 
 leave:
   ret void
 
 loop_body:                                        ; preds = %iter, %pad
-  %tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blah2 ]
+  %tmp99 = phi i8* [ %tmp101, %iter ], [ %phi2, %blug ]
   %tmp100 = icmp eq i8* %tmp99, undef
   br i1 %tmp100, label %unwind_out, label %iter
 
@@ -143,10 +132,7 @@ iter:
 
 ; CHECK-LABEL: define void @h(
 ; CHECK: blug:
-; CHECK: catchpad []
-; CHECK-NEXT: to label %blah2
-
-; CHECK: blah2:
+; CHECK: catchpad within %cs []
 ; CHECK-NEXT: ptrtoint i8* %phi2 to i32
 
 define void @i() personality i32 (...)* @_except_handler3 {
@@ -160,16 +146,14 @@ throw:
 
 catchpad:                                              ; preds = %throw
   %phi2 = phi i8* [ %tmp96, %throw ]
-  catchpad [] to label %cp_body unwind label %catchendpad
+  %cs = catchswitch within none [label %cp_body] unwind label %cleanuppad
 
 cp_body:
+  catchpad within %cs []
   br label %loop_head
 
-catchendpad:
-  catchendpad unwind label %cleanuppad
-
 cleanuppad:
-  cleanuppad []
+  cleanuppad within none []
   br label %loop_head
 
 loop_head:
@@ -205,39 +189,31 @@ for.inc:
   br label %for.cond
 
 catch.dispatch:                                   ; preds = %for.cond
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch unwind label %catchendblock
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %catch.dispatch.2
+  %cs = catchswitch within none [label %catch] unwind label %catch.dispatch.2
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %0 to label %try.cont
+  %0 = catchpad within %cs [i8* null, i32 64, i8* null]
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %catch
   invoke void @external(i32* %c)
           to label %try.cont.7 unwind label %catch.dispatch.2
 
 catch.dispatch.2:                                 ; preds = %try.cont, %catchendblock
-  %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catchendblock ]
-  %1 = catchpad [i8* null, i32 64, i8* null]
-          to label %catch.4 unwind label %catchendblock.3
+  %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ]
+  %cs2 = catchswitch within none [label %catch.4] unwind to caller
 
 catch.4:                                          ; preds = %catch.dispatch.2
+  catchpad within %cs2 [i8* null, i32 64, i8* null]
   unreachable
 
 try.cont.7:                                       ; preds = %try.cont
   ret void
-
-catchendblock.3:                                  ; preds = %catch.dispatch.2
-  catchendpad unwind to caller
 }
 
 ; CHECK-LABEL: define void @test1(
 ; CHECK: for.cond:
 ; CHECK:   %d.0 = phi i32* [ %b, %entry ], [ %incdec.ptr, %for.inc ]
 
-; CHECK: catchendpad unwind label %catch.dispatch.2
-
 ; CHECK: catch.dispatch.2:
-; CHECK: %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catchendblock ]
+; CHECK: %e.0 = phi i32* [ %c, %try.cont ], [ %b, %catch.dispatch ]

Modified: llvm/trunk/test/Transforms/LoopStrengthReduce/pr25541.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/pr25541.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopStrengthReduce/pr25541.ll (original)
+++ llvm/trunk/test/Transforms/LoopStrengthReduce/pr25541.ll Fri Dec 11 23:38:55 2015
@@ -12,10 +12,10 @@ for.cond.i:
           to label %for.inc.i unwind label %catch.dispatch.i
 
 catch.dispatch.i:                                 ; preds = %for.cond.i
-  %0 = catchpad [i8* null, i32 64, i8* null]
-          to label %for.cond.1.preheader.i unwind label %catchendblock.i
+  %cs = catchswitch within none [label %for.cond.1.preheader.i] unwind to caller
 
 for.cond.1.preheader.i:                           ; preds = %catch.dispatch.i
+  %0 = catchpad within %cs [i8* null, i32 64, i8* null]
   %cmp.i = icmp eq i32* %_First.addr.0.i, null
   br label %for.cond.1.i
 
@@ -23,18 +23,15 @@ for.cond.1.i:
   br i1 %cmp.i, label %for.end.i, label %for.body.i
 
 for.body.i:                                       ; preds = %for.cond.1.i
-  invoke void @g()
-          to label %for.cond.1.i unwind label %catchendblock.i
-
-catchendblock.i:                                  ; preds = %for.body.i, %catch.dispatch.i
-  catchendpad unwind to caller
+  call void @g()
+  br label %for.cond.1.i
 
 for.inc.i:                                        ; preds = %for.cond.i
   %incdec.ptr.i = getelementptr inbounds i32, i32* %_First.addr.0.i, i64 1
   br label %for.cond.i
 
 for.end.i:                                        ; preds = %for.cond.1.i
-  catchret %0 to label %leave
+  catchret from %0 to label %leave
 
 leave:                                            ; preds = %for.end.i
   ret void

Added: llvm/trunk/test/Transforms/LoopUnswitch/cleanuppad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/cleanuppad.ll?rev=255422&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnswitch/cleanuppad.ll (added)
+++ llvm/trunk/test/Transforms/LoopUnswitch/cleanuppad.ll Fri Dec 11 23:38:55 2015
@@ -0,0 +1,44 @@
+; RUN: opt -S -loop-unswitch < %s | FileCheck %s
+target triple = "x86_64-pc-win32"
+
+define void @f(i32 %doit, i1 %x, i1 %y) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %tobool = icmp eq i32 %doit, 0
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  br i1 %x, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  br i1 %tobool, label %if.then, label %for.inc
+
+if.then:                                          ; preds = %for.body
+  br i1 %y, label %for.inc, label %delete.notnull
+
+delete.notnull:                                   ; preds = %if.then
+  invoke void @g()
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %delete.notnull
+  br label %for.inc
+
+lpad:                                             ; preds = %delete.notnull
+  %cp = cleanuppad within none []
+  cleanupret from %cp unwind to caller
+
+for.inc:                                          ; preds = %invoke.cont, %if.then, %for.body
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+
+declare void @g()
+
+declare i32 @__CxxFrameHandler3(...)
+
+; CHECK-LABEL: define void @f(
+; CHECK: cleanuppad within none []
+; CHECK-NOT: cleanuppad
+
+attributes #0 = { ssp uwtable }

Modified: llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/empty-cleanuppad.ll Fri Dec 11 23:38:55 2015
@@ -31,12 +31,12 @@ invoke.cont:
   ret void
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
-  cleanupret %0 unwind label %ehcleanup.1
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %ehcleanup.1
 
 ehcleanup.1:                                      ; preds = %ehcleanup
-  %1 = cleanuppad []
-  cleanupret %1 unwind to caller
+  %1 = cleanuppad within none []
+  cleanupret from %1 unwind to caller
 }
 
 
@@ -60,15 +60,14 @@ ehcleanup.1:
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK: ehcleanup:
-; CHECK:   cleanuppad
+; CHECK:   cleanuppad within none
 ; CHECK:   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %b)
-; CHECK:   cleanupret %0 unwind label %catch.dispatch
+; CHECK:   cleanupret from %0 unwind label %catch.dispatch
 ; CHECK: catch.dispatch:
-; CHECK:   catchpad
+; CHECK:   catchswitch within none [label %catch] unwind to caller
 ; CHECK: catch:
+; CHECK:   catchpad
 ; CHECK:   catchret
-; CHECK: catchendblock:                                    ; preds = %catch.dispatch
-; CHECK:   catchendpad unwind to caller
 ; CHECK-NOT: cleanuppad
 ; CHECK: }
 ;
@@ -81,15 +80,16 @@ invoke.cont:
   br label %try.cont
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
+  %0 = cleanuppad within none []
   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %b)
-  cleanupret %0 unwind label %catch.dispatch
+  cleanupret from %0 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %ehcleanup
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %1 to label %catchret.dest
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %catchret.dest
 
 catchret.dest:                                    ; preds = %catch
   br label %try.cont
@@ -97,12 +97,9 @@ catchret.dest:
 try.cont:                                         ; preds = %catchret.dest, %invoke.cont
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %ehcleanup.1
-
-ehcleanup.1:                                      ; preds = %catchendblock
-  %2 = cleanuppad []
-  cleanupret %2 unwind to caller
+ehcleanup.1:
+  %2 = cleanuppad within none []
+  cleanupret from %2 unwind to caller
 }
 
 
@@ -121,21 +118,19 @@ ehcleanup.1:
 ; In this case the inner cleanup pad should be eliminated and the invoke of g()
 ; should unwind directly to the catchpad.
 ;
-; CHECK: define void @f3()
+; CHECK-LABEL: define void @f3()
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK:           to label %try.cont unwind label %catch.dispatch
 ; CHECK: catch.dispatch:
-; CHECK:   catchpad [i8* null, i32 64, i8* null]
-; CHECK-NEXT: to label %catch unwind label %catchendblock
+; CHECK-NEXT: catchswitch within none [label %catch] unwind label %ehcleanup.1
 ; CHECK: catch:
+; CHECK:   catchpad within %cs1 [i8* null, i32 64, i8* null]
 ; CHECK:   catchret
-; CHECK: catchendblock:
-; CHECK:   catchendpad unwind label %ehcleanup.1
 ; CHECK: ehcleanup.1:
 ; CHECK:   cleanuppad
 ; CHECK:   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
-; CHECK:   cleanupret %1 unwind to caller
+; CHECK:   cleanupret from %cp3 unwind to caller
 ; CHECK: }
 ;
 define void @f3() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
@@ -147,14 +142,15 @@ invoke.cont:
   br label %try.cont
 
 ehcleanup:                                        ; preds = %entry
-  %0 = cleanuppad []
-  cleanupret %0 unwind label %catch.dispatch
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %ehcleanup
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup.1
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %1 to label %catchret.dest
+  %cp2 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %cp2 to label %catchret.dest
 
 catchret.dest:                                    ; preds = %catch
   br label %try.cont
@@ -162,13 +158,10 @@ catchret.dest:
 try.cont:                                         ; preds = %catchret.dest, %invoke.cont
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %ehcleanup.1
-
-ehcleanup.1:                                      ; preds = %catchendblock
-  %2 = cleanuppad []
+ehcleanup.1:
+  %cp3 = cleanuppad within none []
   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
-  cleanupret %2 unwind to caller
+  cleanupret from %cp3 unwind to caller
 }
 
 
@@ -184,11 +177,10 @@ ehcleanup.1:
 ; }
 ;
 ; In this case, the cleanuppad should be eliminated, the invoke outside of the
-; call block should be converted to a call and the catchendpad should unwind
-; to the caller (that is, that is, exception handling continues with the parent
-; frame of the caller).)
+; catch block should be converted to a call (that is, that is, exception
+; handling continues with the parent frame of the caller).)
 ;
-; CHECK: define void @f4()
+; CHECK-LABEL: define void @f4()
 ; CHECK: entry:
 ; CHECK:   call void @g
 ; Note: The cleanuppad simplification will insert an unconditional branch here
@@ -196,11 +188,10 @@ ehcleanup.1:
 ; CHECK:   invoke void @g()
 ; CHECK:           to label %try.cont unwind label %catch.dispatch
 ; CHECK: catch.dispatch:
-; CHECK:   catchpad
+; CHECK:   catchswitch within none [label %catch] unwind to caller
 ; CHECK: catch:
+; CHECK:   catchpad
 ; CHECK:   catchret
-; CHECK: catchendblock:
-; CHECK:   catchendpad unwind to caller
 ; CHECK-NOT: cleanuppad
 ; CHECK: }
 ;
@@ -214,43 +205,41 @@ invoke.cont:
           to label %try.cont unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %invoke.cont
-  %0 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind label %ehcleanup
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %0 to label %try.cont
+  %0 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %0 to label %try.cont
 
 try.cont:                                         ; preds = %catch, %invoke.cont
   ret void
 
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind label %ehcleanup
-
-ehcleanup:                                        ; preds = %catchendblock, %entry
-  %1 = cleanuppad []
-  cleanupret %1 unwind to caller
+ehcleanup:
+  %cp2 = cleanuppad within none []
+  cleanupret from %cp2 unwind to caller
 }
 
 ; This tests the case where a terminatepad unwinds to a cleanuppad.
 ; I'm not sure how this case would arise, but it seems to be syntactically
 ; legal so I'm testing it.
 ;
-; CHECK: define void @f5()
+; CHECK-LABEL: define void @f5()
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK:           to label %try.cont unwind label %terminate
 ; CHECK: terminate:
-; CHECK:   terminatepad [i7 4] unwind to caller
+; CHECK:   terminatepad within none [i7 4] unwind to caller
 ; CHECK-NOT: cleanuppad
 ; CHECK: try.cont:
 ; CHECK:   invoke void @g()
 ; CHECK:           to label %try.cont.1 unwind label %terminate.1
 ; CHECK: terminate.1:
-; CHECK:   terminatepad [i7 4] unwind label %ehcleanup.2
+; CHECK:   terminatepad within none [i7 4] unwind label %ehcleanup.2
 ; CHECK-NOT: ehcleanup.1:
 ; CHECK: ehcleanup.2:
 ; CHECK:   [[TMP:\%.+]] = cleanuppad
 ; CHECK:   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
-; CHECK:   cleanupret [[TMP]] unwind to caller
+; CHECK:   cleanupret from [[TMP]] unwind to caller
 ; CHECK: }
 define void @f5() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
 entry:
@@ -259,27 +248,27 @@ entry:
           to label %try.cont unwind label %terminate
 
 terminate:                                        ; preds = %entry
-  terminatepad [i7 4] unwind label %ehcleanup
+  terminatepad within none [i7 4] unwind label %ehcleanup
 
 ehcleanup:                                        ; preds = %terminate
-  %0 = cleanuppad []
-  cleanupret %0 unwind to caller
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind to caller
 
 try.cont:                                         ; preds = %entry
   invoke void @g()
           to label %try.cont.1 unwind label %terminate.1
 
 terminate.1:                                      ; preds = %try.cont
-  terminatepad [i7 4] unwind label %ehcleanup.1
+  terminatepad within none [i7 4] unwind label %ehcleanup.1
 
 ehcleanup.1:                                      ; preds = %terminate.1
-  %1 = cleanuppad []
-  cleanupret %1 unwind label %ehcleanup.2
+  %1 = cleanuppad within none []
+  cleanupret from %1 unwind label %ehcleanup.2
 
 ehcleanup.2:                                      ; preds = %ehcleanup.1
-  %2 = cleanuppad []
+  %2 = cleanuppad within none []
   call void @"\01??1S2@@QEAA at XZ"(%struct.S2* %a)
-  cleanupret %2 unwind to caller
+  cleanupret from %2 unwind to caller
 
 try.cont.1:                                       ; preds = %try.cont
   ret void
@@ -304,7 +293,7 @@ try.cont.1:
 ; In this case, the cleanup pad should be eliminated and the PHI node in the
 ; cleanup pad should be sunk into the catch dispatch block.
 ;
-; CHECK: define i32 @f6()
+; CHECK-LABEL: define i32 @f6()
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK: invoke.cont:
@@ -325,17 +314,15 @@ invoke.cont:
 
 ehcleanup:                                        ; preds = %invoke.cont, %entry
   %state.0 = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
-  %0 = cleanuppad []
-  cleanupret %0 unwind label %catch.dispatch
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %ehcleanup
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %1 to label %return
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %return
 
 return:                                           ; preds = %invoke.cont, %catch
   %retval.0 = phi i32 [ %state.0, %catch ], [ 0, %invoke.cont ]
@@ -363,7 +350,7 @@ return:
 ; In this case, the cleanup pad should be eliminated and the PHI node in the
 ; cleanup pad should be merged with the PHI node in the catch dispatch block.
 ;
-; CHECK: define i32 @f7()
+; CHECK-LABEL: define i32 @f7()
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK: invoke.cont:
@@ -390,18 +377,16 @@ invoke.cont.1:
 
 ehcleanup:                                        ; preds = %invoke.cont.1, %invoke.cont
   %state.0 = phi i32 [ 3, %invoke.cont.1 ], [ 2, %invoke.cont ]
-  %0 = cleanuppad []
-  cleanupret %0 unwind label %catch.dispatch
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %ehcleanup, %entry
   %state.1 = phi i32 [ %state.0, %ehcleanup ], [ 1, %entry ]
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
-  catchret %1 to label %return
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
+  catchret from %1 to label %return
 
 return:                                           ; preds = %invoke.cont.1, %catch
   %retval.0 = phi i32 [ %state.1, %catch ], [ 0, %invoke.cont.1 ]
@@ -435,7 +420,7 @@ return:
 ; should have an incoming value entry for path from 'foo' that references the
 ; PHI node itself.
 ;
-; CHECK: define void @f8()
+; CHECK-LABEL: define void @f8()
 ; CHECK: entry:
 ; CHECK:   invoke void @g()
 ; CHECK: invoke.cont:
@@ -456,18 +441,16 @@ invoke.cont:
 
 ehcleanup:                                        ; preds = %invoke.cont, %entry
   %x = phi i32 [ 2, %invoke.cont ], [ 1, %entry ]
-  %0 = cleanuppad []
-  cleanupret %0 unwind label %catch.dispatch
+  %0 = cleanuppad within none []
+  cleanupret from %0 unwind label %catch.dispatch
 
 catch.dispatch:                                   ; preds = %ehcleanup, %catch.cont
-  %1 = catchpad [i8* null, i32 u0x40, i8* null] to label %catch unwind label %catchendblock
+  %cs1 = catchswitch within none [label %catch] unwind to caller
 
 catch:                                            ; preds = %catch.dispatch
+  %1 = catchpad within %cs1 [i8* null, i32 u0x40, i8* null]
   call void @use_x(i32 %x)
-  catchret %1 to label %catch.cont
-
-catchendblock:                                    ; preds = %catch.dispatch
-  catchendpad unwind to caller
+  catchret from %1 to label %catch.cont
 
 catch.cont:                                       ; preds = %catch
   invoke void @g()

Modified: llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll (original)
+++ llvm/trunk/test/Transforms/SimplifyCFG/wineh-unreachable.ll Fri Dec 11 23:38:55 2015
@@ -12,7 +12,7 @@ entry:
 exit:
   ret void
 unreachable.unwind:
-  cleanuppad []
+  cleanuppad within none []
   unreachable  
 }
 
@@ -22,24 +22,21 @@ entry:
   invoke void @f()
     to label %exit unwind label %catch.pad
 catch.pad:
-  ; CHECK: catchpad []
-  ; CHECK-NEXT: to label %catch.body unwind label %catch.end
-  %catch = catchpad []
-    to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind label %unreachable.unwind
+  ; CHECK: catch.pad:
+  ; CHECK-NEXT: catchswitch within none [label %catch.body] unwind to caller
 catch.body:
   ; CHECK:      catch.body:
+  ; CHECK-NEXT:   catchpad within %cs1
   ; CHECK-NEXT:   call void @f()
   ; CHECK-NEXT:   unreachable
+  %catch = catchpad within %cs1 []
   call void @f()
-  catchret %catch to label %unreachable
-catch.end:
-  ; CHECK: catch.end:
-  ; CHECK-NEXT: catchendpad unwind to caller
-  catchendpad unwind label %unreachable.unwind
+  catchret from %catch to label %unreachable
 exit:
   ret void
 unreachable.unwind:
-  cleanuppad []
+  cleanuppad within none []
   unreachable
 unreachable:
   unreachable
@@ -51,24 +48,20 @@ entry:
   invoke void @f()
     to label %exit unwind label %cleanup.pad
 cleanup.pad:
-  ; CHECK: %cleanup = cleanuppad []
+  ; CHECK: %cleanup = cleanuppad within none []
   ; CHECK-NEXT: call void @f()
   ; CHECK-NEXT: unreachable
-  %cleanup = cleanuppad []
+  %cleanup = cleanuppad within none []
   invoke void @f()
-    to label %cleanup.ret unwind label %cleanup.end
+    to label %cleanup.ret unwind label %unreachable.unwind
 cleanup.ret:
   ; This cleanupret should be rewritten to unreachable,
   ; and merged into the pred block.
-  cleanupret %cleanup unwind label %unreachable.unwind
-cleanup.end:
-  ; This cleanupendpad should be rewritten to unreachable,
-  ; causing the invoke to be rewritten to a call.
-  cleanupendpad %cleanup unwind label %unreachable.unwind
+  cleanupret from %cleanup unwind label %unreachable.unwind
 exit:
   ret void
 unreachable.unwind:
-  cleanuppad []
+  cleanuppad within none []
   unreachable
 }
 
@@ -78,12 +71,12 @@ entry:
   invoke void @f()
     to label %exit unwind label %terminate.pad
 terminate.pad:
-  ; CHECK: terminatepad [] unwind to caller
-  terminatepad [] unwind label %unreachable.unwind
+  ; CHECK: terminatepad within none [] unwind to caller
+  terminatepad within none [] unwind label %unreachable.unwind
 exit:
   ret void
 unreachable.unwind:
-  cleanuppad []
+  cleanuppad within none []
   unreachable
 }
 
@@ -94,14 +87,11 @@ entry:
           to label %exit unwind label %catch.pad
 
 catch.pad:
-  %catch = catchpad []
-          to label %catch.body unwind label %catch.end
+  %cs1 = catchswitch within none [label %catch.body] unwind to caller
 
 catch.body:
-  catchret %catch to label %exit
-
-catch.end:
-  catchendpad unwind to caller
+  %catch = catchpad within %cs1 []
+  catchret from %catch to label %exit
 
 exit:
   unreachable

Added: llvm/trunk/test/Transforms/Sink/catchswitch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Sink/catchswitch.ll?rev=255422&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Sink/catchswitch.ll (added)
+++ llvm/trunk/test/Transforms/Sink/catchswitch.ll Fri Dec 11 23:38:55 2015
@@ -0,0 +1,37 @@
+; RUN: opt -sink -S < %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+define void @h() personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  %call = call i32 @g(i32 1) readnone
+  invoke void @_CxxThrowException(i8* null, i8* null) noreturn
+          to label %unreachable unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %cs = catchswitch within none [label %catch] unwind to caller
+
+catch:                                            ; preds = %catch.dispatch
+  %cp = catchpad within %cs [i8* null, i32 64, i8* null]
+  catchret from %cp to label %try.cont
+
+try.cont:                                         ; preds = %catch
+  call void @k(i32 %call)
+  ret void
+
+unreachable:                                      ; preds = %entry
+  unreachable
+}
+
+declare x86_stdcallcc void @_CxxThrowException(i8*, i8*)
+
+declare i32 @__CxxFrameHandler3(...)
+
+declare i32 @g(i32) readnone
+
+declare void @k(i32)
+
+; CHECK-LABEL: define void @h(
+; CHECK: call i32 @g(i32 1)
+; CHECK-NEXT: invoke void @_CxxThrowException(

Added: llvm/trunk/test/Verifier/invalid-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/invalid-eh.ll?rev=255422&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/invalid-eh.ll (added)
+++ llvm/trunk/test/Verifier/invalid-eh.ll Fri Dec 11 23:38:55 2015
@@ -0,0 +1,38 @@
+; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s
+; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s
+; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s
+; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s
+
+;T1: define void @f() {
+;T1:   entry:
+;T1:     catchret from undef to label %next
+;T1:     ; CHECK1: CatchReturnInst needs to be provided a CatchPad
+;T1:   next:
+;T1:     unreachable
+;T1: }
+
+;T2: define void @f() {
+;T2:   entry:
+;T2:     %x = cleanuppad within none []
+;T2:     ; catchret's first operand's operator must be catchpad
+;T2:     catchret from %x to label %entry
+;T2:     ; CHECK2: CatchReturnInst needs to be provided a CatchPad
+;T2: }
+
+;T3: define void @f() {
+;T3:   entry:
+;T3:     cleanupret from undef unwind label %next
+;T3:     ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad
+;T3:   next:
+;T3:     unreachable
+;T3: }
+
+;T4: define void @f() {
+;T4:   entry:
+;T4:     %cs = catchswitch within none [label %next] unwind to caller
+;T4:   next:
+;T4:     %x = catchpad within %cs []
+;T4:     ; cleanupret first operand's operator must be cleanuppad
+;T4:     cleanupret from %x unwind to caller
+;T4:     ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad
+;T4: }

Modified: llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp?rev=255422&r1=255421&r2=255422&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp (original)
+++ llvm/trunk/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp Fri Dec 11 23:38:55 2015
@@ -259,8 +259,6 @@ static const char *GetCodeName(unsigned
       STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
       STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
       STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
-      STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPENDPAD)
-      STRINGIFY_CODE(FUNC_CODE, INST_CATCHENDPAD)
       STRINGIFY_CODE(FUNC_CODE, INST_TERMINATEPAD)
       STRINGIFY_CODE(FUNC_CODE, INST_PHI)
       STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)




More information about the llvm-commits mailing list