[llvm] r204388 - Remove LowerInvoke's obsolete "-enable-correct-eh-support" option

Mark Seaborn mseaborn at chromium.org
Thu Mar 20 12:54:48 PDT 2014


Author: mseaborn
Date: Thu Mar 20 14:54:47 2014
New Revision: 204388

URL: http://llvm.org/viewvc/llvm-project?rev=204388&view=rev
Log:
Remove LowerInvoke's obsolete "-enable-correct-eh-support" option

This option caused LowerInvoke to generate code using SJLJ-based
exception handling, but there is no code left that interprets the
jmp_buf stack that the resulting code maintained (llvm.sjljeh.jblist).
This option has been obsolete for a while, and replaced by
SjLjEHPrepare.

This leaves the default behaviour of LowerInvoke, which is to convert
invokes to calls.

Differential Revision: http://llvm-reviews.chandlerc.com/D3136

Removed:
    llvm/trunk/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll
    llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll
    llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll
    llvm/trunk/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll
    llvm/trunk/test/Transforms/LowerInvoke/basictest.ll
Modified:
    llvm/trunk/docs/CommandGuide/llc.rst
    llvm/trunk/docs/CommandGuide/lli.rst
    llvm/trunk/docs/Passes.rst
    llvm/trunk/include/llvm/Transforms/Scalar.h
    llvm/trunk/lib/CodeGen/Passes.cpp
    llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp

Modified: llvm/trunk/docs/CommandGuide/llc.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llc.rst?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llc.rst (original)
+++ llvm/trunk/docs/CommandGuide/llc.rst Thu Mar 20 14:54:47 2014
@@ -112,11 +112,6 @@ End-user Options
  optimizations allow the code generator to make use of some instructions which
  would otherwise not be usable (such as ``fsin`` on X86).
 
-.. option:: --enable-correct-eh-support
-
- Instruct the **lowerinvoke** pass to insert code for correct exception
- handling support.  This is expensive and is by default omitted for efficiency.
-
 .. option:: --stats
 
  Print statistics recorded by code-generation passes.

Modified: llvm/trunk/docs/CommandGuide/lli.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/lli.rst?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/lli.rst (original)
+++ llvm/trunk/docs/CommandGuide/lli.rst Thu Mar 20 14:54:47 2014
@@ -190,12 +190,6 @@ CODE GENERATION OPTIONS
 
 
 
-**-enable-correct-eh-support**
-
- Make the -lowerinvoke pass insert expensive, but correct, EH code.
-
-
-
 **-jit-enable-eh**
 
  Exception handling should be enabled in the just-in-time compiler.

Modified: llvm/trunk/docs/Passes.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Passes.rst?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/docs/Passes.rst (original)
+++ llvm/trunk/docs/Passes.rst Thu Mar 20 14:54:47 2014
@@ -893,33 +893,14 @@ this would require knowledge of the enti
 any libraries which may not be available in bitcode form); it simply lowers
 every atomic intrinsic.
 
-``-lowerinvoke``: Lower invoke and unwind, for unwindless code generators
--------------------------------------------------------------------------
+``-lowerinvoke``: Lower invokes to calls, for unwindless code generators
+------------------------------------------------------------------------
 
 This transformation is designed for use by code generators which do not yet
-support stack unwinding.  This pass supports two models of exception handling
-lowering, the "cheap" support and the "expensive" support.
-
-"Cheap" exception handling support gives the program the ability to execute any
-program which does not "throw an exception", by turning "``invoke``"
-instructions into calls and by turning "``unwind``" instructions into calls to
-``abort()``.  If the program does dynamically use the "``unwind``" instruction,
-the program will print a message then abort.
-
-"Expensive" exception handling support gives the full exception handling
-support to the program at the cost of making the "``invoke``" instruction
-really expensive.  It basically inserts ``setjmp``/``longjmp`` calls to emulate
-the exception handling as necessary.
-
-Because the "expensive" support slows down programs a lot, and EH is only used
-for a subset of the programs, it must be specifically enabled by the
-``-enable-correct-eh-support`` option.
-
-Note that after this pass runs the CFG is not entirely accurate (exceptional
-control flow edges are not correct anymore) so only very simple things should
-be done after the ``lowerinvoke`` pass has run (like generation of native
-code).  This should not be used as a general purpose "my LLVM-to-LLVM pass
-doesn't support the ``invoke`` instruction yet" lowering pass.
+support stack unwinding.  This pass converts ``invoke`` instructions to
+``call`` instructions, so that any exception-handling ``landingpad`` blocks
+become dead code (which can be removed by running the ``-simplifycfg`` pass
+afterwards).
 
 ``-lowerswitch``: Lower ``SwitchInst``\ s to branches
 -----------------------------------------------------

Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar.h Thu Mar 20 14:54:47 2014
@@ -262,16 +262,10 @@ extern char &LowerSwitchID;
 
 //===----------------------------------------------------------------------===//
 //
