diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/MemorySSA.h | 23 | ||||
| -rw-r--r-- | llvm/include/llvm/Analysis/MemorySSAUpdater.h | 8 | ||||
| -rw-r--r-- | llvm/lib/Analysis/MemorySSAUpdater.cpp | 29 |
3 files changed, 49 insertions, 11 deletions
diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h index 342aefcaa7e..d445e4430e5 100644 --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -578,10 +578,11 @@ public: setNumHungOffUseOperands(getNumOperands() - 1); } - // After deleting incoming block BB, the incoming blocks order may be changed. - void unorderedDeleteIncomingBlock(const BasicBlock *BB) { + // After deleting entries that satisfy Pred, remaining entries may have + // changed order. + template <typename Fn> void unorderedDeleteIncomingIf(Fn &&Pred) { for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - if (block_begin()[I] == BB) { + if (Pred(getIncomingValue(I), getIncomingBlock(I))) { unorderedDeleteIncoming(I); E = getNumOperands(); --I; @@ -590,17 +591,17 @@ public: "Cannot remove all incoming blocks in a MemoryPhi."); } + // After deleting incoming block BB, the incoming blocks order may be changed. + void unorderedDeleteIncomingBlock(const BasicBlock *BB) { + unorderedDeleteIncomingIf( + [&](const MemoryAccess *, const BasicBlock *B) { return BB == B; }); + } + // After deleting incoming memory access MA, the incoming accesses order may // be changed. void unorderedDeleteIncomingValue(const MemoryAccess *MA) { - for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - if (getIncomingValue(I) == MA) { - unorderedDeleteIncoming(I); - E = getNumOperands(); - --I; - } - assert(getNumOperands() >= 1 && - "Cannot remove all incoming values in a MemoryPhi."); + unorderedDeleteIncomingIf( + [&](const MemoryAccess *M, const BasicBlock *) { return MA == M; }); } static bool classof(const Value *V) { diff --git a/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/llvm/include/llvm/Analysis/MemorySSAUpdater.h index a17bd811d70..38f08c1eebd 100644 --- a/llvm/include/llvm/Analysis/MemorySSAUpdater.h +++ b/llvm/include/llvm/Analysis/MemorySSAUpdater.h @@ -124,6 +124,14 @@ public: /// |------| |------| void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To, Instruction *Start); + /// BasicBlock Old had New, an empty BasicBlock, added directly before it, + /// and the predecessors in Preds that used to point to Old, now point to + /// New. If New is the only predecessor, move Old's Phi, if present, to New. + /// Otherwise, add a new Phi in New with appropriate incoming values, and + /// update the incoming values in Old's Phi node too, if present. + void + wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New, + ArrayRef<BasicBlock *> Preds); // The below are utility functions. Other than creation of accesses to pass // to insertDef, and removeAccess to remove accesses, you should generally diff --git a/llvm/lib/Analysis/MemorySSAUpdater.cpp b/llvm/lib/Analysis/MemorySSAUpdater.cpp index 8ab5f743c98..bdb370c9899 100644 --- a/llvm/lib/Analysis/MemorySSAUpdater.cpp +++ b/llvm/lib/Analysis/MemorySSAUpdater.cpp @@ -499,6 +499,35 @@ static MemoryAccess *onlySingleValue(MemoryPhi *MP) { return MA; } +void MemorySSAUpdater::wireOldPredecessorsToNewImmediatePredecessor( + BasicBlock *Old, BasicBlock *New, ArrayRef<BasicBlock *> Preds) { + assert(!MSSA->getWritableBlockAccesses(New) && + "Access list should be null for a new block."); + MemoryPhi *Phi = MSSA->getMemoryAccess(Old); + if (!Phi) + return; + if (pred_size(Old) == 1) { + assert(pred_size(New) == Preds.size() && + "Should have moved all predecessors."); + MSSA->moveTo(Phi, New, MemorySSA::Beginning); + } else { + assert(!Preds.empty() && "Must be moving at least one predecessor to the " + "new immediate predecessor."); + MemoryPhi *NewPhi = MSSA->createMemoryPhi(New); + SmallPtrSet<BasicBlock *, 16> PredsSet(Preds.begin(), Preds.end()); + Phi->unorderedDeleteIncomingIf([&](MemoryAccess *MA, BasicBlock *B) { + if (PredsSet.count(B)) { + NewPhi->addIncoming(MA, B); + return true; + } + return false; + }); + Phi->addIncoming(NewPhi, New); + if (onlySingleValue(NewPhi)) + removeMemoryAccess(NewPhi); + } +} + void MemorySSAUpdater::removeMemoryAccess(MemoryAccess *MA) { assert(!MSSA->isLiveOnEntryDef(MA) && "Trying to remove the live on entry def"); |

