diff options
| author | Joseph Tremoulet <jotrem@microsoft.com> | 2015-08-17 13:51:37 +0000 |
|---|---|---|
| committer | Joseph Tremoulet <jotrem@microsoft.com> | 2015-08-17 13:51:37 +0000 |
| commit | 7031c9fc2e0a7e443b317ea6bfdbaf8e1422ac1b (patch) | |
| tree | 0afdccef24a0e8c8d19143a92f156533934e4bbc /llvm/lib/CodeGen/WinEHPrepare.cpp | |
| parent | 789da6678e55c7dd5316b4a8145c513343b0e84b (diff) | |
| download | bcm5719-llvm-7031c9fc2e0a7e443b317ea6bfdbaf8e1422ac1b.tar.gz bcm5719-llvm-7031c9fc2e0a7e443b317ea6bfdbaf8e1422ac1b.zip | |
[WinEHPrepare] Fix catchret successor phi demotion
Summary:
When demoting an SSA value that has a use on a phi and one of the phi's
predecessors terminates with catchret, the edge needs to be split and the
load inserted in the new block, else we'll still have a cross-funclet SSA
value.
Add a test for this, and for the similar case where a def to be spilled is
on and invoke and a critical edge, which was already implemented but
missing a test.
Reviewers: majnemer
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D12065
llvm-svn: 245218
Diffstat (limited to 'llvm/lib/CodeGen/WinEHPrepare.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 8ab098bc1f1..a299c4fcfb1 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -3289,6 +3289,42 @@ void WinEHPrepare::replaceUseWithLoad(Value *V, Use &U, AllocaInst *&SpillSlot, // 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 = UsingPHI->getIncomingBlock(U); + if (auto *CatchRet = + dyn_cast<CatchReturnInst>(IncomingBlock->getTerminator())) { + // Putting a load above a catchret and use on the phi would still leave + // a cross-funclet def/use. We need to split the edge, change the + // catchret to target the new block, and put the load there. + BasicBlock *PHIBlock = UsingInst->getParent(); + BasicBlock *NewBlock = SplitEdge(IncomingBlock, PHIBlock); + // SplitEdge gives us: + // IncomingBlock: + // ... + // br label %NewBlock + // NewBlock: + // catchret label %PHIBlock + // But we need: + // IncomingBlock: + // ... + // catchret label %NewBlock + // NewBlock: + // br label %PHIBlock + // So move the terminators to each others' blocks and swap their + // successors. + BranchInst *Goto = cast<BranchInst>(IncomingBlock->getTerminator()); + Goto->removeFromParent(); + CatchRet->removeFromParent(); + IncomingBlock->getInstList().push_back(CatchRet); + NewBlock->getInstList().push_back(Goto); + Goto->setSuccessor(0, PHIBlock); + CatchRet->setSuccessor(NewBlock); + // Update the color mapping for the newly split edge. + std::set<BasicBlock *> &ColorsForPHIBlock = BlockColors[PHIBlock]; + BlockColors[NewBlock] = ColorsForPHIBlock; + for (BasicBlock *FuncletPad : ColorsForPHIBlock) + FuncletBlocks[FuncletPad].insert(NewBlock); + // Treat the new block as incoming for load insertion. + IncomingBlock = NewBlock; + } Value *&Load = Loads[IncomingBlock]; // Insert the load into the predecessor block if (!Load) |