-// LowerInvoke - This pass converts invoke and unwind instructions to use sjlj
-// exception handling mechanisms.  Note that after this pass runs the CFG is not
-// entirely accurate (exceptional control flow edges are not correct anymore) so
-// only very simple things should be done after the lowerinvoke pass has run
-// (like generation of native code).  This should *NOT* be used as a general
-// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet"
-// lowering pass.
+// LowerInvoke - This pass removes invoke instructions, converting them to call
+// instructions.
 //
-FunctionPass *createLowerInvokePass(const TargetMachine *TM = 0,
-                                    bool useExpensiveEHSupport = false);
+FunctionPass *createLowerInvokePass();
 extern char &LowerInvokePassID;
 
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/lib/CodeGen/Passes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Passes.cpp?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/Passes.cpp (original)
+++ llvm/trunk/lib/CodeGen/Passes.cpp Thu Mar 20 14:54:47 2014
@@ -423,7 +423,7 @@ void TargetPassConfig::addPassesToHandle
     addPass(createDwarfEHPass(TM));
     break;
   case ExceptionHandling::None:
-    addPass(createLowerInvokePass(TM));
+    addPass(createLowerInvokePass());
 
     // The lower invoke pass may create unreachable code. Remove it.
     addPass(createUnreachableBlockEliminationPass());

Modified: llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp?rev=204388&r1=204387&r2=204388&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Thu Mar 20 14:54:47 2014
@@ -1,4 +1,4 @@
-//===- LowerInvoke.cpp - Eliminate Invoke & Unwind instructions -----------===//
+//===- LowerInvoke.cpp - Eliminate Invoke instructions --------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -8,29 +8,9 @@
 //===----------------------------------------------------------------------===//
 //
 // This transformation is designed for use by code generators which do not yet
-// support stack unwinding.  This pass supports two models of exception handling
-// lowering, the 'cheap' support and the 'expensive' support.
-//
-// 'Cheap' exception handling support gives the program the ability to execute
-// any program which does not "throw an exception", by turning 'invoke'
-// instructions into calls and by turning 'unwind' instructions into calls to
-// abort().  If the program does dynamically use the unwind instruction, the
-// program will print a message then abort.
-//
-// 'Expensive' exception handling support gives the full exception handling
-// support to the program at the cost of making the 'invoke' instruction
-// really expensive.  It basically inserts setjmp/longjmp calls to emulate the
-// exception handling as necessary.
-//
-// Because the 'expensive' support slows down programs a lot, and EH is only
-// used for a subset of the programs, it must be specifically enabled by an
-// option.
-//
-// Note that after this pass runs the CFG is not entirely accurate (exceptional
-// control flow edges are not correct anymore) so only very simple things should
-// be done after the lowerinvoke pass has run (like generation of native code).
-// This should not be used as a general purpose "my LLVM-to-LLVM pass doesn't
-// support the invoke instruction yet" lowering pass.
+// support stack unwinding.  This pass converts 'invoke' instructions to 'call'
+// instructions, so that any exception-handling 'landingpad' blocks become dead
+// code (which can be removed by running the '-simplifycfg' pass afterwards).
 //
 //===----------------------------------------------------------------------===//
 
@@ -38,64 +18,23 @@
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Instructions.h"
-#include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include <csetjmp>
-#include <set>
 using namespace llvm;
 
 STATISTIC(NumInvokes, "Number of invokes replaced");
