[WinEH] Use operand bundles to describe call sites
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Dec 2015 21:27:27 +0000 (21:27 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Dec 2015 21:27:27 +0000 (21:27 +0000)
SimplifyCFG allows tail merging with code which terminates in
unreachable which, in turn, makes it possible for an invoke to end up in
a funclet which it was not originally part of.

Using operand bundles on invokes allows us to determine whether or not
an invoke was part of a funclet in the source program.

Furthermore, it allows us to unambiguously answer questions about the
legality of inlining into call sites which the personality may have
trouble with.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255674 91177308-0d34-0410-b5e6-96231b3b80d8

36 files changed:
docs/LangRef.rst
include/llvm/IR/InstrTypes.h
include/llvm/IR/LLVMContext.h
include/llvm/Transforms/Utils/Local.h
lib/CodeGen/WinEHPrepare.cpp
lib/IR/LLVMContext.cpp
lib/IR/Verifier.cpp
lib/Transforms/Utils/InlineFunction.cpp
lib/Transforms/Utils/Local.cpp
test/CodeGen/WinEH/wineh-cloning.ll
test/CodeGen/WinEH/wineh-demotion.ll
test/CodeGen/WinEH/wineh-no-demotion.ll
test/CodeGen/X86/catchpad-weight.ll
test/CodeGen/X86/cleanuppad-inalloca.ll
test/CodeGen/X86/cleanuppad-large-codemodel.ll
test/CodeGen/X86/cleanuppad-realign.ll
test/CodeGen/X86/funclet-layout.ll
test/CodeGen/X86/seh-catch-all-win32.ll
test/CodeGen/X86/seh-catch-all.ll
test/CodeGen/X86/seh-catchpad.ll
test/CodeGen/X86/seh-except-finally.ll
test/CodeGen/X86/seh-finally.ll
test/CodeGen/X86/seh-safe-div-win32.ll
test/CodeGen/X86/seh-safe-div.ll
test/CodeGen/X86/seh-stack-realign.ll
test/CodeGen/X86/win-catchpad-csrs.ll
test/CodeGen/X86/win-catchpad-nested-cxx.ll
test/CodeGen/X86/win-catchpad-nested.ll
test/CodeGen/X86/win-catchpad.ll
test/CodeGen/X86/win-cleanuppad.ll
test/CodeGen/X86/win-funclet-cfi.ll
test/CodeGen/X86/win32-eh-states.ll
test/CodeGen/X86/win32-seh-catchpad.ll
test/CodeGen/X86/win32-seh-nested-finally.ll
test/CodeGen/X86/wineh-coreclr.ll
test/CodeGen/X86/wineh-exceptionpointer.ll

index 21ca7ec0c30203985ea4945dcf304b5c210edb91..72c0a319dfab26546f6ea55987aa405bbb772ccd 100644 (file)
@@ -1571,6 +1571,15 @@ caller's deoptimization state to the callee's deoptimization state is
 semantically equivalent to composing the caller's deoptimization
 continuation after the callee's deoptimization continuation.
 
+Funclet Operand Bundles
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Funclet operand bundles are characterized by the ``"funclet"``
+operand bundle tag.  These operand bundles indicate that a call site
+is within a particular funclet.  There can be at most one
+``"funclet"`` operand bundle attached to a call site and it must have
+exactly one bundle operand.
+
 .. _moduleasm:
 
 Module-Level Inline Assembly
index 242da30c52f4e823853368d28c9ff4a55ceb5906..5091bb4078336a659a8edab75b5078611f8e759a 100644 (file)
@@ -1219,6 +1219,11 @@ struct OperandBundleUse {
     return getTagID() == LLVMContext::OB_deopt;
   }
 
+  /// \brief Return true if this is a "funclet" operand bundle.
+  bool isFuncletOperandBundle() const {
+    return getTagID() == LLVMContext::OB_funclet;
+  }
+
 private:
   /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
   StringMapEntry<uint32_t> *Tag;
@@ -1237,6 +1242,8 @@ template <typename InputTy> class OperandBundleDefT {
 public:
   explicit OperandBundleDefT(std::string Tag, std::vector<InputTy> Inputs)
       : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {}
+  explicit OperandBundleDefT(std::string Tag, ArrayRef<InputTy> Inputs)
+      : Tag(std::move(Tag)), Inputs(Inputs) {}
 
   explicit OperandBundleDefT(const OperandBundleUse &OBU) {
     Tag = OBU.getTagName();
@@ -1430,11 +1437,12 @@ public:
   /// may write to the heap.
   bool hasClobberingOperandBundles() const {
     for (auto &BOI : bundle_op_infos()) {
-      if (BOI.Tag->second == LLVMContext::OB_deopt)
+      if (BOI.Tag->second == LLVMContext::OB_deopt ||
+          BOI.Tag->second == LLVMContext::OB_funclet)
         continue;
 
-      // This instruction has an operand bundle that is not a "deopt" operand
-      // bundle.  Assume the worst.
+      // This instruction has an operand bundle that is not known to us.
+      // Assume the worst.
       return true;
     }
 
index c00e3052b592d4033bcc61642b20e6cd773a5c68..e99f02420efc78e6067a8b4115cca17047524540 100644 (file)
@@ -72,7 +72,8 @@ public:
   /// Additionally, this scheme allows LLVM to efficiently check for specific
   /// operand bundle tags without comparing strings.
   enum {
-    OB_deopt = 0,  // "deopt"
+    OB_deopt = 0,   // "deopt"
+    OB_funclet = 1, // "funclet"
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
index 81598a3dddf28b48d00f8d1477a4d9c7bb68bca4..81b376f0c212cf445ecd2d8ade9d28a8db4ca3a8 100644 (file)
@@ -288,6 +288,10 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress,
 bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                                 DIBuilder &Builder, bool Deref, int Offset = 0);
 
+/// \brief Insert an unreachable instruction before the specified
+/// instruction, making it and the rest of the code in the block dead.
+void changeToUnreachable(Instruction *I, bool UseLLVMTrap);
+
 /// Replace 'BB's terminator with one that does not have an unwind successor
 /// block.  Rewrites `invoke` to `call`, etc.  Updates any PHIs in unwind
 /// successor.
index 3ac5d8a7c3bae50797ea6440469dcd3df30969a5..3b076b65e693da4430a967abf353dd228673e1af 100644 (file)
@@ -74,7 +74,7 @@ private:
 
   void demotePHIsOnFunclets(Function &F);
   void cloneCommonBlocks(Function &F);
-  void removeImplausibleTerminators(Function &F);
+  void removeImplausibleInstructions(Function &F);
   void cleanupPreparedFunclets(Function &F);
   void verifyPreparedFunclets(Function &F);
 
@@ -765,19 +765,56 @@ void WinEHPrepare::cloneCommonBlocks(Function &F) {
   }
 }
 
-void WinEHPrepare::removeImplausibleTerminators(Function &F) {
+void WinEHPrepare::removeImplausibleInstructions(Function &F) {
   // Remove implausible terminators and replace them with UnreachableInst.
   for (auto &Funclet : FuncletBlocks) {
     BasicBlock *FuncletPadBB = Funclet.first;
     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
-    Instruction *FuncletPadInst = FuncletPadBB->getFirstNonPHI();
-    auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPadInst);
-    auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPadInst);
+    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+    auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI);
+    auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad);
+    auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad);
 
     for (BasicBlock *BB : BlocksInFunclet) {
+      for (Instruction &I : *BB) {
+        CallSite CS(&I);
+        if (!CS)
+          continue;
+
+        Value *FuncletBundleOperand = nullptr;
+        if (auto BU = CS.getOperandBundle(LLVMContext::OB_funclet))
+          FuncletBundleOperand = BU->Inputs.front();
+
+        if (FuncletBundleOperand == FuncletPad)
+          continue;
+
+        // Skip call sites which are nounwind intrinsics.
+        auto *CalledFn =
+            dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
+        if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
+          continue;
+
+        // This call site was not part of this funclet, remove it.
+        if (CS.isInvoke()) {
+          // Remove the unwind edge if it was an invoke.
+          removeUnwindEdge(BB);
+          // Get a pointer to the new call.
+          BasicBlock::iterator CallI =
+              std::prev(BB->getTerminator()->getIterator());
+          auto *CI = cast<CallInst>(&*CallI);
+          changeToUnreachable(CI, /*UseLLVMTrap=*/false);
+        } else {
+          changeToUnreachable(&I, /*UseLLVMTrap=*/false);
+        }
+
+        // There are no more instructions in the block (except for unreachable),
+        // we are done.
+        break;
+      }
+
       TerminatorInst *TI = BB->getTerminator();
       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
-      bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
+      bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad;
       // The token consumed by a CatchReturnInst must match the funclet token.
       bool IsUnreachableCatchret = false;
       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
@@ -788,19 +825,14 @@ void WinEHPrepare::removeImplausibleTerminators(Function &F) {
         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
       if (IsUnreachableRet || IsUnreachableCatchret ||
           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);
-
-        new UnreachableInst(BB->getContext(), TI);
-        TI->eraseFromParent();
+        changeToUnreachable(TI, /*UseLLVMTrap=*/false);
       } 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)
+        if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
+          // Invokes within a cleanuppad for the MSVC++ personality never
+          // transfer control to their unwind edge: the personality will
+          // terminate the program.
           removeUnwindEdge(BB);
+        }
       }
     }
   }
