Index: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp =================================================================== --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +++ llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -33,10 +33,11 @@ AllocaInst *Slot; if (AllocaPoint) { Slot = new AllocaInst(I.getType(), DL.getAllocaAddrSpace(), nullptr, - I.getName()+".reg2mem", AllocaPoint); + I.getName() + ".reg2mem", AllocaPoint); } else { - Slot = new AllocaInst(I.getType(), DL.getAllocaAddrSpace(), nullptr, - I.getName() + ".reg2mem", &F->getEntryBlock().front()); + Slot = + new AllocaInst(I.getType(), DL.getAllocaAddrSpace(), nullptr, + I.getName() + ".reg2mem", &F->getEntryBlock().front()); } // We cannot demote invoke instructions to the stack if their normal edge @@ -44,7 +45,8 @@ // into which the store can be inserted. if (InvokeInst *II = dyn_cast(&I)) { if (!II->getNormalDest()->getSinglePredecessor()) { - unsigned SuccNum = GetSuccessorNumber(II->getParent(), II->getNormalDest()); + unsigned SuccNum = + GetSuccessorNumber(II->getParent(), II->getNormalDest()); assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!"); BasicBlock *BB = SplitCriticalEdge(II, SuccNum); assert(BB && "Unable to split critical edge."); @@ -65,7 +67,7 @@ // 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; + DenseMap Loads; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == &I) { Value *&V = Loads[PN->getIncomingBlock(i)]; @@ -92,8 +94,19 @@ BasicBlock::iterator InsertPt; if (!I.isTerminator()) { InsertPt = ++I.getIterator(); + // Don't insert before PHI nodes or landingpad instrs. for (; isa(InsertPt) || InsertPt->isEHPad(); ++InsertPt) - /* empty */; // Don't insert before PHI nodes or landingpad instrs. + if (isa(InsertPt)) + break; + if (CatchSwitchInst *CSI = dyn_cast(InsertPt)) { + for (BasicBlock *Handler : CSI->handlers()) { + new StoreInst(&I, Slot, &*Handler->getFirstInsertionPt()); + } + if (CSI->hasUnwindDest()) { + new StoreInst(&I, Slot, &*CSI->getUnwindDest()->getFirstInsertionPt()); + } + return Slot; + } } else { InvokeInst &II = cast(I); InsertPt = II.getNormalDest()->getFirstInsertionPt(); @@ -118,19 +131,20 @@ AllocaInst *Slot; if (AllocaPoint) { Slot = new AllocaInst(P->getType(), DL.getAllocaAddrSpace(), nullptr, - P->getName()+".reg2mem", AllocaPoint); + P->getName() + ".reg2mem", AllocaPoint); } else { Function *F = P->getParent()->getParent(); - Slot = new AllocaInst(P->getType(), DL.getAllocaAddrSpace(), nullptr, - P->getName() + ".reg2mem", - &F->getEntryBlock().front()); + Slot = + new AllocaInst(P->getType(), DL.getAllocaAddrSpace(), nullptr, + P->getName() + ".reg2mem", &F->getEntryBlock().front()); } // Iterate over each operand inserting a store in each predecessor. for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) { if (InvokeInst *II = dyn_cast(P->getIncomingValue(i))) { assert(II->getParent() != P->getIncomingBlock(i) && - "Invoke edge not supported yet"); (void)II; + "Invoke edge not supported yet"); + (void)II; } new StoreInst(P->getIncomingValue(i), Slot, P->getIncomingBlock(i)->getTerminator()); @@ -138,14 +152,27 @@ // Insert a load in place of the PHI and replace all uses. BasicBlock::iterator InsertPt = P->getIterator(); - + // Don't insert before PHI nodes or landingpad instrs. for (; isa(InsertPt) || InsertPt->isEHPad(); ++InsertPt) - /* empty */; // Don't insert before PHI nodes or landingpad instrs. - - Value *V = - new LoadInst(P->getType(), Slot, P->getName() + ".reload", &*InsertPt); - P->replaceAllUsesWith(V); - + if (isa(InsertPt)) + break; + if (CatchSwitchInst *CSI = dyn_cast(InsertPt)) { + // We need a separate load before each actual use of the PHI + SmallVector users; + for (User *U : P->users()) { + Instruction *User = cast(U); + users.push_back(User); + } + for (Instruction *User : users) { + Value *V = + new LoadInst(P->getType(), Slot, P->getName() + ".reload", User); + User->replaceUsesOfWith(P, V); + } + } else { + Value *V = + new LoadInst(P->getType(), Slot, P->getName() + ".reload", &*InsertPt); + P->replaceAllUsesWith(V); + } // Delete PHI. P->eraseFromParent(); return Slot;