[llvm] r229944 - EH: Prune unreachable resume instructions during Dwarf EH preparation

Reid Kleckner reid at kleckner.net
Thu Feb 19 17:00:20 PST 2015


Author: rnk
Date: Thu Feb 19 19:00:19 2015
New Revision: 229944

URL: http://llvm.org/viewvc/llvm-project?rev=229944&view=rev
Log:
EH: Prune unreachable resume instructions during Dwarf EH preparation

Today a simple function that only catches exceptions and doesn't run
destructor cleanups ends up containing a dead call to _Unwind_Resume
(PR20300). We can't remove these dead resume instructions during normal
optimization because inlining might introduce additional landingpads
that do have cleanups to run. Instead we can do this during EH
preparation, which is guaranteed to run after inlining.

Fixes PR20300.

Reviewers: majnemer

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

Modified:
    llvm/trunk/include/llvm/CodeGen/Passes.h
    llvm/trunk/lib/CodeGen/CodeGen.cpp
    llvm/trunk/lib/CodeGen/DwarfEHPrepare.cpp
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/test/CodeGen/Mips/eh.ll
    llvm/trunk/test/CodeGen/X86/dwarf-eh-prepare.ll
    llvm/trunk/test/CodeGen/X86/gcc_except_table.ll
    llvm/trunk/test/CodeGen/X86/gcc_except_table_functions.ll
    llvm/trunk/test/CodeGen/XCore/exception.ll

Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/Passes.h Thu Feb 19 19:00:19 2015
@@ -612,13 +612,13 @@ namespace llvm {
   ModulePass *createForwardControlFlowIntegrityPass();
 } // End llvm namespace
 
-/// This initializer registers TargetMachine constructor, so the pass being
-/// initialized can use target dependent interfaces. Please do not move this
-/// macro to be together with INITIALIZE_PASS, which is a complete target
-/// independent initializer, and we don't want to make libScalarOpts depend
-/// on libCodeGen.
-#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
-  static void* initialize##passName##PassOnce(PassRegistry &Registry) { \
+/// Target machine pass initializer for passes with dependencies. Use with
+/// INITIALIZE_TM_PASS_END.
+#define INITIALIZE_TM_PASS_BEGIN INITIALIZE_PASS_BEGIN
+
+/// Target machine pass initializer for passes with dependencies. Use with
+/// INITIALIZE_TM_PASS_BEGIN.
+#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \
     PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \
       PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \
       PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \
@@ -629,4 +629,13 @@ namespace llvm {
     CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
   }
 
+/// This initializer registers TargetMachine constructor, so the pass being
+/// initialized can use target dependent interfaces. Please do not move this
+/// macro to be together with INITIALIZE_PASS, which is a complete target
+/// independent initializer, and we don't want to make libScalarOpts depend
+/// on libCodeGen.
+#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \
+    INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \
+    INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis)
+
 #endif