@@ -854,7 +886,7 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
     demotePHIsOnFunclets(F);
 
   if (!DisableCleanups) {
-    removeImplausibleTerminators(F);
+    removeImplausibleInstructions(F);
 
     cleanupPreparedFunclets(F);
   }
index af998c861357121ee5732cdcc3395dd714bda180..8848bcb7147770ea141869fedae0b96dcaa14bcd 100644 (file)
@@ -132,6 +132,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
   assert(DeoptEntry->second == LLVMContext::OB_deopt &&
          "deopt operand bundle id drifted!");
   (void)DeoptEntry;
+
+  auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
+  assert(FuncletEntry->second == LLVMContext::OB_funclet &&
+         "funclet operand bundle id drifted!");
+  (void)FuncletEntry;
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
index 234ab29d8ed1e5f4012022c94928b8fe40a84a95..32646cf79996f9ed7178e7e8d039ab841d4a8d03 100644 (file)
@@ -2381,13 +2381,25 @@ void Verifier::VerifyCallSite(CallSite CS) {
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCallSite(ID, CS);
 
-  // Verify that a callsite has at most one "deopt" operand bundle.
-  bool FoundDeoptBundle = false;
+  // Verify that a callsite has at most one "deopt" and one "funclet" operand
+  // bundle.
+  bool FoundDeoptBundle = false, FoundFuncletBundle = false;
   for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) {
-    if (CS.getOperandBundleAt(i).getTagID() == LLVMContext::OB_deopt) {
+    OperandBundleUse BU = CS.getOperandBundleAt(i);
+    uint32_t Tag = BU.getTagID();
+    if (Tag == LLVMContext::OB_deopt) {
       Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I);
       FoundDeoptBundle = true;
     }
+    if (Tag == LLVMContext::OB_funclet) {
+      Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", I);
+      FoundFuncletBundle = true;
+      Assert(BU.Inputs.size() == 1,
+             "Expected exactly one funclet bundle operand", I);
+      Assert(isa<FuncletPadInst>(BU.Inputs.front()),
+             "Funclet bundle operands should correspond to a FuncletPadInst",
+             I);
+    }
   }
 
   visitInstruction(*I);
@@ -3002,6 +3014,8 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
       UnwindDest = CRI->getUnwindDest();
     } else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
       continue;
+    } else if (CallSite(U)) {
+      continue;
     } else {
       Assert(false, "bogus cleanuppad use", &CPI);
     }
index b0d99a8e830a5ce821e5a9412b7affe6c11a7d8e..db2cacd4739ed272fe394f76376eaf7dddb5033a 100644 (file)
@@ -1035,12 +1035,17 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
   // The inliner does not know how to inline through calls with operand bundles
   // in general ...
   if (CS.hasOperandBundles()) {
-    // ... but it knows how to inline through "deopt" operand bundles.
-    bool CanInline =
-        CS.getNumOperandBundles() == 1 &&
-        CS.getOperandBundleAt(0).getTagID() == LLVMContext::OB_deopt;
-    if (!CanInline)
+    for (int i = 0, e = CS.getNumOperandBundles(); i != e; ++i) {
+      uint32_t Tag = CS.getOperandBundleAt(i).getTagID();
+      // ... but it knows how to inline through "deopt" operand bundles ...
+      if (Tag == LLVMContext::OB_deopt)
+        continue;
+      // ... and "funclet" operand bundles.
+      if (Tag == LLVMContext::OB_funclet)
+        continue;
+
       return false;
+    }
   }
 
   // If the call to the callee cannot throw, set the 'nounwind' flag on any