-STATISTIC(NumSpilled, "Number of registers live across unwind edges");
-
-static cl::opt<bool> ExpensiveEHSupport("enable-correct-eh-support",
- cl::desc("Make the -lowerinvoke pass insert expensive, but correct, EH code"));
 
 namespace {
   class LowerInvoke : public FunctionPass {
-    const TargetMachine *TM;
-
-    // Used for both models.
-    Constant *AbortFn;
-
-    // Used for expensive EH support.
-    StructType *JBLinkTy;
-    GlobalVariable *JBListHead;
-    Constant *SetJmpFn, *LongJmpFn, *StackSaveFn, *StackRestoreFn;
-    bool useExpensiveEHSupport;
-
   public:
     static char ID; // Pass identification, replacement for typeid
-    explicit LowerInvoke(const TargetMachine *TM = 0,
-                         bool useExpensiveEHSupport = ExpensiveEHSupport)
-      : FunctionPass(ID), TM(TM),
-        useExpensiveEHSupport(useExpensiveEHSupport) {
+    explicit LowerInvoke() : FunctionPass(ID) {
       initializeLowerInvokePass(*PassRegistry::getPassRegistry());
     }
-    bool doInitialization(Module &M) override;
     bool runOnFunction(Function &F) override;
-
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      // This is a cluster of orthogonal Transforms
-      AU.addPreserved("mem2reg");
-      AU.addPreservedID(LowerSwitchID);
-    }
-
-  private:
-    bool insertCheapEHSupport(Function &F);
-    void splitLiveRangesLiveAcrossInvokes(SmallVectorImpl<InvokeInst*>&Invokes);
-    void rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
-                                AllocaInst *InvokeNum, AllocaInst *StackPtr,
-                                SwitchInst *CatchSwitch);
-    bool insertExpensiveEHSupport(Function &F);
   };
 }
 