Modified: llvm/trunk/lib/CodeGen/CodeGen.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGen.cpp?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGen.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGen.cpp Thu Feb 19 19:00:19 2015
@@ -24,9 +24,10 @@ void llvm::initializeCodeGen(PassRegistr
   initializeBranchFolderPassPass(Registry);
   initializeCodeGenPreparePass(Registry);
   initializeDeadMachineInstructionElimPass(Registry);
+  initializeDwarfEHPreparePass(Registry);
   initializeEarlyIfConverterPass(Registry);
-  initializeExpandPostRAPass(Registry);
   initializeExpandISelPseudosPass(Registry);
+  initializeExpandPostRAPass(Registry);
   initializeFinalizeMachineBundlesPass(Registry);
   initializeGCMachineCodeAnalysisPass(Registry);
   initializeGCModuleInfoPass(Registry);
@@ -36,31 +37,34 @@ void llvm::initializeCodeGen(PassRegistr
   initializeLiveStacksPass(Registry);
   initializeLiveVariablesPass(Registry);
   initializeLocalStackSlotPassPass(Registry);
+  initializeLowerIntrinsicsPass(Registry);
   initializeMachineBlockFrequencyInfoPass(Registry);
   initializeMachineBlockPlacementPass(Registry);
   initializeMachineBlockPlacementStatsPass(Registry);
-  initializeMachineCopyPropagationPass(Registry);
-  initializeMachineCombinerPass(Registry);
   initializeMachineCSEPass(Registry);
+  initializeMachineCombinerPass(Registry);
+  initializeMachineCopyPropagationPass(Registry);
   initializeMachineDominatorTreePass(Registry);
-  initializeMachinePostDominatorTreePass(Registry);
+  initializeMachineFunctionPrinterPassPass(Registry);
   initializeMachineLICMPass(Registry);
   initializeMachineLoopInfoPass(Registry);
   initializeMachineModuleInfoPass(Registry);
+  initializeMachinePostDominatorTreePass(Registry);
   initializeMachineSchedulerPass(Registry);
   initializeMachineSinkingPass(Registry);
   initializeMachineVerifierPassPass(Registry);
   initializeOptimizePHIsPass(Registry);
+  initializePEIPass(Registry);
   initializePHIEliminationPass(Registry);
   initializePeepholeOptimizerPass(Registry);
   initializePostMachineSchedulerPass(Registry);
   initializePostRASchedulerPass(Registry);
   initializeProcessImplicitDefsPass(Registry);
-  initializePEIPass(Registry);
   initializeRegisterCoalescerPass(Registry);
   initializeSlotIndexesPass(Registry);
-  initializeStackProtectorPass(Registry);
   initializeStackColoringPass(Registry);
+  initializeStackMapLivenessPass(Registry);
+  initializeStackProtectorPass(Registry);
   initializeStackSlotColoringPass(Registry);
   initializeTailDuplicatePassPass(Registry);
   initializeTargetPassConfigPass(Registry);
@@ -70,9 +74,7 @@ void llvm::initializeCodeGen(PassRegistr
   initializeUnreachableMachineBlockElimPass(Registry);
   initializeVirtRegMapPass(Registry);
   initializeVirtRegRewriterPass(Registry);
-  initializeLowerIntrinsicsPass(Registry);
-  initializeMachineFunctionPrinterPassPass(Registry);
-  initializeStackMapLivenessPass(Registry);
+  initializeWinEHPreparePass(Registry);
 }
 
 void LLVMInitializeCodeGen(LLVMPassRegistryRef R) {

Modified: llvm/trunk/lib/CodeGen/DwarfEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DwarfEHPrepare.cpp?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/DwarfEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/DwarfEHPrepare.cpp Thu Feb 19 19:00:19 2015
@@ -13,13 +13,18 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/CFG.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Transforms/Utils/Local.h"
 using namespace llvm;
 
 #define DEBUG_TYPE "dwarfehprepare"
@@ -33,18 +38,28 @@ namespace {
     // RewindFunction - _Unwind_Resume or the target equivalent.
     Constant *RewindFunction;
 
+    DominatorTree *DT;
+    const TargetLowering *TLI;
+
     bool InsertUnwindResumeCalls(Function &Fn);
     Value *GetExceptionObject(ResumeInst *RI);
+    size_t
+    pruneUnreachableResumes(Function &Fn,
+                            SmallVectorImpl<ResumeInst *> &Resumes,
+                            SmallVectorImpl<LandingPadInst *> &CleanupLPads);
 
   public:
     static char ID; // Pass identification, replacement for typeid.
 
     // INITIALIZE_TM_PASS requires a default constructor, but it isn't used in
     // practice.
-    DwarfEHPrepare() : FunctionPass(ID), TM(nullptr), RewindFunction(nullptr) {}
+    DwarfEHPrepare()
+        : FunctionPass(ID), TM(nullptr), RewindFunction(nullptr), DT(nullptr),
+          TLI(nullptr) {}
 
     DwarfEHPrepare(const TargetMachine *TM)
-        : FunctionPass(ID), TM(TM), RewindFunction(nullptr) {}
+        : FunctionPass(ID), TM(TM), RewindFunction(nullptr), DT(nullptr),
+          TLI(nullptr) {}
 
     bool runOnFunction(Function &Fn) override;
 
@@ -53,6 +68,8 @@ namespace {
       return false;
     }
 
+    void getAnalysisUsage(AnalysisUsage &AU) const override;
+
     const char *getPassName() const override {
       return "Exception handling preparation";
     }
@@ -60,13 +77,22 @@ namespace {
 } // end anonymous namespace
 
 char DwarfEHPrepare::ID = 0;
-INITIALIZE_TM_PASS(DwarfEHPrepare, "dwarfehprepare", "Prepare DWARF exceptions",
-                   false, false)
+INITIALIZE_TM_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare",
+                         "Prepare DWARF exceptions", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
+INITIALIZE_TM_PASS_END(DwarfEHPrepare, "dwarfehprepare",
+                       "Prepare DWARF exceptions", false, false)
 
 FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) {
   return new DwarfEHPrepare(TM);
 }
 
+void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<TargetTransformInfoWrapperPass>();
+  AU.addRequired<DominatorTreeWrapperPass>();
+}
+
 /// GetExceptionObject - Return the exception object from the value passed into
 /// the 'resume' instruction (typically an aggregate). Clean up any dead
 /// instructions, including the 'resume' instruction.
@@ -107,21 +133,71 @@ Value *DwarfEHPrepare::GetExceptionObjec
   return ExnObj;
 }
 
+/// Replace resumes that are not reachable from a cleanup landing pad with
+/// unreachable and then simplify those blocks.
+size_t DwarfEHPrepare::pruneUnreachableResumes(
+    Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
+    SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
+  BitVector ResumeReachable(Resumes.size());
+  size_t ResumeIndex = 0;
+  for (auto *RI : Resumes) {
+    for (auto *LP : CleanupLPads) {
+      if (isPotentiallyReachable(LP, RI, DT)) {
+        ResumeReachable.set(ResumeIndex);
+        break;
+      }
+    }
+    ++ResumeIndex;
+  }
+
+  // If everything is reachable, there is no change.
+  if (ResumeReachable.all())
+    return Resumes.size();
+
+  const TargetTransformInfo &TTI =
+      getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
+  LLVMContext &Ctx = Fn.getContext();
+
+  // Otherwise, insert unreachable instructions and call simplifycfg.
+  size_t ResumesLeft = 0;
+  for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
+    ResumeInst *RI = Resumes[I];
+    if (ResumeReachable[I]) {
+      Resumes[ResumesLeft++] = RI;
+    } else {
+      BasicBlock *BB = RI->getParent();
+      new UnreachableInst(Ctx, RI);
+      RI->eraseFromParent();
+      SimplifyCFG(BB, TTI, 1, TLI->getDataLayout());
+    }
+  }
+  Resumes.resize(ResumesLeft);
+  return ResumesLeft;
+}
+
 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
 /// into calls to the appropriate _Unwind_Resume function.
 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
   SmallVector<ResumeInst*, 16> Resumes;