@@ -1088,23 +1093,13 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
   // 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 (CallerPersonality) {
+    EHPersonality Personality = classifyEHPersonality(CallerPersonality);
     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!");
-        }
-      }
+      Optional<OperandBundleUse> ParentFunclet =
+          CS.getOperandBundle(LLVMContext::OB_funclet);
+      if (ParentFunclet)
+        CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
 
       // OK, the inlining site is legal.  What about the target function?
 
@@ -1116,7 +1111,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
             // 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()))
+              if (isa<CatchSwitchInst>(CalledBB.getFirstNonPHI()))
                 return false;
             }
           }
@@ -1195,11 +1190,9 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
       HandleByValArgumentInit(Init.first, Init.second, Caller->getParent(),
                               &*FirstNewBlock, IFI);
 
-    if (CS.hasOperandBundles()) {
-      auto ParentDeopt = CS.getOperandBundleAt(0);
-      assert(ParentDeopt.getTagID() == LLVMContext::OB_deopt &&
-             "Checked on entry!");
-
+    Optional<OperandBundleUse> ParentDeopt =
+        CS.getOperandBundle(LLVMContext::OB_deopt);
+    if (ParentDeopt) {
       SmallVector<OperandBundleDef, 2> OpDefs;
 
       for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
@@ -1225,12 +1218,12 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
           // Prepend the parent's deoptimization continuation to the newly
           // inlined call's deoptimization continuation.
           std::vector<Value *> MergedDeoptArgs;
-          MergedDeoptArgs.reserve(ParentDeopt.Inputs.size() +
+          MergedDeoptArgs.reserve(ParentDeopt->Inputs.size() +
                                   ChildOB.Inputs.size());
 
           MergedDeoptArgs.insert(MergedDeoptArgs.end(),
-                                 ParentDeopt.Inputs.begin(),
-                                 ParentDeopt.Inputs.end());
+                                 ParentDeopt->Inputs.begin(),
+                                 ParentDeopt->Inputs.end());
           MergedDeoptArgs.insert(MergedDeoptArgs.end(), ChildOB.Inputs.begin(),
                                  ChildOB.Inputs.end());
 
@@ -1423,12 +1416,48 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
     }
   }
 
-  // Update the lexical scopes of the new funclets.  Anything that had 'none' as
-  // its parent is now nested inside the callsite's EHPad.
+  // Update the lexical scopes of the new funclets and callsites.
+  // 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) {
+      // Add bundle operands to any top-level call sites.
+      SmallVector<OperandBundleDef, 1> OpBundles;
+      for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;) {
+        Instruction *I = &*BBI++;
+        CallSite CS(I);
+        if (!CS)
+          continue;
+
+        // Skip call sites which are nounwind intrinsics.
+        auto *CalledFn =
+            dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
+        if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
+          continue;
+
+        // Skip call sites which already have a "funclet" bundle.
+        if (CS.getOperandBundle(LLVMContext::OB_funclet))
+          continue;
+
+        CS.getOperandBundlesAsDefs(OpBundles);
+        OpBundles.emplace_back("funclet", CallSiteEHPad);
+
+        Instruction *NewInst;
+        if (CS.isCall())
+          NewInst = CallInst::Create(cast<CallInst>(I), OpBundles, I);
+        else
+          NewInst = InvokeInst::Create(cast<InvokeInst>(I), OpBundles, I);
+        NewInst->setDebugLoc(I->getDebugLoc());
+        NewInst->takeName(I);
+        I->replaceAllUsesWith(NewInst);
+        I->eraseFromParent();
+
+        OpBundles.clear();
+      }
+
       Instruction *I = BB->getFirstNonPHI();
       if (!I->isEHPad())
         continue;
index 24f88179c9036d6e472b74549d3fdc582ccf6cfb..31039816e14a957d3d41ce6dd7cbb0eb5b3202f8 100644 (file)
@@ -1180,9 +1180,7 @@ bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                            Deref, Offset);
 }
 
-/// changeToUnreachable - Insert an unreachable instruction before the specified
-/// instruction, making it and the rest of the code in the block dead.
-static void changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
+void llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
   BasicBlock *BB = I->getParent();
   // Loop over all of the successors, removing BB's entry from any PHI
   // nodes.
index 66a9132980fcbf1f22a47b46d81015f811d35097..c13e0a163641e9c261fa943db8ba12d350e81cc4 100644 (file)
@@ -4,25 +4,26 @@ declare i32 @__CxxFrameHandler3(...)
 declare i32 @__C_specific_handler(...)
 
 declare void @f()
-declare i32 @g()
-declare void @h(i32)
-declare i1 @b()
 
+declare void @llvm.foo(i32) nounwind
+declare void @llvm.bar() nounwind
+declare i32 @llvm.qux() nounwind
+declare i1 @llvm.baz() nounwind
 
 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   ; %x def colors: {entry} subset of use colors; must spill
-  %x = call i32 @g()
+  %x = call i32 @llvm.qux()
   invoke void @f()
     to label %noreturn unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchpad within %cs []
+  %cp = catchpad within %cs []
   br label %noreturn
 noreturn:
   ; %x use colors: {entry, cleanup}
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   unreachable
 }
 ; Need two copies of the call to @h, one under entry and one under catch.
@@ -30,16 +31,16 @@ noreturn:
 ; for the use in entry's copy.
 ; CHECK-LABEL: define void @test1(
 ; CHECK: entry:
-; CHECK:   %x = call i32 @g()
+; CHECK:   %x = call i32 @llvm.qux()
 ; 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 within %cs []
-; CHECK-NEXT: call void @h(i32 %x)
+; CHECK-NEXT: call void @llvm.foo(i32 %x)
 ; CHECK: [[EntryCopy]]:
-; CHECK:   call void @h(i32 %x)
+; CHECK:   call void @llvm.foo(i32 %x)
 
 
 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
@@ -50,7 +51,7 @@ cleanup:
   cleanuppad within none []
   br label %exit
 exit:
-  call void @f()
+  call void @llvm.bar()
   ret void
 }
 ; Need two copies of %exit's call to @f -- the subsequent ret is only
@@ -62,10 +63,10 @@ exit:
 ; CHECK:     to label %[[exit:[^ ]+]] unwind label %cleanup
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: ret void
 
 
@@ -85,7 +86,7 @@ cleanup:
   cleanuppad within none []
   br label %shared
 shared:
-  call void @f()
+  call void @llvm.bar()
   br label %exit
 exit:
   ret void
@@ -98,11 +99,11 @@ exit:
 ; CHECK:     to label %[[exit:[^ ]+]] unwind
 ; CHECK: catch:
 ; CHECK:   catchpad within %cs []
-; CHECK-NEXT: call void @f()
+; CHECK-NEXT: call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
 ; CHECK:   ret void
@@ -118,26 +119,26 @@ catch:
   catchpad within %cs []
   br label %shared
 shared:
-  %x = call i32 @g()
-  %i = call i32 @g()
+  %x = call i32 @llvm.qux()
+  %i = call i32 @llvm.qux()
   %zero.trip = icmp eq i32 %i, 0
   br i1 %zero.trip, label %exit, label %loop
 loop:
   %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ]
-  %b = call i1 @b()
+  %b = call i1 @llvm.baz()
   br i1 %b, label %left, label %right
 left:
-  %y = call i32 @g()
+  %y = call i32 @llvm.qux()
   br label %loop.tail
 right:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   br label %loop.tail
 loop.tail:
   %i.dec = sub i32 %i.loop, 1
   %done = icmp eq i32 %i.dec, 0
   br i1 %done, label %exit, label %loop
 exit:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   unreachable
 }
 ; Make sure we can clone regions that have internal control
@@ -148,34 +149,34 @@ exit:
 ; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch.switch
 ; CHECK:  catch:
 ; CHECK:    catchpad within %cs []
-; CHECK:    [[x_C:%[^ ]+]] = call i32 @g()
-; CHECK:    [[i_C:%[^ ]+]] = call i32 @g()
+; CHECK:    [[x_C:%[^ ]+]] = call i32 @llvm.qux()
+; CHECK:    [[i_C:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
 ; CHECK:    br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]]
 ; CHECK:  [[shared_E]]:
-; CHECK:    [[x_E:%[^ ]+]] = call i32 @g()
-; CHECK:    [[i_E:%[^ ]+]] = call i32 @g()
+; CHECK:    [[x_E:%[^ ]+]] = call i32 @llvm.qux()
+; CHECK:    [[i_E:%[^ ]+]] = call i32 @llvm.qux()
 ; 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]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
-; CHECK:    [[b_C:%[^ ]+]] = call i1 @b()
+; CHECK:    [[b_C:%[^ ]+]] = call i1 @llvm.baz()
 ; CHECK:    br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
 ; CHECK:  [[loop_E]]:
 ; CHECK:    [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ]
-; CHECK:    [[b_E:%[^ ]+]] = call i1 @b()
+; CHECK:    [[b_E:%[^ ]+]] = call i1 @llvm.baz()
 ; CHECK:    br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]]
 ; CHECK:  [[left_C]]:
-; CHECK:    [[y_C:%[^ ]+]] = call i32 @g()
+; CHECK:    [[y_C:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[left_E]]:
-; CHECK:    [[y_E:%[^ ]+]] = call i32 @g()
+; CHECK:    [[y_E:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[right_C]]:
-; CHECK:    call void @h(i32 [[x_C]])
+; CHECK:    call void @llvm.foo(i32 [[x_C]])
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[right_E]]:
-; CHECK:    call void @h(i32 [[x_E]])
+; CHECK:    call void @llvm.foo(i32 [[x_E]])
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[looptail_C]]:
 ; CHECK:    [[idec_C]] = sub i32 [[iloop_C]], 1
@@ -186,10 +187,10 @@ exit:
 ; CHECK:    [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0
 ; CHECK:    br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]]
 ; CHECK:  [[exit_C]]:
-; CHECK:    call void @h(i32 [[x_C]])
+; CHECK:    call void @llvm.foo(i32 [[x_C]])
 ; CHECK:    unreachable
 ; CHECK:  [[exit_E]]:
-; CHECK:    call void @h(i32 [[x_E]])
+; CHECK:    call void @llvm.foo(i32 [[x_E]])
 ; CHECK:    unreachable
 
 
@@ -199,8 +200,8 @@ entry:
     to label %exit unwind label %outer
 outer:
   %o = cleanuppad within none []
-  %x = call i32 @g()
-  invoke void @f()
+  %x = call i32 @llvm.qux()
+  invoke void @f() [ "funclet"(token %o) ]
     to label %outer.ret unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within %o [label %inner] unwind to caller
@@ -208,7 +209,7 @@ inner:
   %i = catchpad within %cs []
   catchret from %i to label %outer.post-inner
 outer.post-inner:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   br label %outer.ret
 outer.ret:
   cleanupret from %o unwind to caller
@@ -220,64 +221,17 @@ exit:
 ; and so don't need to be spilled.
 ; CHECK-LABEL: define void @test5(
 ; CHECK:      outer:
-; CHECK:        %x = call i32 @g()
+; CHECK:        %x = call i32 @llvm.qux()
 ; CHECK-NEXT:   invoke void @f()
 ; CHECK-NEXT:     to label %outer.ret unwind label %catch.switch
 ; CHECK:      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:   call void @llvm.foo(i32 %x)
 ; CHECK-NEXT:   br label %outer.ret
 
 
-define void @test6() personality i32 (...)* @__C_specific_handler {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  cleanuppad within none []
-  br label %shared
-right:
-  %cs = catchswitch within none [label %right.catch] unwind to caller
-right.catch:
-  catchpad within %cs []
-  br label %shared
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = cleanuppad within none []
-  call void @h(i32 %x)
-  cleanupret from %i unwind to caller
-exit:
-  ret void
-}
-; CHECK-LABEL: define void @test6(
-; CHECK:     left:
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; 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
-; CHECK:     shared.cont:
-; CHECK:       unreachable
-; 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 @test9() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
@@ -286,14 +240,14 @@ invoke.cont:
   invoke void @f()
     to label %unreachable unwind label %right
 left:
-  cleanuppad within none []
-  call void @h(i32 1)
-  invoke void @f()
+  %cp.left = cleanuppad within none []
+  call void @llvm.foo(i32 1)
+  invoke void @f() [ "funclet"(token %cp.left) ]
     to label %unreachable unwind label %right
 right:
-  cleanuppad within none []
-  call void @h(i32 2)
-  invoke void @f()
+  %cp.right = cleanuppad within none []
+  call void @llvm.foo(i32 2)
+  invoke void @f() [ "funclet"(token %cp.right) ]
     to label %unreachable unwind label %left
 unreachable:
   unreachable
@@ -305,11 +259,11 @@ unreachable:
 ; CHECK:     invoke.cont:
 ; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
 ; CHECK:     [[LEFT]]:
-; CHECK:       call void @h(i32 1)
+; CHECK:       call void @llvm.foo(i32 1)
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]]
 ; CHECK:     [[RIGHT]]:
-; CHECK:       call void @h(i32 2)
+; CHECK:       call void @llvm.foo(i32 2)
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]]
 ; CHECK:     [[UNREACHABLE_RIGHT]]:
@@ -361,7 +315,7 @@ entry:
     to label %exit unwind label %cleanup.outer
 cleanup.outer:
   %outer = cleanuppad within none []
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %outer) ]
     to label %outer.cont unwind label %cleanup.inner
 outer.cont:
   br label %merge
@@ -369,7 +323,7 @@ cleanup.inner:
   %inner = cleanuppad within %outer []
   br label %merge
 merge:
-  call void @f()
+  call void @llvm.bar()
   unreachable
 exit:
   ret void
@@ -379,7 +333,7 @@ exit:
 ; rewritten to call @f()
 ; CHECK-LABEL: define void @test11()
 ; CHECK:      %inner = cleanuppad within %outer []
-; CHECK-NEXT: call void @f()
+; CHECK-NEXT: call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 
 define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 {
@@ -398,7 +352,7 @@ right:
 join:
   ; This call will get cloned; make sure we can handle cloning
   ; instructions with debug metadata attached.
-  call void @f(), !dbg !9
+  call void @llvm.bar(), !dbg !9
   unreachable
 exit:
   ret void
index bd239133ea878388c8f64858fd06b70089298cf4..411952d84bb6ce3ff3c077641f55e0c0092fc5b8 100644 (file)
@@ -10,6 +10,8 @@ declare void @h(i32)
 
 declare i1 @i()
 
+declare void @llvm.bar() nounwind
+
 ; CHECK-LABEL: @test1(
 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
 entry:
@@ -43,7 +45,7 @@ catch:
   ; CHECK: catch:
   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
   ; CHECK-NEXT: call void @h(i32 [[Reload]])
-  call void @h(i32 %phi)
+  call void @h(i32 %phi) [ "funclet"(token %cp) ]
   catchret from %cp to label %exit
 
 exit:
@@ -81,10 +83,10 @@ catch.inner:
   %cpinner = catchpad within %cs1 []
   ; Need just one store here because only %y is affected
   ; CHECK: catch.inner:
-  %z = call i32 @g()
+  %z = call i32 @g() [ "funclet"(token %cpinner) ]
   ; CHECK:   store i32 %z
   ; CHECK-NEXT: invoke void @f
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %cpinner) ]
           to label %catchret.inner unwind label %merge.outer
 
 catchret.inner:
@@ -106,8 +108,8 @@ catch.outer:
   ; CHECK-DAG: load i32, i32* [[Slot1]]
   ; CHECK-DAG: load i32, i32* [[Slot2]]
   ; CHECK: catchret from [[CatchPad]] to label
-  call void @h(i32 %x)
-  call void @h(i32 %y)
+  call void @h(i32 %x) [ "funclet"(token %cpouter) ]
+  call void @h(i32 %y) [ "funclet"(token %cpouter) ]
   catchret from %cpouter to label %exit
 
 exit:
@@ -166,7 +168,7 @@ catch.outer:
    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
    ; CHECK:   call void @h(i32 [[Reload]])
    %cp2 = catchpad within %cs2 []
-   call void @h(i32 %phi.outer)
+   call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
    catchret from %cp2 to label %exit
 exit:
    ret void
@@ -197,19 +199,19 @@ cleanup:
   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
   %cp = cleanuppad within none []
-  %b = call i1 @i()
+  %b = call i1 @i() [ "funclet"(token %cp) ]
   br i1 %b, label %left, label %right
 
 left:
   ; CHECK: left:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
-  call void @h(i32 %phi.cleanup)
+  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
   br label %merge
 
 right:
   ; CHECK: right:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
-  call void @h(i32 %phi.cleanup)
+  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
   br label %merge
 
 merge:
@@ -239,7 +241,7 @@ catch:
   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
   ; CHECK:   call void @h(i32 [[CatchReload]]
   %cp2 = catchpad within %cs1 []
-  call void @h(i32 %phi.catch)
+  call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
   catchret from %cp2 to label %exit
 
 exit:
@@ -265,7 +267,7 @@ cleanup:
   ; CHECK: cleanup:
   ; CHECK:   call void @h(i32 %x)
   %cp2 = cleanuppad within none []
-  call void @h(i32 %x)
+  call void @h(i32 %x) [ "funclet"(token %cp2) ]
   cleanupret from %cp2 unwind to caller
 }
 
@@ -295,7 +297,7 @@ catch:
   ; CHECK: catch:
   ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
   %cp = catchpad within %cs1 []
-  %b = call i1 @i()
+  %b = call i1 @i() [ "funclet"(token %cp) ]
   br i1 %b, label %left, label %right
 left:
   ; Edge from %left to %join needs to be split so that
@@ -312,7 +314,7 @@ right:
   ; CHECK: right:
   ; CHECK:   %y = call i32 @g()
   ; CHECK:   catchret from %[[CatchPad]] to label %join
-  %y = call i32 @g()
+  %y = call i32 @g() [ "funclet"(token %cp) ]
   catchret from %cp to label %join
 join:
   ; CHECK: join:
@@ -336,19 +338,19 @@ done:
 
 cleanup1:
   ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
-  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: call void @llvm.bar()
   ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
   %cp0 = cleanuppad within none []
   br label %cleanupexit
 
 cleanup2:
   ; CHECK: cleanuppad within none []
-  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: call void @llvm.bar()
   ; CHECK-NEXT: unreachable
   %cp1 = cleanuppad within none []
   br label %cleanupexit
 
 cleanupexit:
-  call void @f()
+  call void @llvm.bar()
   cleanupret from %cp0 unwind label %cleanup2
 }
index ab094aeebf520751fbf8ffc470463e606e3cb2c5..4fb84db890930e6a35f159ae7017165f0c3eebbc 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion < %s | FileCheck %s
+; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion -disable-cleanups < %s | FileCheck %s
 
 declare i32 @__CxxFrameHandler3(...)
 