@@ -107,65 +46,11 @@ INITIALIZE_PASS(LowerInvoke, "lowerinvok
 char &llvm::LowerInvokePassID = LowerInvoke::ID;
 
 // Public Interface To the LowerInvoke pass.
-FunctionPass *llvm::createLowerInvokePass(const TargetMachine *TM,
-                                          bool useExpensiveEHSupport) {
-  return new LowerInvoke(TM, useExpensiveEHSupport || ExpensiveEHSupport);
+FunctionPass *llvm::createLowerInvokePass() {
+  return new LowerInvoke();
 }
 
-// doInitialization - Make sure that there is a prototype for abort in the
-// current module.
-bool LowerInvoke::doInitialization(Module &M) {
-  Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
-  if (useExpensiveEHSupport) {
-    // Insert a type for the linked list of jump buffers.
-    const TargetLowering *TLI = TM ? TM->getTargetLowering() : 0;
-    unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0;
-    JBSize = JBSize ? JBSize : 200;
-    Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
-
-    JBLinkTy = StructType::create(M.getContext(), "llvm.sjljeh.jmpbufty");
-    Type *Elts[] = { JmpBufTy, PointerType::getUnqual(JBLinkTy) };
-    JBLinkTy->setBody(Elts);
-
-    Type *PtrJBList = PointerType::getUnqual(JBLinkTy);
-
-    // Now that we've done that, insert the jmpbuf list head global, unless it
-    // already exists.
-    if (!(JBListHead = M.getGlobalVariable("llvm.sjljeh.jblist", PtrJBList))) {
-      JBListHead = new GlobalVariable(M, PtrJBList, false,
-                                      GlobalValue::LinkOnceAnyLinkage,
-                                      Constant::getNullValue(PtrJBList),
-                                      "llvm.sjljeh.jblist");
-    }
-
-// VisualStudio defines setjmp as _setjmp
-#if defined(_MSC_VER) && defined(setjmp) && \
-                         !defined(setjmp_undefined_for_msvc)
-#  pragma push_macro("setjmp")
-#  undef setjmp
-#  define setjmp_undefined_for_msvc
-#endif
-
-    SetJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::setjmp);
-
-#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)
-   // let's return it to _setjmp state
-#  pragma pop_macro("setjmp")
-#  undef setjmp_undefined_for_msvc
-#endif
-
-    LongJmpFn = Intrinsic::getDeclaration(&M, Intrinsic::longjmp);
-    StackSaveFn = Intrinsic::getDeclaration(&M, Intrinsic::stacksave);
-    StackRestoreFn = Intrinsic::getDeclaration(&M, Intrinsic::stackrestore);
-  }
-
-  // We need the 'write' and 'abort' functions for both models.
-  AbortFn = M.getOrInsertFunction("abort", Type::getVoidTy(M.getContext()),
-                                  (Type *)0);
-  return true;
-}
-
-bool LowerInvoke::insertCheapEHSupport(Function &F) {
+bool LowerInvoke::runOnFunction(Function &F) {
   bool Changed = false;
   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
     if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
@@ -192,387 +77,3 @@ bool LowerInvoke::insertCheapEHSupport(F
     }
   return Changed;
 }
-
-/// rewriteExpensiveInvoke - Insert code and hack the function to replace the
-/// specified invoke instruction with a call.
-void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo,
-                                         AllocaInst *InvokeNum,
-                                         AllocaInst *StackPtr,
-                                         SwitchInst *CatchSwitch) {
-  ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()),
-                                            InvokeNo);
-
-  // If the unwind edge has phi nodes, split the edge.
-  if (isa<PHINode>(II->getUnwindDest()->begin())) {
-    SplitCriticalEdge(II, 1, this);
-
-    // If there are any phi nodes left, they must have a single predecessor.
-    while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) {
-      PN->replaceAllUsesWith(PN->getIncomingValue(0));
-      PN->eraseFromParent();
-    }
-  }
-
-  // Insert a store of the invoke num before the invoke and store zero into the
-  // location afterward.
-  new StoreInst(InvokeNoC, InvokeNum, true, II);  // volatile
-  
-  // Insert a store of the stack ptr before the invoke, so we can restore it
-  // later in the exception case.
-  CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II);
-  new StoreInst(StackSaveRet, StackPtr, true, II); // volatile
-
-  BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt();
-  // nonvolatile.
-  new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), 
-                InvokeNum, false, NI);
-
-  Instruction* StackPtrLoad =
-    new LoadInst(StackPtr, "stackptr.restore", true,
-                 II->getUnwindDest()->getFirstInsertionPt());
-  CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad);
-    
-  // Add a switch case to our unwind block.
-  CatchSwitch->addCase(InvokeNoC, II->getUnwindDest());
-
-  // Insert a normal call instruction.
-  SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
-  CallInst *NewCall = CallInst::Create(II->getCalledValue(),
-                                       CallArgs, "", II);
-  NewCall->takeName(II);
-  NewCall->setCallingConv(II->getCallingConv());
-  NewCall->setAttributes(II->getAttributes());
-  NewCall->setDebugLoc(II->getDebugLoc());
-  II->replaceAllUsesWith(NewCall);
-
-  // Replace the invoke with an uncond branch.
-  BranchInst::Create(II->getNormalDest(), NewCall->getParent());
-  II->eraseFromParent();
-}
-
-/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until
-/// we reach blocks we've already seen.
-static void MarkBlocksLiveIn(BasicBlock *BB, std::set<BasicBlock*> &LiveBBs) {
-  if (!LiveBBs.insert(BB).second) return; // already been here.
-
-  for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
-    MarkBlocksLiveIn(*PI, LiveBBs);
-}
-
-// First thing we need to do is scan the whole function for values that are
-// live across unwind edges.  Each value that is live across an unwind edge
-// we spill into a stack location, guaranteeing that there is nothing live
-// across the unwind edge.  This process also splits all critical edges
-// coming out of invoke's.
-void LowerInvoke::
-splitLiveRangesLiveAcrossInvokes(SmallVectorImpl<InvokeInst*> &Invokes) {
-  // First step, split all critical edges from invoke instructions.
-  for (unsigned i = 0, e = Invokes.size(); i != e; ++i) {
-    InvokeInst *II = Invokes[i];
-    SplitCriticalEdge(II, 0, this);
-    SplitCriticalEdge(II, 1, this);
-    assert(!isa<PHINode>(II->getNormalDest()) &&
-           !isa<PHINode>(II->getUnwindDest()) &&
-           "critical edge splitting left single entry phi nodes?");
-  }
-
-  Function *F = Invokes.back()->getParent()->getParent();
-
-  // To avoid having to handle incoming arguments specially, we lower each arg
-  // to a copy instruction in the entry block.  This ensures that the argument
-  // value itself cannot be live across the entry block.
-  BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin();
-  while (isa<AllocaInst>(AfterAllocaInsertPt) &&
-        isa<ConstantInt>(cast<AllocaInst>(AfterAllocaInsertPt)->getArraySize()))
-    ++AfterAllocaInsertPt;
-  for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end();
-       AI != E; ++AI) {
-    Type *Ty = AI->getType();
-    // Aggregate types can't be cast, but are legal argument types, so we have
-    // to handle them differently. We use an extract/insert pair as a
-    // lightweight method to achieve the same goal.
-    if (isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) {
-      Instruction *EI = ExtractValueInst::Create(AI, 0, "",AfterAllocaInsertPt);
-      Instruction *NI = InsertValueInst::Create(AI, EI, 0);
-      NI->insertAfter(EI);
-      AI->replaceAllUsesWith(NI);
-      // Set the operand of the instructions back to the AllocaInst.
-      EI->setOperand(0, AI);
-      NI->setOperand(0, AI);
-    } else {
-      // This is always a no-op cast because we're casting AI to AI->getType()
-      // so src and destination types are identical. BitCast is the only
-      // possibility.
-      CastInst *NC = new BitCastInst(
-        AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt);
-      AI->replaceAllUsesWith(NC);
-      // Set the operand of the cast instruction back to the AllocaInst.
-      // Normally it's forbidden to replace a CastInst's operand because it
-      // could cause the opcode to reflect an illegal conversion. However,
-      // we're replacing it here with the same value it was constructed with.
-      // We do this because the above replaceAllUsesWith() clobbered the
-      // operand, but we want this one to remain.
-      NC->setOperand(0, AI);
-    }
-  }
-
-  // Finally, scan the code looking for instructions with bad live ranges.
-  for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
-    for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
-      // Ignore obvious cases we don't have to handle.  In particular, most
-      // instructions either have no uses or only have a single use inside the
-      // current block.  Ignore them quickly.
-      Instruction *Inst = II;
-      if (Inst->use_empty()) continue;
-      if (Inst->hasOneUse() &&
-          cast<Instruction>(Inst->user_back())->getParent() == BB &&
-          !isa<PHINode>(Inst->user_back())) continue;
-
-      // If this is an alloca in the entry block, it's not a real register
-      // value.
-      if (AllocaInst *AI = dyn_cast<AllocaInst>(Inst))
-        if (isa<ConstantInt>(AI->getArraySize()) && BB == F->begin())
-          continue;
-
-      // Avoid iterator invalidation by copying users to a temporary vector.
-      SmallVector<Instruction*,16> Users;
-      for (User *U : Inst->users()) {
-        Instruction *UI = cast<Instruction>(U);
-        if (UI->getParent() != BB || isa<PHINode>(UI))
-          Users.push_back(UI);
-      }
-
-      // Scan all of the uses and see if the live range is live across an unwind
-      // edge.  If we find a use live across an invoke edge, create an alloca
-      // and spill the value.
-
-      // Find all of the blocks that this value is live in.
-      std::set<BasicBlock*> LiveBBs;
-      LiveBBs.insert(Inst->getParent());
-      while (!Users.empty()) {
-        Instruction *U = Users.back();
-        Users.pop_back();
-
-        if (!isa<PHINode>(U)) {
-          MarkBlocksLiveIn(U->getParent(), LiveBBs);
-        } else {
-          // Uses for a PHI node occur in their predecessor block.
-          PHINode *PN = cast<PHINode>(U);
-          for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
-            if (PN->getIncomingValue(i) == Inst)
-              MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs);
-        }
-      }
-
-      // Now that we know all of the blocks that this thing is live in, see if
-      // it includes any of the unwind locations.
-      bool NeedsSpill = false;
-      for (unsigned i = 0, e = Invokes.size(); i != e; ++i) {
-        BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest();
-        if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) {
-          NeedsSpill = true;
-        }
-      }
-
-      // If we decided we need a spill, do it.
-      if (NeedsSpill) {
-        ++NumSpilled;
-        DemoteRegToStack(*Inst, true);
-      }
-    }
-}
-
-bool LowerInvoke::insertExpensiveEHSupport(Function &F) {
-  SmallVector<ReturnInst*,16> Returns;
-  SmallVector<InvokeInst*,16> Invokes;
-  UnreachableInst* UnreachablePlaceholder = 0;
-
-  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
-    if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
-      // Remember all return instructions in case we insert an invoke into this
-      // function.
-      Returns.push_back(RI);
-    } else if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
-      Invokes.push_back(II);
-    }
-
-  if (Invokes.empty()) return false;
-
-  NumInvokes += Invokes.size();
-
-  // TODO: This is not an optimal way to do this.  In particular, this always
-  // inserts setjmp calls into the entries of functions with invoke instructions
-  // even though there are possibly paths through the function that do not
-  // execute any invokes.  In particular, for functions with early exits, e.g.
-  // the 'addMove' method in hexxagon, it would be nice to not have to do the
-  // setjmp stuff on the early exit path.  This requires a bit of dataflow, but
-  // would not be too hard to do.
-
-  // If we have an invoke instruction, insert a setjmp that dominates all
-  // invokes.  After the setjmp, use a cond branch that goes to the original
-  // code path on zero, and to a designated 'catch' block of nonzero.
-  Value *OldJmpBufPtr = 0;
-  if (!Invokes.empty()) {
-    // First thing we need to do is scan the whole function for values that are
-    // live across unwind edges.  Each value that is live across an unwind edge
-    // we spill into a stack location, guaranteeing that there is nothing live
-    // across the unwind edge.  This process also splits all critical edges
-    // coming out of invoke's.
-    splitLiveRangesLiveAcrossInvokes(Invokes);
-
-    BasicBlock *EntryBB = F.begin();
-
-    // Create an alloca for the incoming jump buffer ptr and the new jump buffer
-    // that needs to be restored on all exits from the function.  This is an
-    // alloca because the value needs to be live across invokes.
-    const TargetLowering *TLI = TM ? TM->getTargetLowering() : 0;
-    unsigned Align = TLI ? TLI->getJumpBufAlignment() : 0;
-    AllocaInst *JmpBuf =
-      new AllocaInst(JBLinkTy, 0, Align,
-                     "jblink", F.begin()->begin());
-
-    Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())),
-                     ConstantInt::get(Type::getInt32Ty(F.getContext()), 1) };
-    OldJmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "OldBuf",
-                                             EntryBB->getTerminator());
-
-    // Copy the JBListHead to the alloca.
-    Value *OldBuf = new LoadInst(JBListHead, "oldjmpbufptr", true,
-                                 EntryBB->getTerminator());
-    new StoreInst(OldBuf, OldJmpBufPtr, true, EntryBB->getTerminator());
-
-    // Add the new jumpbuf to the list.
-    new StoreInst(JmpBuf, JBListHead, true, EntryBB->getTerminator());
-
-    // Create the catch block.  The catch block is basically a big switch
-    // statement that goes to all of the invoke catch blocks.
-    BasicBlock *CatchBB =
-            BasicBlock::Create(F.getContext(), "setjmp.catch", &F);
-
-    // Create an alloca which keeps track of the stack pointer before every
-    // invoke, this allows us to properly restore the stack pointer after
-    // long jumping.
-    AllocaInst *StackPtr = new AllocaInst(Type::getInt8PtrTy(F.getContext()), 0,
-                                          "stackptr", EntryBB->begin());
-
-    // Create an alloca which keeps track of which invoke is currently
-    // executing.  For normal calls it contains zero.
-    AllocaInst *InvokeNum = new AllocaInst(Type::getInt32Ty(F.getContext()), 0,
-                                           "invokenum",EntryBB->begin());
-    new StoreInst(ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), 
-                  InvokeNum, true, EntryBB->getTerminator());
-
-    // Insert a load in the Catch block, and a switch on its value.  By default,
-    // we go to a block that just does an unwind (which is the correct action
-    // for a standard call). We insert an unreachable instruction here and
-    // modify the block to jump to the correct unwinding pad later.
-    BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F);
-    UnreachablePlaceholder = new UnreachableInst(F.getContext(), UnwindBB);
-
-    Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB);
-    SwitchInst *CatchSwitch =
-      SwitchInst::Create(CatchLoad, UnwindBB, Invokes.size(), CatchBB);
-
-    // Now that things are set up, insert the setjmp call itself.
-
-    // Split the entry block to insert the conditional branch for the setjmp.
-    BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(),
-                                                     "setjmp.cont");
-
-    Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 0);
-    Value *JmpBufPtr = GetElementPtrInst::Create(JmpBuf, Idx, "TheJmpBuf",
-                                                 EntryBB->getTerminator());
-    JmpBufPtr = new BitCastInst(JmpBufPtr,
-                        Type::getInt8PtrTy(F.getContext()),
-                                "tmp", EntryBB->getTerminator());
-    Value *SJRet = CallInst::Create(SetJmpFn, JmpBufPtr, "sjret",
-                                    EntryBB->getTerminator());
-
-    // Compare the return value to zero.
-    Value *IsNormal = new ICmpInst(EntryBB->getTerminator(),
-                                   ICmpInst::ICMP_EQ, SJRet,
-                                   Constant::getNullValue(SJRet->getType()),
-                                   "notunwind");
-    // Nuke the uncond branch.
-    EntryBB->getTerminator()->eraseFromParent();
-
-    // Put in a new condbranch in its place.
-    BranchInst::Create(ContBlock, CatchBB, IsNormal, EntryBB);
-
-    // At this point, we are all set up, rewrite each invoke instruction.
-    for (unsigned i = 0, e = Invokes.size(); i != e; ++i)
-      rewriteExpensiveInvoke(Invokes[i], i+1, InvokeNum, StackPtr, CatchSwitch);
-  }
-
-  // We know that there is at least one unwind.
-
-  // Create three new blocks, the block to load the jmpbuf ptr and compare
-  // against null, the block to do the longjmp, and the error block for if it
-  // is null.  Add them at the end of the function because they are not hot.
-  BasicBlock *UnwindHandler = BasicBlock::Create(F.getContext(),
-                                                "dounwind", &F);
-  BasicBlock *UnwindBlock = BasicBlock::Create(F.getContext(), "unwind", &F);
-  BasicBlock *TermBlock = BasicBlock::Create(F.getContext(), "unwinderror", &F);
-
-  // If this function contains an invoke, restore the old jumpbuf ptr.
-  Value *BufPtr;
-  if (OldJmpBufPtr) {
-    // Before the return, insert a copy from the saved value to the new value.
-    BufPtr = new LoadInst(OldJmpBufPtr, "oldjmpbufptr", UnwindHandler);
-    new StoreInst(BufPtr, JBListHead, UnwindHandler);
-  } else {
-    BufPtr = new LoadInst(JBListHead, "ehlist", UnwindHandler);
-  }
-
-  // Load the JBList, if it's null, then there was no catch!
-  Value *NotNull = new ICmpInst(*UnwindHandler, ICmpInst::ICMP_NE, BufPtr,
-                                Constant::getNullValue(BufPtr->getType()),
-                                "notnull");
-  BranchInst::Create(UnwindBlock, TermBlock, NotNull, UnwindHandler);
-
-  // Create the block to do the longjmp.
-  // Get a pointer to the jmpbuf and longjmp.
-  Value *Idx[] = { Constant::getNullValue(Type::getInt32Ty(F.getContext())),
-                   ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) };
-  Idx[0] = GetElementPtrInst::Create(BufPtr, Idx, "JmpBuf", UnwindBlock);
-  Idx[0] = new BitCastInst(Idx[0],
-             Type::getInt8PtrTy(F.getContext()),
-                           "tmp", UnwindBlock);
-  Idx[1] = ConstantInt::get(Type::getInt32Ty(F.getContext()), 1);
-  CallInst::Create(LongJmpFn, Idx, "", UnwindBlock);
-  new UnreachableInst(F.getContext(), UnwindBlock);
-
-  // Set up the term block ("throw without a catch").
-  new UnreachableInst(F.getContext(), TermBlock);
-
-  // Insert a call to abort()
-  CallInst::Create(AbortFn, "",
-                   TermBlock->getTerminator())->setTailCall();
-
-  // Replace the inserted unreachable with a branch to the unwind handler.
-  if (UnreachablePlaceholder) {
-    BranchInst::Create(UnwindHandler, UnreachablePlaceholder);
-    UnreachablePlaceholder->eraseFromParent();
-  }
-
-  // Finally, for any returns from this function, if this function contains an
-  // invoke, restore the old jmpbuf pointer to its input value.
-  if (OldJmpBufPtr) {
-    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
-      ReturnInst *R = Returns[i];
-
-      // Before the return, insert a copy from the saved value to the new value.
-      Value *OldBuf = new LoadInst(OldJmpBufPtr, "oldjmpbufptr", true, R);
-      new StoreInst(OldBuf, JBListHead, true, R);
-    }
-  }
-
-  return true;
-}
-
-bool LowerInvoke::runOnFunction(Function &F) {
-  if (useExpensiveEHSupport)
-    return insertExpensiveEHSupport(F);
-  else
-    return insertCheapEHSupport(F);
-}

