[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