From: David Majnemer Date: Thu, 6 Aug 2015 21:08:32 +0000 (+0000) Subject: Handle PHI nodes prefacing EH pads too X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d284a380ab016c1aa7626236abeeacad64312179;p=oota-llvm.git Handle PHI nodes prefacing EH pads too git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244274 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index fb059b92cdb..df9da1456a1 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -2951,6 +2951,7 @@ void WinEHPrepare::numberFunclet(BasicBlock *InitialBB, BasicBlock *FuncletBB) { } bool WinEHPrepare::prepareExplicitEH(Function &F) { + LLVMContext &Context = F.getContext(); // Remove unreachable blocks. It is not valuable to assign them a color and // their existence can trick us into thinking values are alive when they are // not. @@ -2980,24 +2981,97 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) { numberFunclet(CRI->getSuccessor(), EntryBlock); } - // Strip PHI nodes off of EH pads. + // Insert cleanuppads before EH blocks with PHI nodes. for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { BasicBlock *BB = FI++; + // Skip any BBs which aren't EH pads. + if (!BB->isEHPad()) + continue; + // Skip any cleanuppads, they can hold non-PHI instructions. + if (isa(BB->getFirstNonPHI())) + continue; + // Skip any EH pads without PHIs, we don't need to worry about demoting into + // them. + if (!isa(BB->begin())) + continue; + + // Create our new cleanuppad BB, terminate it with a cleanupret. + auto *NewCleanupBB = BasicBlock::Create( + Context, Twine(BB->getName(), ".wineh.phibb"), &F, BB); + auto *CPI = CleanupPadInst::Create(Type::getVoidTy(Context), {BB}, "", + NewCleanupBB); + CleanupReturnInst::Create(Context, /*RetVal=*/nullptr, BB, NewCleanupBB); + + // Update the funclet data structures to keep them in the loop. + BlockColors[NewCleanupBB].insert(NewCleanupBB); + FuncletBlocks[NewCleanupBB].insert(NewCleanupBB); + + // Reparent PHIs from the old EH BB into the cleanuppad. for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { - if (!BI->isEHPad()) + Instruction *I = BI++; + auto *PN = dyn_cast(I); + // Stop at the first non-PHI. + if (!PN) + break; + PN->removeFromParent(); + PN->insertBefore(CPI); + } + + // Redirect predecessors from the old EH BB to the cleanuppad. + std::set Preds; + Preds.insert(pred_begin(BB), pred_end(BB)); + for (BasicBlock *Pred : Preds) { + // Don't redirect the new cleanuppad to itself! + if (Pred == NewCleanupBB) continue; + TerminatorInst *TI = Pred->getTerminator(); + for (unsigned TII = 0, TIE = TI->getNumSuccessors(); TII != TIE; ++TII) { + BasicBlock *Successor = TI->getSuccessor(TII); + if (Successor == BB) + TI->setSuccessor(TII, NewCleanupBB); + } + } + } + + // Get rid of polychromatic PHI nodes. + for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { + BasicBlock *BB = FI++; + std::set &ColorsForBB = BlockColors[BB]; + bool IsEHPad = BB->isEHPad(); + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { Instruction *I = BI++; auto *PN = dyn_cast(I); + // Stop at the first non-PHI node. if (!PN) + break; + + // EH pads cannot be lowered with PHI nodes prefacing them. + if (IsEHPad) { + // We should have removed PHIs from all non-cleanuppad blocks. + if (!isa(BB->getFirstNonPHI())) + report_fatal_error("Unexpected PHI on EH Pad"); + DemotePHIToStack(PN); continue; - auto *SpillSlot = new AllocaInst(I->getType(), nullptr, - Twine(I->getName(), ".wineh.phispill"), - EntryBlock->begin()); - - // Iterate over each operand inserting a store in each predecessor. - for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) - new StoreInst(P->getIncomingValue(i), Slot, - P->getIncomingBlock(i)->getTerminator()); + } + + // See if *all* the basic blocks involved in this PHI node are in the + // same, lone, color. If so, demotion is not needed. + bool SameColor = ColorsForBB.size() == 1; + if (SameColor) { + for (unsigned PNI = 0, PNE = PN->getNumIncomingValues(); PNI != PNE; + ++PNI) { + BasicBlock *IncomingBB = PN->getIncomingBlock(PNI); + std::set &ColorsForIncomingBB = BlockColors[IncomingBB]; + // If the colors differ, bail out early and demote. + if (ColorsForIncomingBB != ColorsForBB) { + SameColor = false; + break; + } + } + } + + if (!SameColor) + DemotePHIToStack(PN); } } @@ -3180,9 +3254,9 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) { // branches, etc. for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { BasicBlock *BB = FI++; - SimplifyInstructionsInBlock(BB); - ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true); - MergeBlockIntoPredecessor(BB); + //SimplifyInstructionsInBlock(BB); + //ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true); + //MergeBlockIntoPredecessor(BB); } // TODO: Do something about cleanupblocks which branch to implausible diff --git a/lib/Transforms/Utils/DemoteRegToStack.cpp b/lib/Transforms/Utils/DemoteRegToStack.cpp index f11b6099939..1d7c740b6e0 100644 --- a/lib/Transforms/Utils/DemoteRegToStack.cpp +++ b/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -135,7 +135,7 @@ AllocaInst *llvm::DemotePHIToStack(PHINode *P, Instruction *AllocaPoint) { // Insert a load in place of the PHI and replace all uses. BasicBlock::iterator InsertPt = P; - for (; isa(InsertPt) || isa(InsertPt); ++InsertPt) + for (; isa(InsertPt) || InsertPt->isEHPad(); ++InsertPt) /* empty */; // Don't insert before PHI nodes or landingpad instrs. Value *V = new LoadInst(Slot, P->getName()+".reload", InsertPt);