diff options
| author | Joseph Tremoulet <jotrem@microsoft.com> | 2016-01-02 15:22:36 +0000 | 
|---|---|---|
| committer | Joseph Tremoulet <jotrem@microsoft.com> | 2016-01-02 15:22:36 +0000 | 
| commit | 71e5676de4d30bbff60f496912db1036f8956430 (patch) | |
| tree | 928521c4b8f8d11220ac7bb0eb856a7e1edcd817 /llvm/lib | |
| parent | c47c6ac0a51b62f75cdfcd6ea0d2cb4585408fa3 (diff) | |
| download | bcm5719-llvm-71e5676de4d30bbff60f496912db1036f8956430.tar.gz bcm5719-llvm-71e5676de4d30bbff60f496912db1036f8956430.zip  | |
[WinEH] Update catchrets with cloned successors
Summary:
Add a pass to update catchrets when their successors get cloned; the
existing pass doesn't catch these because it walks the funclet whose
blocks are being cloned but the catchret is in a child funclet.
Also update the test for removing incoming PHI values; when the
predecessor is a catchret, the relevant color is the catchret's parentPad,
not its block's color.
Reviewers: andrew.w.kaylor, rnk, majnemer
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D15840
llvm-svn: 256689
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 42 | 
1 files changed, 38 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 83507894b49..3d1c3803194 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -598,6 +598,11 @@ void WinEHPrepare::cloneCommonBlocks(Function &F) {    for (auto &Funclets : FuncletBlocks) {      BasicBlock *FuncletPadBB = Funclets.first;      std::vector<BasicBlock *> &BlocksInFunclet = Funclets.second; +    Value *FuncletToken; +    if (FuncletPadBB == &F.getEntryBlock()) +      FuncletToken = ConstantTokenNone::get(F.getContext()); +    else +      FuncletToken = FuncletPadBB->getFirstNonPHI();      std::vector<std::pair<BasicBlock *, BasicBlock *>> Orig2Clone;      ValueToValueMapTy VMap; @@ -669,15 +674,44 @@ void WinEHPrepare::cloneCommonBlocks(Function &F) {          RemapInstruction(&I, VMap,                           RF_IgnoreMissingEntries | RF_NoModuleLevelChanges); +    // Catchrets targeting cloned blocks need to be updated separately from +    // the loop above because they are not in the current funclet. +    SmallVector<CatchReturnInst *, 2> FixupCatchrets; +    for (auto &BBMapping : Orig2Clone) { +      BasicBlock *OldBlock = BBMapping.first; +      BasicBlock *NewBlock = BBMapping.second; + +      FixupCatchrets.clear(); +      for (BasicBlock *Pred : predecessors(OldBlock)) +        if (auto *CatchRet = dyn_cast<CatchReturnInst>(Pred->getTerminator())) +          if (CatchRet->getParentPad() == FuncletToken) +            FixupCatchrets.push_back(CatchRet); + +      for (CatchReturnInst *CatchRet : FixupCatchrets) +        CatchRet->setSuccessor(NewBlock); +    } +      auto UpdatePHIOnClonedBlock = [&](PHINode *PN, bool IsForOldBlock) {        unsigned NumPreds = PN->getNumIncomingValues();        for (unsigned PredIdx = 0, PredEnd = NumPreds; PredIdx != PredEnd;             ++PredIdx) {          BasicBlock *IncomingBlock = PN->getIncomingBlock(PredIdx); -        ColorVector &IncomingColors = BlockColors[IncomingBlock]; -        bool BlockInFunclet = IncomingColors.size() == 1 && -                              IncomingColors.front() == FuncletPadBB; -        if (IsForOldBlock != BlockInFunclet) +        bool EdgeTargetsFunclet; +        if (auto *CRI = +                dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) { +          EdgeTargetsFunclet = (CRI->getParentPad() == FuncletToken); +        } else { +          ColorVector &IncomingColors = BlockColors[IncomingBlock]; +          assert(!IncomingColors.empty() && "Block not colored!"); +          assert((IncomingColors.size() == 1 || +                  llvm::all_of(IncomingColors, +                               [&](BasicBlock *Color) { +                                 return Color != FuncletPadBB; +                               })) && +                 "Cloning should leave this funclet's blocks monochromatic"); +          EdgeTargetsFunclet = (IncomingColors.front() == FuncletPadBB); +        } +        if (IsForOldBlock != EdgeTargetsFunclet)            continue;          PN->removeIncomingValue(IncomingBlock, /*DeletePHIIfEmpty=*/false);          // Revisit the next entry.  | 