+  SmallVector<LandingPadInst*, 16> CleanupLPads;
   for (BasicBlock &BB : Fn) {
     if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
       Resumes.push_back(RI);
+    if (auto *LP = BB.getLandingPadInst())
+      if (LP->isCleanup())
+        CleanupLPads.push_back(LP);
   }
 
   if (Resumes.empty())
     return false;
 
-  // Find the rewind function if we didn't already.
-  const TargetLowering *TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
   LLVMContext &Ctx = Fn.getContext();
+
+  size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
+  if (ResumesLeft == 0)
+    return true; // We pruned them all.
+
+  // Find the rewind function if we didn't already.
   if (!RewindFunction) {
     FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
                                           Type::getInt8PtrTy(Ctx), false);
@@ -130,9 +206,7 @@ bool DwarfEHPrepare::InsertUnwindResumeC
   }
 
   // Create the basic block where the _Unwind_Resume call will live.
-  unsigned ResumesSize = Resumes.size();
-
-  if (ResumesSize == 1) {
+  if (ResumesLeft == 1) {
     // Instead of creating a new BB and PHI node, just append the call to
     // _Unwind_Resume to the end of the single resume block.
     ResumeInst *RI = Resumes.front();
@@ -149,7 +223,7 @@ bool DwarfEHPrepare::InsertUnwindResumeC
   }
 
   BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
-  PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesSize,
+  PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
                                 "exn.obj", UnwindBB);
 
   // Extract the exception object from the ResumeInst and add it to the PHI node
@@ -175,6 +249,10 @@ bool DwarfEHPrepare::InsertUnwindResumeC
 
 bool DwarfEHPrepare::runOnFunction(Function &Fn) {
   assert(TM && "DWARF EH preparation requires a target machine");
+  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+  TLI = TM->getSubtargetImpl(Fn)->getTargetLowering();
   bool Changed = InsertUnwindResumeCalls(Fn);
+  DT = nullptr;
+  TLI = nullptr;
   return Changed;
 }

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Thu Feb 19 19:00:19 2015
@@ -84,8 +84,13 @@ private:
 } // end anonymous namespace
 
 char WinEHPrepare::ID = 0;
-INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
-                   false, false)
+INITIALIZE_TM_PASS_BEGIN(WinEHPrepare, "winehprepare",
+                         "Prepare Windows exceptions", false, false)
+INITIALIZE_PASS_DEPENDENCY(DwarfEHPrepare)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
+INITIALIZE_TM_PASS_END(WinEHPrepare, "winehprepare",
+                       "Prepare Windows exceptions", false, false)
 
 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
   return new WinEHPrepare(TM);
