diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index 16b58cf7178..0d26ed333ca 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -23,7 +23,6 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/TinyPtrVector.h" -#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/CodeGen/WinEHFuncInfo.h" @@ -122,9 +121,6 @@ private: void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB); - bool prepareExplicitEH(Function &F); - void numberFunclet(BasicBlock *InitialBB, BasicBlock *FuncletBB); - Triple TheTriple; // All fields are reset by runOnFunction. @@ -164,9 +160,6 @@ private: DenseMap HandlerToParentFP; AllocaInst *SEHExceptionCodeSlot = nullptr; - - std::map> BlockColors; - std::map> FuncletBlocks; }; class WinEHFrameVariableMaterializer : public ValueMaterializer { @@ -368,13 +361,23 @@ FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { } bool WinEHPrepare::runOnFunction(Function &Fn) { - if (!Fn.hasPersonalityFn()) - return false; - // No need to prepare outlined handlers. if (Fn.hasFnAttribute("wineh-parent")) return false; + SmallVector LPads; + SmallVector Resumes; + for (BasicBlock &BB : Fn) { + if (auto *LP = BB.getLandingPadInst()) + LPads.push_back(LP); + if (auto *Resume = dyn_cast(BB.getTerminator())) + Resumes.push_back(Resume); + } + + // No need to prepare functions that lack landing pads. + if (LPads.empty()) + return false; + // Classify the personality to see what kind of preparation we need. Personality = classifyEHPersonality(Fn.getPersonalityFn()); @@ -382,27 +385,6 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { if (!isMSVCEHPersonality(Personality)) return false; - SmallVector LPads; - SmallVector Resumes; - bool ForExplicitEH = false; - for (BasicBlock &BB : Fn) { - if (auto *LP = BB.getLandingPadInst()) { - LPads.push_back(LP); - } else if (BB.getFirstNonPHI()->isEHPad()) { - ForExplicitEH = true; - break; - } - if (auto *Resume = dyn_cast(BB.getTerminator())) - Resumes.push_back(Resume); - } - - if (ForExplicitEH) - return prepareExplicitEH(Fn); - - // No need to prepare functions that lack landing pads. - if (LPads.empty()) - return false; - DT = &getAnalysis().getDomTree(); LibInfo = &getAnalysis().getTLI(); @@ -2912,350 +2894,3 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, while (!Num.HandlerStack.empty()) Num.processCallSite(None, ImmutableCallSite()); } - -void WinEHPrepare::numberFunclet(BasicBlock *InitialBB, BasicBlock *FuncletBB) { - Instruction *FirstNonPHI = FuncletBB->getFirstNonPHI(); - bool IsCatch = isa(FirstNonPHI); - bool IsCleanup = isa(FirstNonPHI); - - // Initialize the worklist with the funclet's entry point. - std::vector Worklist; - Worklist.push_back(InitialBB); - - while (!Worklist.empty()) { - BasicBlock *BB = Worklist.back(); - Worklist.pop_back(); - - // There can be only one "pad" basic block in the funclet: the initial one. - if (BB != FuncletBB && BB->isEHPad()) - continue; - - // Add 'FuncletBB' as a possible color for 'BB'. - if (BlockColors[BB].insert(FuncletBB).second == false) { - // Skip basic blocks which we have already visited. - continue; - } - - FuncletBlocks[FuncletBB].insert(BB); - - Instruction *Terminator = BB->getTerminator(); - // The catchret's successors cannot be part of the funclet. - if (IsCatch && isa(Terminator)) - continue; - // The cleanupret's successors cannot be part of the funclet. - if (IsCleanup && isa(Terminator)) - continue; - - Worklist.insert(Worklist.end(), succ_begin(BB), succ_end(BB)); - } -} - -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. - removeUnreachableBlocks(F); - - BasicBlock *EntryBlock = &F.getEntryBlock(); - - // Number everything starting from the entry block. - numberFunclet(EntryBlock, EntryBlock); - - for (BasicBlock &BB : F) { - // Remove single entry PHIs to simplify preparation. - if (auto *PN = dyn_cast(BB.begin())) - if (PN->getNumIncomingValues() == 1) - FoldSingleEntryPHINodes(&BB); - - // EH pad instructions are always the first non-PHI nodes in a block if they - // are at all present. - Instruction *I = BB.getFirstNonPHI(); - if (I->isEHPad()) - numberFunclet(&BB, &BB); - - // It is possible for a normal basic block to only be reachable via an - // exceptional basic block. The successor of a catchret is the only case - // where this is possible. - if (auto *CRI = dyn_cast(BB.getTerminator())) - numberFunclet(CRI->getSuccessor(), EntryBlock); - } - - // 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;) { - 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; - } - - // 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); - } - } - - // Turn all inter-funclet uses of a Value into loads and stores. - for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { - BasicBlock *BB = FI++; - std::set &ColorsForBB = BlockColors[BB]; - for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { - Instruction *I = BI++; - // Funclets are permitted to use static allocas. - if (auto *AI = dyn_cast(I)) - if (AI->isStaticAlloca()) - continue; - - // FIXME: Our spill-placement algorithm is incredibly naive. We should - // try to sink+hoist as much as possible to avoid redundant stores and reloads. - DenseMap Loads; - AllocaInst *SpillSlot = nullptr; - for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); - UI != UE;) { - Use &U = *UI++; - auto *UsingInst = cast(U.getUser()); - BasicBlock *UsingBB = UsingInst->getParent(); - - // Is the Use inside a block which is colored with a subset of the Def? - // If so, we don't need to escape the Def because we will clone - // ourselves our own private copy. - std::set &ColorsForUsingBB = BlockColors[UsingBB]; - if (std::includes(ColorsForBB.begin(), ColorsForBB.end(), - ColorsForUsingBB.begin(), ColorsForUsingBB.end())) - continue; - - // Lazilly create the spill slot. We spill immediately after the value - // in the BasicBlock. - // FIXME: This can be improved to spill at the block exit points. - if (!SpillSlot) - SpillSlot = new AllocaInst(I->getType(), nullptr, - Twine(I->getName(), ".wineh.spillslot"), - EntryBlock->begin()); - - if (auto *PN = dyn_cast(UsingInst)) { - // 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. - BasicBlock *IncomingBlock = PN->getIncomingBlock(U); - Value *&V = Loads[IncomingBlock]; - // Insert the load into the predecessor block - if (!V) - V = new LoadInst(SpillSlot, Twine(I->getName(), ".wineh.reload"), - /*Volatile=*/false, - IncomingBlock->getTerminator()); - U.set(V); - } else { - // Reload right before the old use. - // FIXME: This can be improved to reload at a block entry point. - Value *V = - new LoadInst(SpillSlot, Twine(I->getName(), ".wineh.reload"), - /*Volatile=*/false, UsingInst); - U.set(V); - } - } - if (SpillSlot) { - // Insert stores of the computed value into the stack slot. - // We have to be careful if I is an invoke instruction, - // because we can't insert the store AFTER the terminator instruction. - BasicBlock::iterator InsertPt; - if (!isa(I)) { - InsertPt = I; - ++InsertPt; - // Don't insert before PHI nodes or EH pad instrs. - for (; isa(InsertPt) || InsertPt->isEHPad(); ++InsertPt) - ; - } else { - auto *II = cast(I); - // We cannot demote invoke instructions to the stack if their normal - // edge is critical. Therefore, split the critical edge and create a - // basic block into which the store can be inserted. - if (!II->getNormalDest()->getSinglePredecessor()) { - unsigned SuccNum = GetSuccessorNumber(BB, II->getNormalDest()); - assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!"); - BasicBlock *NewBlock = SplitCriticalEdge(II, SuccNum); - assert(NewBlock && "Unable to split critical edge."); - // Update the color mapping for the newly split edge. - std::set &ColorsForUsingBB = - BlockColors[II->getParent()]; - BlockColors[NewBlock] = ColorsForUsingBB; - for (BasicBlock *FuncletPad : ColorsForUsingBB) - FuncletBlocks[FuncletPad].insert(NewBlock); - } - InsertPt = II->getNormalDest()->getFirstInsertionPt(); - } - new StoreInst(I, SpillSlot, InsertPt); - } - } - } - - // We need to clone all blocks which belong to multiple funclets. Values are - // remapped throughout the funclet to propogate both the new instructions - // *and* the new basic blocks themselves. - for (auto &Funclet : FuncletBlocks) { - BasicBlock *FuncletPadBB = Funclet.first; - std::set &BlocksInFunclet = Funclet.second; - - std::map Orig2Clone; - ValueToValueMapTy VMap; - for (BasicBlock *BB : BlocksInFunclet) { - std::set &ColorsForBB = BlockColors[BB]; - // We don't need to do anything if the block is monochromatic. - size_t NumColorsForBB = ColorsForBB.size(); - if (NumColorsForBB == 1) - continue; - - assert(!isa(BB->front()) && - "Polychromatic PHI nodes should have been demoted!"); - - // Create a new basic block and copy instructions into it! - BasicBlock *CBB = CloneBasicBlock( - BB, VMap, Twine(".for.", FuncletPadBB->getName()), &F); - - // Add basic block mapping. - VMap[BB] = CBB; - - // Record delta operations that we need to perform to our color mappings. - Orig2Clone[BB] = CBB; - } - - // Update our color mappings to reflect that one block has lost a color and - // another has gained a color. - for (auto &BBMapping : Orig2Clone) { - BasicBlock *OldBlock = BBMapping.first; - BasicBlock *NewBlock = BBMapping.second; - - BlocksInFunclet.insert(NewBlock); - BlockColors[NewBlock].insert(FuncletPadBB); - - BlocksInFunclet.erase(OldBlock); - BlockColors[OldBlock].erase(FuncletPadBB); - } - - // Loop over all of the instructions in the function, fixing up operand - // references as we go. This uses VMap to do all the hard work. - for (BasicBlock *BB : BlocksInFunclet) - // Loop over all instructions, fixing each one as we find it... - for (Instruction &I : *BB) - RemapInstruction(&I, VMap, RF_IgnoreMissingEntries); - } - - // Clean-up some of the mess we made by removing useles PHI nodes, trivial - // branches, etc. - for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE;) { - BasicBlock *BB = FI++; - SimplifyInstructionsInBlock(BB); - ConstantFoldTerminator(BB, /*DeleteDeadConditions=*/true); - MergeBlockIntoPredecessor(BB); - } - - // TODO: Do something about cleanupblocks which branch to implausible - // cleanuprets. - - // We might have some unreachable blocks after cleaning up some impossible - // control flow. - removeUnreachableBlocks(F); - - // Recolor the CFG to verify that all is well. - for (BasicBlock &BB : F) { - size_t NumColors = BlockColors[&BB].size(); - assert(NumColors == 1 && "Expected monochromatic BB!"); - if (NumColors == 0) - report_fatal_error("Uncolored BB!"); - if (NumColors > 1) - report_fatal_error("Multicolor BB!"); - bool EHPadHasPHI = BB.isEHPad() && isa(BB.begin()); - assert(!EHPadHasPHI && "EH Pad still has a PHI!"); - if (EHPadHasPHI) - report_fatal_error("EH Pad still has a PHI!"); - } - - BlockColors.clear(); - FuncletBlocks.clear(); - return true; -} diff --git a/lib/Transforms/Utils/DemoteRegToStack.cpp b/lib/Transforms/Utils/DemoteRegToStack.cpp index 1d7c740b6e0..f11b6099939 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) || InsertPt->isEHPad(); ++InsertPt) + for (; isa(InsertPt) || isa(InsertPt); ++InsertPt) /* empty */; // Don't insert before PHI nodes or landingpad instrs. Value *V = new LoadInst(Slot, P->getName()+".reload", InsertPt);