Removed: llvm/trunk/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll?rev=204387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll (original)
+++ llvm/trunk/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll (removed)
@@ -1,15 +0,0 @@
-; RUN: opt < %s -lowerinvoke -enable-correct-eh-support -disable-output
-
-define void @_ZNKSt11__use_cacheISt16__numpunct_cacheIcEEclERKSt6locale() {
-entry:
-	br i1 false, label %then, label %UnifiedReturnBlock
-then:		; preds = %entry
-	invoke void @_Znwj( )
-			to label %UnifiedReturnBlock unwind label %UnifiedReturnBlock
-UnifiedReturnBlock:		; preds = %then, %then, %entry
-	%UnifiedRetVal = phi i32* [ null, %entry ], [ null, %then ], [ null, %then ] ; <i32*> [#uses=0]
-	ret void
-}
-
-declare void @_Znwj()
-

Removed: llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll?rev=204387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll (original)
+++ llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll (removed)
@@ -1,17 +0,0 @@
-; RUN: opt < %s -lowerinvoke -enable-correct-eh-support -disable-output
-
-declare void @ll_listnext__listiterPtr()
-
-define void @WorkTask.fn() {
-block0:
-	invoke void @ll_listnext__listiterPtr( )
-			to label %block9 unwind label %block8_exception_handling
-block8_exception_handling:		; preds = %block0
-	ret void
-block9:		; preds = %block0
-	%w_2690 = phi { i32, i32 }* [ null, %block0 ]		; <{ i32, i32 }*> [#uses=1]
-	%tmp.129 = getelementptr { i32, i32 }* %w_2690, i32 0, i32 1		; <i32*> [#uses=1]
-	%v2769 = load i32* %tmp.129		; <i32> [#uses=0]
-	ret void
-}
-

Removed: llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll?rev=204387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll (original)
+++ llvm/trunk/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll (removed)
@@ -1,15 +0,0 @@
-; RUN: opt < %s -lowerinvoke -enable-correct-eh-support -disable-output
-
-declare fastcc i32 @ll_listnext__listiterPtr()
-
-define fastcc i32 @WorkTask.fn() {
-block0:
-	%v2679 = invoke fastcc i32 @ll_listnext__listiterPtr( )
-			to label %block9 unwind label %block8_exception_handling	; <i32> [#uses=1]
-block8_exception_handling:		; preds = %block0
-	ret i32 0
-block9:		; preds = %block0
-	%i_2689 = phi i32 [ %v2679, %block0 ]		; <i32> [#uses=1]
-	ret i32 %i_2689
-}
-

Removed: llvm/trunk/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll?rev=204387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll (original)
+++ llvm/trunk/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll (removed)
@@ -1,14 +0,0 @@
-; RUN: opt < %s -lowerinvoke -enable-correct-eh-support -disable-output
-; PR2029
-define i32 @main(i32 %argc, i8** %argv) {
-bb470:
-        invoke i32 @main(i32 0, i8** null) to label %invcont474 unwind label
-%lpad902
-
-invcont474:             ; preds = %bb470
-        ret i32 0
-
-lpad902:                ; preds = %bb470
-        %tmp471.lcssa = phi i8* [ null, %bb470 ]                ; <i8*>
-        ret i32 0
-}

Removed: llvm/trunk/test/Transforms/LowerInvoke/basictest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerInvoke/basictest.ll?rev=204387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerInvoke/basictest.ll (original)
+++ llvm/trunk/test/Transforms/LowerInvoke/basictest.ll (removed)
@@ -1,30 +0,0 @@
-; RUN: opt < %s -lowerinvoke -disable-output -enable-correct-eh-support
-
-
-define i32 @foo() {
-	invoke i32 @foo( )
-			to label %Ok unwind label %Crap		; <i32>:1 [#uses=0]
-Ok:		; preds = %0
-	invoke i32 @foo( )
-			to label %Ok2 unwind label %Crap		; <i32>:2 [#uses=0]
-Ok2:		; preds = %Ok
-	ret i32 2
-Crap:		; preds = %Ok, %0
-	ret i32 1
-}
-
-define i32 @bar(i32 %blah) {
-	br label %doit
-doit:		; preds = %0
-        ;; Value live across an unwind edge.
-	%B2 = add i32 %blah, 1		; <i32> [#uses=1]
-	invoke i32 @foo( )
-			to label %Ok unwind label %Crap		; <i32>:1 [#uses=0]
-Ok:		; preds = %doit
-	invoke i32 @foo( )
-			to label %Ok2 unwind label %Crap		; <i32>:2 [#uses=0]
-Ok2:		; preds = %Ok
-	ret i32 2
-Crap:		; preds = %Ok, %doit
-	ret i32 %B2
-}





More information about the llvm-commits mailing list