@@ -11,22 +11,21 @@ declare i32 @g()
 declare void @h(i32)
 
 ; CHECK-LABEL: @test1(
-define void @test1() personality i32 (...)* @__C_specific_handler {
+define void @test1(i1 %bool) personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
-          to label %invoke.cont1 unwind label %left
-
-invoke.cont1:
-  invoke void @f()
-          to label %invoke.cont2 unwind label %right
+          to label %invoke.cont unwind label %left
 
-invoke.cont2:
+invoke.cont:
   invoke void @f()
           to label %exit unwind label %inner
 
 left:
   %0 = cleanuppad within none []
-  br label %shared
+  br i1 %bool, label %shared, label %cleanupret
+
+cleanupret:
+  cleanupret from %0 unwind label %right
 
 right:
   %1 = cleanuppad within none []
@@ -34,19 +33,19 @@ right:
 
 shared:
   %x = call i32 @g()
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %0) ]
           to label %shared.cont unwind label %inner
 
 shared.cont:
   unreachable
 
 inner:
-  %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
+  %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ]
   %i = cleanuppad within none []
   call void @h(i32 %phi)
   unreachable
 
-; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
+; CHECK: %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ], [ %x.for.left, %shared.for.left ]
 ; CHECK: %i = cleanuppad within none []
 ; CHECK: call void @h(i32 %phi)
 
@@ -55,26 +54,25 @@ exit:
 }
 
 ; CHECK-LABEL: @test2(
-define void @test2() personality i32 (...)* @__C_specific_handler {
+define void @test2(i1 %bool) personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
-          to label %invoke.cont unwind label %left
-
-invoke.cont:
-  invoke void @f()
-          to label %exit unwind label %right
+          to label %shared.cont unwind label %left
 
 left:
-  cleanuppad within none []
-  br label %shared
+  %0 = cleanuppad within none []
+  br i1 %bool, label %shared, label %cleanupret
+
+cleanupret:
+  cleanupret from %0 unwind label %right
 
 right:
-  cleanuppad within none []
+  %1 = cleanuppad within none []
   br label %shared
 
 shared:
   %x = call i32 @g()
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %0) ]
           to label %shared.cont unwind label %inner
 
 shared.cont:
@@ -85,9 +83,9 @@ inner:
   call void @h(i32 %x)
   unreachable
 
-; CHECK:  %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
-; CHECK:  %i = cleanuppad within none []
-; CHECK:  call void @h(i32 %x1)
+; CHECK: %x1 = phi i32 [ %x.for.left, %shared.for.left ], [ %x, %shared ]
+; CHECK: %i = cleanuppad within none []
+; CHECK: call void @h(i32 %x1)
 
 exit:
   unreachable
@@ -119,13 +117,12 @@ shared:
   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)
 
+; CHECK: %phi.for.left = phi i32 [ 1, %left ]
+; CHECK: call void @h(i32 %phi.for.left)
+
 exit:
   unreachable
 }
index 1abcd03ac64ffa61cf5281008c176a12f5462537..60939bc6b03ee3da12f91affbccb9f6650c53fdf 100644 (file)
@@ -58,7 +58,7 @@ catch:                                            ; preds = %catch.dispatch.2
 
 ehcleanup:                                        ; preds = %catchendblock
   %4 = cleanuppad within none []
-  call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
+  call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4 [ "funclet"(token %4) ]
   cleanupret from %4 unwind to caller
 }
 
index 294ef3abc46236068f0b87f810b7c4e3b8804e8e..2e34ada52e6b9b3c23b06b585f7267af988524d6 100644 (file)
@@ -30,7 +30,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %2 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0)
+  call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0) [ "funclet"(token %2) ]
   cleanupret from %2 unwind to caller
 }
 
index e32cdbed73fb2dcbaa9d97ff987a2915e9e41010..8ffb97d8dd68717e146ca9b352c67c929f64d744 100644 (file)
@@ -10,7 +10,7 @@ entry:
     to label %exit unwind label %cleanup
 cleanup:
   %c = cleanuppad within none []
-  call void @bar()
+  call void @bar() [ "funclet"(token %c) ]
   cleanupret from %c unwind to caller
 exit:
   ret void
index d322932da4c1bf2c1f6c543addfc7bb80604a7a9..5a565cc1570f176d326327a4fe8f3e69cca6edb5 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  call void @Dtor(i64* %o)
+  call void @Dtor(i64* %o) [ "funclet"(token %0) ]
   cleanupret from %0 unwind to caller
 }
 
index b5972df43cc95851d43e37c9f2a37ef7da0ab848..0942645cf5a40e5f491896659adfed2ca49ef578 100644 (file)
@@ -59,7 +59,7 @@ catch.dispatch:                                   ; preds = %entry
 
 catch:                                            ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
-  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
+  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 ["funclet"(token %0)]
           to label %unreachable unwind label %catch.dispatch.1
 
 catch.dispatch.1:                                 ; preds = %catch
@@ -110,7 +110,7 @@ catch.dispatch:                                   ; preds = %entry
 
 catch.2:                                          ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  tail call void @exit(i32 0) #2
+  tail call void @exit(i32 0) #2 [ "funclet"(token %0) ]
   unreachable
 
 catch.dispatch.1:                                 ; preds = %catch.dispatch
@@ -118,7 +118,7 @@ catch.dispatch.1:                                 ; preds = %catch.dispatch
 
 catch:                                            ; preds = %catch.dispatch.1
   %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
-  tail call void @exit(i32 0) #2
+  tail call void @exit(i32 0) #2 [ "funclet"(token %1) ]
   unreachable
 
 try.cont:                                         ; preds = %entry
index 69afb1b9d9c63c90bf0da7b38d6c3f137694993c..e8da7ab971b13070e139da6567434a77b9f46ed3 100644 (file)
@@ -27,7 +27,7 @@ lpad:                                             ; preds = %entry
 __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
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4 [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
index 4463485f2093fc4eb5e9dc825dde52579b9e90c8..76823bd476b1c957b80c631b990f154bc65e9a76 100644 (file)
@@ -21,7 +21,7 @@ lpad:
 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)
+  call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code) [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 }
 
index a8be4ec14500c07ddace91b3846b252ca181b5eb..321d3a70cf8afbdbe464aa58afeb657bd1c5b440 100644 (file)
@@ -69,7 +69,7 @@ __except:                                         ; preds = %catch.dispatch
 
 ehcleanup:                                        ; preds = %__except.2
   %cp2 = cleanuppad within none []