@@ -114,8 +119,12 @@ bool WinEHPrepare::runOnFunction(Functio
   EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn());
 
   // Delegate through to the DWARF pass if this is unrecognized.
-  if (!isMSVCPersonality(Pers))
+  if (!isMSVCPersonality(Pers)) {
+    // Use the resolver from our pass manager in the dwarf pass.
+    assert(getResolver());
+    DwarfPrepare->setResolver(getResolver());
     return DwarfPrepare->runOnFunction(Fn);
+  }
 
   // FIXME: This only returns true if the C++ EH handlers were outlined.
   //        When that code is complete, it should always return whatever

Modified: llvm/trunk/test/CodeGen/Mips/eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/eh.ll?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/eh.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/eh.ll Thu Feb 19 19:00:19 2015
@@ -27,6 +27,7 @@ lpad:
 ; CHECK-EL:  bne $5
 
   %exn.val = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+           cleanup
            catch i8* bitcast (i8** @_ZTId to i8*)
   %exn = extractvalue { i8*, i32 } %exn.val, 0
   %sel = extractvalue { i8*, i32 } %exn.val, 1

Modified: llvm/trunk/test/CodeGen/X86/dwarf-eh-prepare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/dwarf-eh-prepare.ll?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/dwarf-eh-prepare.ll (original)
+++ llvm/trunk/test/CodeGen/X86/dwarf-eh-prepare.ll Thu Feb 19 19:00:19 2015
@@ -7,12 +7,13 @@
 @int_typeinfo = global i8 0
 
 declare void @might_throw()
+declare void @cleanup()
 
