X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSjLjEHPrepare.cpp;h=7f46a062fa7b8ab1252bbb9a12af7d8c39f428b3;hb=a4b5050cf5af18ac18565073fecbfcb95f93556b;hp=5ac0c09ded9990c9dac8987eadf1c7d4df839371;hpb=30442f95573d7e0f505c573bd7462b77769010fa;p=oota-llvm.git diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp index 5ac0c09ded9..7f46a062fa7 100644 --- a/lib/CodeGen/SjLjEHPrepare.cpp +++ b/lib/CodeGen/SjLjEHPrepare.cpp @@ -13,29 +13,28 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sjljehprepare" -#include "llvm/Transforms/Scalar.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/IRBuilder.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/IRBuilder.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include using namespace llvm; @@ -45,7 +44,6 @@ STATISTIC(NumSpilled, "Number of registers live across unwind edges"); namespace { class SjLjEHPrepare : public FunctionPass { const TargetLowering *TLI; - Type *FunctionContextTy; Constant *RegisterFn; Constant *UnregisterFn; @@ -61,13 +59,11 @@ namespace { public: static char ID; // Pass identification, replacement for typeid explicit SjLjEHPrepare(const TargetLowering *tli = NULL) - : FunctionPass(ID), TLI(tli) {} + : FunctionPass(ID), TLI(tli) { } bool doInitialization(Module &M); bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - FunctionPass::getAnalysisUsage(AU); - } + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} const char *getPassName() const { return "SJLJ Exception Handling preparation"; } @@ -143,26 +139,14 @@ void SjLjEHPrepare::insertCallSiteStore(Instruction *I, int Number) { Builder.CreateStore(CallSiteNoC, CallSite, true/*volatile*/); } -/// markBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until +/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until /// we reach blocks we've already seen. -static void markBlocksLiveIn(BasicBlock *BB, Instruction *Inst, - SmallPtrSet &LiveBBs, - SmallPtrSet &InvokesCrossed, - bool &FoundDef) { - if (!LiveBBs.insert(BB)) return; // Already been here. - if (BB == Inst->getParent()) { - FoundDef = true; - return; - } +static void MarkBlocksLiveIn(BasicBlock *BB, + SmallPtrSet &LiveBBs) { + if (!LiveBBs.insert(BB)) return; // already been here. - for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { - BasicBlock *Pred = *PI; - if (BB->isLandingPad() && BB != Inst->getParent()) { - InvokesCrossed.insert(Pred); - continue; - } - markBlocksLiveIn(Pred, Inst, LiveBBs, InvokesCrossed, FoundDef); - } + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + MarkBlocksLiveIn(*PI, LiveBBs); } /// substituteLPadValues - Substitute the values returned by the landingpad @@ -212,53 +196,38 @@ setupFunctionContext(Function &F, ArrayRef LPads) { new AllocaInst(FunctionContextTy, 0, Align, "fn_context", EntryBB->begin()); // Fill in the function context structure. - Type *Int32Ty = Type::getInt32Ty(F.getContext()); - Value *Zero = ConstantInt::get(Int32Ty, 0); - Value *One = ConstantInt::get(Int32Ty, 1); - Value *Two = ConstantInt::get(Int32Ty, 2); - Value *Three = ConstantInt::get(Int32Ty, 3); - Value *Four = ConstantInt::get(Int32Ty, 4); - - Value *Idxs[2] = { Zero, 0 }; - for (unsigned I = 0, E = LPads.size(); I != E; ++I) { LandingPadInst *LPI = LPads[I]; IRBuilder<> Builder(LPI->getParent()->getFirstInsertionPt()); // Reference the __data field. - Idxs[1] = Two; - Value *FCData = Builder.CreateGEP(FuncCtx, Idxs, "__data"); + Value *FCData = Builder.CreateConstGEP2_32(FuncCtx, 0, 2, "__data"); // The exception values come back in context->__data[0]. - Idxs[1] = Zero; - Value *ExceptionAddr = Builder.CreateGEP(FCData, Idxs, "exception_gep"); + Value *ExceptionAddr = Builder.CreateConstGEP2_32(FCData, 0, 0, + "exception_gep"); Value *ExnVal = Builder.CreateLoad(ExceptionAddr, true, "exn_val"); - ExnVal = Builder.CreateIntToPtr(ExnVal, Type::getInt8PtrTy(F.getContext())); + ExnVal = Builder.CreateIntToPtr(ExnVal, Builder.getInt8PtrTy()); - Idxs[1] = One; - Value *SelectorAddr = Builder.CreateGEP(FCData, Idxs, "exn_selector_gep"); + Value *SelectorAddr = Builder.CreateConstGEP2_32(FCData, 0, 1, + "exn_selector_gep"); Value *SelVal = Builder.CreateLoad(SelectorAddr, true, "exn_selector_val"); substituteLPadValues(LPI, ExnVal, SelVal); } // Personality function - Idxs[1] = Three; + IRBuilder<> Builder(EntryBB->getTerminator()); if (!PersonalityFn) PersonalityFn = LPads[0]->getPersonalityFn(); - Value *PersonalityFieldPtr = - GetElementPtrInst::Create(FuncCtx, Idxs, "pers_fn_gep", - EntryBB->getTerminator()); - new StoreInst(PersonalityFn, PersonalityFieldPtr, true, - EntryBB->getTerminator()); + Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 3, + "pers_fn_gep"); + Builder.CreateStore(PersonalityFn, PersonalityFieldPtr, /*isVolatile=*/true); // LSDA address - Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", - EntryBB->getTerminator()); - Idxs[1] = Four; - Value *LSDAFieldPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "lsda_gep", - EntryBB->getTerminator()); - new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); + Value *LSDA = Builder.CreateCall(LSDAAddrFn, "lsda_addr"); + Value *LSDAFieldPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 4, "lsda_gep"); + Builder.CreateStore(LSDA, LSDAFieldPtr, /*isVolatile=*/true); return FuncCtx; } @@ -313,9 +282,6 @@ void SjLjEHPrepare::lowerIncomingArguments(Function &F) { /// edge and spill them. void SjLjEHPrepare::lowerAcrossUnwindEdges(Function &F, ArrayRef Invokes) { - SmallVector, 32> ReloadUsers; - DenseMap, AllocaInst*> AllocaMap; - // Finally, scan the code looking for instructions with bad live ranges. for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) { @@ -346,118 +312,47 @@ void SjLjEHPrepare::lowerAcrossUnwindEdges(Function &F, } // Find all of the blocks that this value is live in. - std::map > InvokesCrossed; - std::map > LiveBBs; - bool FoundDef = false; + SmallPtrSet LiveBBs; + LiveBBs.insert(Inst->getParent()); while (!Users.empty()) { - Instruction *U = Users.pop_back_val(); + Instruction *U = Users.back(); + Users.pop_back(); - if (PHINode *PN = dyn_cast(U)) { + if (!isa(U)) { + MarkBlocksLiveIn(U->getParent(), LiveBBs); + } else { // Uses for a PHI node occur in their predecessor block. + PHINode *PN = cast(U); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == Inst) - markBlocksLiveIn(PN->getIncomingBlock(i), Inst, LiveBBs[U], - InvokesCrossed[U], FoundDef); - } else { - markBlocksLiveIn(U->getParent(), Inst, LiveBBs[U], - InvokesCrossed[U], FoundDef); + MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); } } - // If we hit the definition, resort to the dump-this-value-everywhere - // method. - if (FoundDef) { - // 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) continue; - - for (std::map >::iterator - MI = LiveBBs.begin(), ME = LiveBBs.end(); MI != ME; ++MI) { - if (MI->second.count(UnwindBlock)) { - DEBUG({ - dbgs() << "SJLJ Spill: " << *Inst << " around " - << UnwindBlock->getName() << "\n"; - }); - NeedsSpill = true; - break; - } - } - - // If we decided we need a spill, do it. - if (NeedsSpill) { - DemoteRegToStack(*Inst, true); - ++NumSpilled; - } + // 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)) { + DEBUG(dbgs() << "SJLJ Spill: " << *Inst << " around " + << UnwindBlock->getName() << "\n"); + NeedsSpill = true; + break; } - - // We don't need this map anymore. - InvokesCrossed.clear(); } - // Go through the invokes the value crosses and insert a spill right - // before the invoke. - for (std::map >::iterator - MI = InvokesCrossed.begin(), ME = InvokesCrossed.end(); - MI != ME; ++MI) { - Instruction *User = MI->first; - SmallPtrSet &Crossings = MI->second; - if (Crossings.empty()) continue; - - ReloadUsers.push_back(std::make_pair(Inst, User)); - - AllocaInst *&Slot = AllocaMap[std::make_pair(Inst, User)]; - if (!Slot) - Slot = new AllocaInst(Inst->getType(), 0, - Inst->getName() + ".reg2mem", - F.getEntryBlock().begin()); - - for (SmallPtrSet::iterator - CI = Crossings.begin(), CE = Crossings.end(); CI != CE; ++CI) { - new StoreInst(Inst, Slot, (*CI)->getTerminator()); - ++NumSpilled; - } + // If we decided we need a spill, do it. + // FIXME: Spilling this way is overkill, as it forces all uses of + // the value to be reloaded from the stack slot, even those that aren't + // in the unwind blocks. We should be more selective. + if (NeedsSpill) { + DemoteRegToStack(*Inst, true); + ++NumSpilled; } } } - // Now go through the instructions which were spilled and replace their uses - // after a crossed invoke with a reload instruction. - for (SmallVectorImpl >::iterator - I = ReloadUsers.begin(), E = ReloadUsers.end(); I != E; ++I) { - Instruction *User = I->second; - AllocaInst *Slot = AllocaMap[*I]; - assert(Slot && "A spill slot hasn't been allocated yet!"); - - if (PHINode *PN = dyn_cast(User)) { - // If this is a PHI node, we can't insert a load of the value before the - // use. Instead insert the load in the predecessor block corresponding to - // the incoming value. - // - // Note that if there are multiple edges from a basic block to this PHI - // node that we cannot have multiple loads. The problem is that the - // resulting PHI node will have multiple values (from each load) coming in - // from the same block, which is illegal SSA form. For this reason, we - // keep track of and reuse loads we insert. - DenseMap Loads; - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) - if (PN->getIncomingValue(i) == I->first) { - Value *&V = Loads[PN->getIncomingBlock(i)]; - if (V == 0) - // Insert the load into the predecessor block - V = new LoadInst(Slot, I->first->getName() + ".reload", true, - PN->getIncomingBlock(i)->getTerminator()); - - PN->setIncomingValue(i, V); - } - } else { - LoadInst *Reload = new LoadInst(Slot, Slot->getName() + ".reload", User); - User->replaceUsesOfWith(I->first, Reload); - } - } - // Go through the landing pads and remove any PHIs there. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); @@ -507,48 +402,31 @@ bool SjLjEHPrepare::setupEntryBlockAndCallSites(Function &F) { Value *FuncCtx = setupFunctionContext(F, makeArrayRef(LPads.begin(), LPads.end())); BasicBlock *EntryBB = F.begin(); - Type *Int32Ty = Type::getInt32Ty(F.getContext()); - - Value *Idxs[2] = { - ConstantInt::get(Int32Ty, 0), 0 - }; + IRBuilder<> Builder(EntryBB->getTerminator()); // Get a reference to the jump buffer. - Idxs[1] = ConstantInt::get(Int32Ty, 5); - Value *JBufPtr = GetElementPtrInst::Create(FuncCtx, Idxs, "jbuf_gep", - EntryBB->getTerminator()); + Value *JBufPtr = Builder.CreateConstGEP2_32(FuncCtx, 0, 5, "jbuf_gep"); // Save the frame pointer. - Idxs[1] = ConstantInt::get(Int32Ty, 0); - Value *FramePtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep", - EntryBB->getTerminator()); + Value *FramePtr = Builder.CreateConstGEP2_32(JBufPtr, 0, 0, "jbuf_fp_gep"); - Value *Val = CallInst::Create(FrameAddrFn, - ConstantInt::get(Int32Ty, 0), - "fp", - EntryBB->getTerminator()); - new StoreInst(Val, FramePtr, true, EntryBB->getTerminator()); + Value *Val = Builder.CreateCall(FrameAddrFn, Builder.getInt32(0), "fp"); + Builder.CreateStore(Val, FramePtr, /*isVolatile=*/true); // Save the stack pointer. - Idxs[1] = ConstantInt::get(Int32Ty, 2); - Value *StackPtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep", - EntryBB->getTerminator()); + Value *StackPtr = Builder.CreateConstGEP2_32(JBufPtr, 0, 2, "jbuf_sp_gep"); - Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); - new StoreInst(Val, StackPtr, true, EntryBB->getTerminator()); + Val = Builder.CreateCall(StackAddrFn, "sp"); + Builder.CreateStore(Val, StackPtr, /*isVolatile=*/true); // Call the setjmp instrinsic. It fills in the rest of the jmpbuf. - Value *SetjmpArg = CastInst::Create(Instruction::BitCast, JBufPtr, - Type::getInt8PtrTy(F.getContext()), "", - EntryBB->getTerminator()); - CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "", EntryBB->getTerminator()); + Value *SetjmpArg = Builder.CreateBitCast(JBufPtr, Builder.getInt8PtrTy()); + Builder.CreateCall(BuiltinSetjmpFn, SetjmpArg); // Store a pointer to the function context so that the back-end will know // where to look for it. - Value *FuncCtxArg = CastInst::Create(Instruction::BitCast, FuncCtx, - Type::getInt8PtrTy(F.getContext()), "", - EntryBB->getTerminator()); - CallInst::Create(FuncCtxFn, FuncCtxArg, "", EntryBB->getTerminator()); + Value *FuncCtxArg = Builder.CreateBitCast(FuncCtx, Builder.getInt8PtrTy()); + Builder.CreateCall(FuncCtxFn, FuncCtxArg); // At this point, we are all set up, update the invoke instructions to mark // their call_site values. @@ -611,9 +489,5 @@ bool SjLjEHPrepare::setupEntryBlockAndCallSites(Function &F) { bool SjLjEHPrepare::runOnFunction(Function &F) { bool Res = setupEntryBlockAndCallSites(F); - DEBUG({ - if (verifyFunction(F)) - report_fatal_error("verifyFunction failed!"); - }); return Res; }