-  invoke fastcc void @"\01?fin$0@0@main@@"() #4
+  invoke fastcc void @"\01?fin$0@0@main@@"() #4 [ "funclet"(token %cp2) ]
           to label %invoke.cont.6 unwind label %catch.dispatch.7
 
 invoke.cont.6:                                    ; preds = %ehcleanup
index b252b5b124848c21dcee2e6d50a4e2c2a258ee77..c15ecfcd77b261e8cdd39e381dba98e0524c7716 100644 (file)
@@ -51,7 +51,7 @@ invoke.cont2:                                     ; preds = %invoke.cont
 __finally:                                             ; preds = %entry
   %cleanuppad = cleanuppad within none []
   %locals = call i8* @llvm.localaddress()
-  invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5
+  invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5 [ "funclet"(token %cleanuppad) ]
           to label %invoke.cont3 unwind label %catch.dispatch
 
 invoke.cont3:                                     ; preds = %__finally
@@ -62,7 +62,7 @@ catch.dispatch:                                   ; preds = %invoke.cont3, %lpad
 
 __except:                                         ; preds = %catch.dispatch
   %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
-  %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
+  %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0)) [ "funclet"(token %catchpad) ]
   catchret from %catchpad to label %__try.cont
 
 __try.cont:                                       ; preds = %__except, %invoke.cont2
index 67bce81a66ad31d8bee9cec79c38285df70a37ed..8405d200776d74bfc693c98e23693b13c0b4ab2a 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont:                                      ; preds = %entry
 
 lpad:                                             ; preds = %entry
   %p = cleanuppad within none []
-  %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
+  %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0)) [ "funclet"(token %p) ]
   cleanupret from %p unwind to caller
 }
 
index 3f88696fe602f36ed22df576d57889e0f04b8162..643af3a472fb4e23277c6d021def1118d865287e 100644 (file)
@@ -35,7 +35,7 @@ lpad0:
 
 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))
+  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
@@ -44,7 +44,7 @@ lpad1:
 
 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))
+  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
index 3eeeab09ffbb9b01ffc5391e9a88268fbc3f4d4e..dd5752e8a716995acf13e39dec8cc2ed3aa91174 100644 (file)
@@ -34,7 +34,7 @@ lpad0:
 
 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))
+  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
@@ -43,7 +43,7 @@ lpad1:
 
 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))
+  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
index 880533b43925375aef1dd83b0ee4f115e22bc46f..654cad347f6b46a163d1c7dc242f0c81fd5f4a0f 100644 (file)
@@ -28,7 +28,7 @@ lpad:                                             ; preds = %entry
 __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
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4 [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
index 9f7a49536caa86b4558d95fe2a90185cc866321a..327ee45b4326d022e68ccb4c14ab4aaad971ac15 100644 (file)
@@ -34,7 +34,7 @@ catch.dispatch:
 
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  call void @f(i32 2)
+  call void @f(i32 2) [ "funclet"(token %h1) ]
   catchret from %h1 to label %try.cont
 }
 
index 22ce7e5cd87956c80fe7c7200549d854c794f724..ac4598385cd1f155da351f6c30f840f9780fb6de 100644 (file)
@@ -31,7 +31,7 @@ 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)
+  invoke void @f(i32 2) [ "funclet"(token %h1) ]
           to label %catchret1 unwind label %catch.dispatch.2
 catchret1:
   catchret from %h1 to label %try.cont
index d20f9f69a5ee2646c1772578a7d4fa884acb2dd4..7afcd9cc1f3e1fbee2c9c993fbc49b0c91c7e801 100644 (file)
@@ -16,7 +16,7 @@ catch.dispatch.1:
 
 outer.catch:
   %cp1 = catchpad within %cs1 [i32 1]
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %cp1) ]
           to label %outer.ret unwind label %catch.dispatch.2
 outer.ret:
   catchret from %cp1 to label %exit
index 5bd250461302477bbfdf938cda20e39e0bddc308..836c53bda8e686d69334038e820e0ed6a05b9378 100644 (file)
@@ -41,12 +41,12 @@ catch.dispatch:                                   ; preds = %entry
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
   %e = load i32, i32* %e.addr
-  call void @f(i32 %e, i32* %local)
+  call void @f(i32 %e, i32* %local) [ "funclet"(token %h1) ]
   catchret from %h1 to label %try.cont
 
 handler2:
   %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
-  call void @f(i32 3, i32* %local)
+  call void @f(i32 3, i32* %local) [ "funclet"(token %h2) ]
   catchret from %h2 to label %try.cont
 
 try.cont:
@@ -229,7 +229,7 @@ catch:
   br label %loop
 
 loop:
-  %V = call i1 @getbool()
+  %V = call i1 @getbool() [ "funclet"(token %cp1) ]
   br i1 %V, label %loop, label %catch.done
 
 catch.done:
index 37090c2f6bccb7678c2966edf8c6fa907767997c..4b0a543a876a755fdb18b36ddabf696ad038580e 100644 (file)
@@ -15,7 +15,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2 [ "funclet"(token %0) ]
   cleanupret from %0 unwind to caller
 }
 
@@ -78,12 +78,12 @@ invoke.cont.2:                                    ; preds = %invoke.cont.1
 
 cleanup.inner:                                        ; preds = %invoke.cont
   %0 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2 [ "funclet"(token %0) ]
   cleanupret from %0 unwind label %cleanup.outer
 
 cleanup.outer:                                      ; preds = %invoke.cont.1, %cleanup.inner, %entry
   %1 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2 [ "funclet"(token %1) ]
   cleanupret from %1 unwind to caller
 }
 
index 95afa75a709a541e973a31969b7ed3c8153b6dce..2151cdc7bb4b3ee361aa2f9e7f33f9fd8cc2c6da 100644 (file)
@@ -10,7 +10,7 @@ entry:
 
 cleanupblock:
   %cleanp = cleanuppad within none []
-  call void @g()
+  call void @g() [ "funclet"(token %cleanp) ]
   cleanupret from %cleanp unwind label %catch.dispatch
 
 catch.dispatch:
@@ -18,7 +18,7 @@ catch.dispatch:
 
 catch:
   %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
-  call void @g()
+  call void @g() [ "funclet"(token %cp) ]
   catchret from %cp to label %try.cont
 
 try.cont:
index fe3639b97a4557666c3ff1148a32c86f4f536837..2777d6644e6a3f0bec18918d27ab29c53b7306a4 100644 (file)
@@ -48,7 +48,7 @@ lpad:                                             ; preds = %catch, %entry
 
 catch:                                            ; preds = %lpad.1
   %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  invoke void @may_throw(i32 3)
+  invoke void @may_throw(i32 3) [ "funclet"(token %p1) ]
           to label %invoke.cont.3 unwind label %lpad.1
 
 invoke.cont.3:                                    ; preds = %catch
@@ -59,7 +59,7 @@ lpad.1:                                           ; preds = %invoke.cont
 
 catch.7:
   %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  call void @may_throw(i32 4)
+  call void @may_throw(i32 4) [ "funclet"(token %p2) ]
   catchret from %p2 to label %try.cont.9
 }
 
@@ -131,19 +131,19 @@ catch.dispatch:                                   ; preds = %entry
 
 catch:                                            ; preds = %catch.dispatch
   %1 = catchpad within %0 [i8* null, i32 64, i8* null]
-  invoke void @may_throw(i32 0)
+  invoke void @may_throw(i32 0) [ "funclet"(token %1) ]
           to label %invoke.cont unwind label %ehcleanup5
 
 invoke.cont:                                      ; preds = %catch
-  invoke void @may_throw(i32 1)
+  invoke void @may_throw(i32 1) [ "funclet"(token %1) ]
           to label %invoke.cont2 unwind label %ehcleanup
 
 invoke.cont2:                                     ; preds = %invoke.cont
-  invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+  invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %1) ]
           to label %invoke.cont3 unwind label %ehcleanup5
 
 invoke.cont3:                                     ; preds = %invoke.cont2
-  invoke void @may_throw(i32 2)
+  invoke void @may_throw(i32 2) [ "funclet"(token %1) ]
           to label %invoke.cont4 unwind label %ehcleanup5
 
 invoke.cont4:                                     ; preds = %invoke.cont3
@@ -155,12 +155,12 @@ try.cont:                                         ; preds = %invoke.cont4
 
 ehcleanup:                                        ; preds = %invoke.cont
   %2 = cleanuppad within %1 []
-  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %2) ]
   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@XZ"(%struct.S* nonnull %x)
+  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x) [ "funclet"(token %3) ]
   cleanupret from %3 unwind to caller
 
 unreachable:                                      ; preds = %entry
index 88dea3675725be7198547f17fc1f3546b87833bf..6c25161ec8ca05edba12336dd234925d8326b25c 100644 (file)
@@ -193,7 +193,7 @@ catch.dispatch:                                   ; preds = %entry
 
 __except.ret:                                     ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
-  call void @f(i32 2)
+  call void @f(i32 2) [ "funclet"(token %0) ]
   catchret from %0 to label %__except
 
 __except:
index c91a14278ec70d3923f24d05b6f010ae1f84cbe3..61bf79a76f878ba5af471d2f69f1a5a98f08856f 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont.1:                                    ; preds = %invoke.cont
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  invoke void @f(i32 2) #3
+  invoke void @f(i32 2) #3 [ "funclet"(token %0) ]
           to label %invoke.cont.2 unwind label %ehcleanup.3
 
 invoke.cont.2:                                    ; preds = %ehcleanup
@@ -26,7 +26,7 @@ invoke.cont.2:                                    ; preds = %ehcleanup
 
 ehcleanup.3:                                      ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
   %1 = cleanuppad within none []
-  call void @f(i32 3) #3
+  call void @f(i32 3) #3 [ "funclet"(token %1) ]
   cleanupret from %1 unwind to caller
 }
 
index 7bbc64ece8ede5684c65ae68d59f37cc7fdc7d4f..b61876827cac89e9aa0fcbe7ed4cb9cc9c9e8a87 100644 (file)
@@ -65,12 +65,12 @@ catch1.body:
 ;             ^ 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)
+  call void @g(i8 addrspace(1)* %exn1) [ "funclet"(token %catch1) ]
 ; CHECK: [[L_before_f3:.+]]:
 ; CHECK-NEXT: movl $3, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f3:.+]]:
-  invoke void @f(i32 3)
+  invoke void @f(i32 3) [ "funclet"(token %catch1) ]
     to label %catch1.ret unwind label %finally.pad
 catch1.ret:
   catchret from %catch1 to label %finally.clone
@@ -88,12 +88,12 @@ catch2.body:
 ;             ^ 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)
+  call void @g(i8 addrspace(1)* %exn2) [ "funclet"(token %catch2) ]
 ; CHECK: [[L_before_f4:.+]]:
 ; CHECK-NEXT: movl $4, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f4:.+]]:
-  invoke void @f(i32 4)
+  invoke void @f(i32 4) [ "funclet"(token %catch2) ]
     to label %try_in_catch unwind label %finally.pad
 try_in_catch:
 ; CHECK: # %try_in_catch
@@ -101,7 +101,7 @@ try_in_catch:
 ; CHECK-NEXT: movl $5, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f5:.+]]:
-  invoke void @f(i32 5)
+  invoke void @f(i32 5) [ "funclet"(token %catch2) ]
     to label %catch2.ret unwind label %fault.pad
 fault.pad:
 ; CHECK: .seh_proc [[L_fault:[^ ]+]]
@@ -117,7 +117,7 @@ fault.pad:
 ; CHECK-NEXT: movl $6, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f6:.+]]:
-  invoke void @f(i32 6)
+  invoke void @f(i32 6) [ "funclet"(token %fault) ]
     to label %fault.ret unwind label %finally.pad
 fault.ret:
   cleanupret from %fault unwind label %finally.pad
@@ -138,7 +138,7 @@ finally.pad:
 ; CHECK: .seh_endprologue
 ; CHECK-NEXT: movl $7, %ecx
 ; CHECK-NEXT: callq f
-  call void @f(i32 7)
+  call void @f(i32 7) [ "funclet"(token %finally) ]
   cleanupret from %finally unwind to caller
 tail:
   call void @f(i32 8)
index 9c1f0aaf3de37fcdaa56b06ec35247a0faf4c07d..f6fd4fe7c525689d4d4599900b7796177d65c046 100644 (file)
@@ -19,7 +19,7 @@ catch.body:
   %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)
+  call void @g(i32 addrspace(1)* %cast_exn) [ "funclet"(token %catch) ]
   catchret from %catch to label %exit
 exit:
   ret void