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

Chandler Carruth chandlerc at google.com
Thu Feb 19 18:18:22 PST 2015


Reverted in r229952, didn't pass 'ninja check' on linux for me. Let me know
if this doesn't reproduce easily, but I think it will. Lots of stack traces
that look like heap corruption.

On Thu, Feb 19, 2015 at 5:00 PM, Reid Kleckner <reid at kleckner.net> wrote:

> 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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150219/06041b47/attachment.html>


More information about the llvm-commits mailing list