-define i32 @simple_catch() {
+define i32 @simple_cleanup_catch() {
   invoke void @might_throw()
           to label %cont unwind label %lpad
 
-; CHECK: define i32 @simple_catch()
+; CHECK-LABEL: define i32 @simple_cleanup_catch()
 ; CHECK: invoke void @might_throw()
 
 cont:
@@ -22,15 +23,18 @@ cont:
 
 lpad:
   %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+      cleanup
       catch i8* @int_typeinfo
   %ehptr = extractvalue { i8*, i32 } %ehvals, 0
   %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+  call void @cleanup()
   %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
   %int_match = icmp eq i32 %ehsel, %int_sel
   br i1 %int_match, label %catch_int, label %eh.resume
 
 ; CHECK: lpad:
 ; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: call void @cleanup()
 ; CHECK: call i32 @llvm.eh.typeid.for
 ; CHECK: br i1
 
@@ -41,11 +45,114 @@ catch_int:
 ; CHECK: ret i32 1
 
 eh.resume:
-  resume { i8*, i32 } %ehvals
+  %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+  %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+  resume { i8*, i32 } %new_ehvals
 
 ; CHECK: eh.resume:
-; CHECK: call void @_Unwind_Resume(i8* %{{.*}})
+; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
 }
 
+
+define i32 @catch_no_resume() {
+  invoke void @might_throw()
+          to label %cont unwind label %lpad
+
+cont:
+  ret i32 0
+
+lpad:
+  %ehvals = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+      catch i8* @int_typeinfo
+  %ehptr = extractvalue { i8*, i32 } %ehvals, 0
+  %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+  %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
+  %int_match = icmp eq i32 %ehsel, %int_sel
+  br i1 %int_match, label %catch_int, label %eh.resume
+
+catch_int:
+  ret i32 1
+
+eh.resume:
+  %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+  %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+  resume { i8*, i32 } %new_ehvals
+}
+
+; Check that we can prune the unreachable resume instruction.
+
+; CHECK-LABEL: define i32 @catch_no_resume() {
+; CHECK: invoke void @might_throw()
+; CHECK: ret i32 0
+; CHECK: lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK-NOT: br i1
+; CHECK: ret i32 1
+; CHECK-NOT: call void @_Unwind_Resume
+; CHECK: {{^[}]}}
+
+
+define i32 @catch_cleanup_merge() {
+  invoke void @might_throw()
+          to label %inner_invoke unwind label %outer_lpad
+inner_invoke:
+  invoke void @might_throw()
+          to label %cont unwind label %inner_lpad
+cont:
+  ret i32 0
+
+outer_lpad:
+  %ehvals1 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+      catch i8* @int_typeinfo
+  br label %catch.dispatch
+
+inner_lpad:
+  %ehvals2 = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+      cleanup
+      catch i8* @int_typeinfo
+  call void @cleanup()
+  br label %catch.dispatch
+
+catch.dispatch:
+  %ehvals = phi { i8*, i32 } [ %ehvals1, %outer_lpad ], [ %ehvals2, %inner_lpad ]
+  %ehptr = extractvalue { i8*, i32 } %ehvals, 0
+  %ehsel = extractvalue { i8*, i32 } %ehvals, 1
+  %int_sel = call i32 @llvm.eh.typeid.for(i8* @int_typeinfo)
+  %int_match = icmp eq i32 %ehsel, %int_sel
+  br i1 %int_match, label %catch_int, label %eh.resume
+
+catch_int:
+  ret i32 1
+
+eh.resume:
+  %tmp_ehvals = insertvalue { i8*, i32 } undef, i8* %ehptr, 0
+  %new_ehvals = insertvalue { i8*, i32 } %tmp_ehvals, i32 %ehsel, 1
+  resume { i8*, i32 } %new_ehvals
+}
+
+; We can't prune this merge because one landingpad is a cleanup pad.
+
+; CHECK-LABEL: define i32 @catch_cleanup_merge()
+; CHECK: invoke void @might_throw()
+; CHECK: invoke void @might_throw()
+; CHECK: ret i32 0
+;
+; CHECK: outer_lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: br label %catch.dispatch
+;
+; CHECK: inner_lpad:
+; CHECK: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
+; CHECK: call void @cleanup()
+; CHECK: br label %catch.dispatch
+;
+; CHECK: catch.dispatch:
+; CHECK: call i32 @llvm.eh.typeid.for
+; CHECK: br i1
+; CHECK: catch_int:
+; CHECK: ret i32 1
+; CHECK: eh.resume:
+; CHECK-NEXT: call void @_Unwind_Resume(i8* %ehptr)
+
 declare i32 @__gxx_personality_v0(...)
 declare i32 @llvm.eh.typeid.for(i8*)

Modified: llvm/trunk/test/CodeGen/X86/gcc_except_table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/gcc_except_table.ll?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/gcc_except_table.ll (original)
+++ llvm/trunk/test/CodeGen/X86/gcc_except_table.ll Thu Feb 19 19:00:19 2015
@@ -37,6 +37,7 @@ entry:
 
 lpad:
   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          cleanup
           catch i8* bitcast (i8** @_ZTIi to i8*)
   br label %eh.resume
 

Modified: llvm/trunk/test/CodeGen/X86/gcc_except_table_functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/gcc_except_table_functions.ll?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/gcc_except_table_functions.ll (original)
+++ llvm/trunk/test/CodeGen/X86/gcc_except_table_functions.ll Thu Feb 19 19:00:19 2015
@@ -20,6 +20,7 @@ try.cont:
 
 lpad:
   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          cleanup
           catch i8* bitcast (void ()* @filt0 to i8*)
           catch i8* bitcast (void ()* @filt1 to i8*)
   %sel = extractvalue { i8*, i32 } %0, 1

Modified: llvm/trunk/test/CodeGen/XCore/exception.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/XCore/exception.ll?rev=229944&r1=229943&r2=229944&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/XCore/exception.ll (original)
+++ llvm/trunk/test/CodeGen/XCore/exception.ll Thu Feb 19 19:00:19 2015
@@ -78,6 +78,7 @@ cont:
 ; CHECK: bl __cxa_end_catch
 lpad:
   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+          cleanup
           catch i8* bitcast (i8** @_ZTIi to i8*)
           catch i8* bitcast (i8** @_ZTId to i8*)
   %1 = extractvalue { i8*, i32 } %0, 0
@@ -110,13 +111,14 @@ Exit:
 ; CHECK: .long [[PRE_G]]-[[START]]
 ; CHECK: .long [[POST_G]]-[[PRE_G]]
 ; CHECK: .long [[LANDING]]-[[START]]
-; CHECK: .byte 3
+; CHECK: .byte 5
 ; CHECK: .long [[POST_G]]-[[START]]
 ; CHECK: .long [[END]]-[[POST_G]]
 ; CHECK: .long 0
 ; CHECK: .byte 0
-; CHECK: .byte 1
 ; CHECK: .byte 0
+; CHECK: .byte 1
+; CHECK: .byte 125
 ; CHECK: .byte 2
 ; CHECK: .byte 125
 ; CHECK: .long _ZTIi





More information about the llvm-commits mailing list