1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[MemorySSA] Add APIs to MemoryPhis to delete incoming blocks/values, and an updater API to remove blocks.

Summary:
MemoryPhis now have APIs analogous to BB Phis to remove an incoming value/block.
The MemorySSAUpdater uses the above APIs when updating MemorySSA given a set of dead blocks about to be deleted.

Reviewers: george.burgess.iv

Subscribers: sanjoy, jlebar, Prazek, llvm-commits

Differential Revision: https://reviews.llvm.org/D48396

llvm-svn: 336015
This commit is contained in:
Alina Sbirlea 2018-06-29 20:46:16 +00:00
parent eb18816b59
commit c96b36e0c5
4 changed files with 88 additions and 3 deletions

View File

@ -563,6 +563,46 @@ public:
return getIncomingValue(Idx);
}
// After deleting incoming position I, the order of incoming may be changed.
void unorderedDeleteIncoming(unsigned I) {
unsigned E = getNumOperands();
assert(I < E && "Cannot remove out of bounds Phi entry.");
// MemoryPhi must have at least two incoming values, otherwise the MemoryPhi
// itself should be deleted.
assert(E >= 2 && "Cannot only remove incoming values in MemoryPhis with "
"at least 2 values.");
setIncomingValue(I, getIncomingValue(E - 1));
setIncomingBlock(I, block_begin()[E - 1]);
setOperand(E - 1, nullptr);
block_begin()[E - 1] = nullptr;
setNumHungOffUseOperands(getNumOperands() - 1);
}
// After deleting incoming block BB, the incoming blocks order may be changed.
void unorderedDeleteIncomingBlock(const BasicBlock *BB) {
for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
if (block_begin()[I] == BB) {
unorderedDeleteIncoming(I);
E = getNumOperands();
--I;
}
assert(getNumOperands() >= 1 &&
"Cannot remove all incoming blocks in a MemoryPhi.");
}
// 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.");
}
static bool classof(const Value *V) {
return V->getValueID() == MemoryPhiVal;
}

View File

@ -146,6 +146,15 @@ public:
removeMemoryAccess(MA);
}
/// Remove all MemoryAcceses in a set of BasicBlocks about to be deleted.
/// Assumption we make here: all uses of deleted defs and phi must either
/// occur in blocks about to be deleted (thus will be deleted as well), or
/// they occur in phis that will simply lose an incoming value.
/// Deleted blocks still have successor info, but their predecessor edges and
/// Phi nodes may already be updated. Instructions in DeadBlocks should be
/// deleted after this call.
void removeBlocks(const SmallPtrSetImpl<BasicBlock *> &DeadBlocks);
/// Get handle on MemorySSA.
MemorySSA* getMemorySSA() const { return MSSA; }

View File

@ -1597,10 +1597,11 @@ void MemorySSA::removeFromLookups(MemoryAccess *MA) {
/// ShouldDelete defaults to true, and will cause the memory access to also be
/// deleted, not just removed.
void MemorySSA::removeFromLists(MemoryAccess *MA, bool ShouldDelete) {
BasicBlock *BB = MA->getBlock();
// The access list owns the reference, so we erase it from the non-owning list
// first.
if (!isa<MemoryUse>(MA)) {
auto DefsIt = PerBlockDefs.find(MA->getBlock());
auto DefsIt = PerBlockDefs.find(BB);
std::unique_ptr<DefsList> &Defs = DefsIt->second;
Defs->remove(*MA);
if (Defs->empty())
@ -1609,15 +1610,17 @@ void MemorySSA::removeFromLists(MemoryAccess *MA, bool ShouldDelete) {
// The erase call here will delete it. If we don't want it deleted, we call
// remove instead.
auto AccessIt = PerBlockAccesses.find(MA->getBlock());
auto AccessIt = PerBlockAccesses.find(BB);
std::unique_ptr<AccessList> &Accesses = AccessIt->second;
if (ShouldDelete)
Accesses->erase(MA);
else
Accesses->remove(MA);
if (Accesses->empty())
if (Accesses->empty()) {
PerBlockAccesses.erase(AccessIt);
BlockNumberingValid.erase(BB);
}
}
void MemorySSA::print(raw_ostream &OS) const {

View File

@ -492,6 +492,39 @@ void MemorySSAUpdater::removeMemoryAccess(MemoryAccess *MA) {
MSSA->removeFromLists(MA);
}
void MemorySSAUpdater::removeBlocks(
const SmallPtrSetImpl<BasicBlock *> &DeadBlocks) {
// First delete all uses of BB in MemoryPhis.
for (BasicBlock *BB : DeadBlocks) {
TerminatorInst *TI = BB->getTerminator();
assert(TI && "Basic block expected to have a terminator instruction");
for (BasicBlock *Succ : TI->successors())
if (!DeadBlocks.count(Succ))
if (MemoryPhi *MP = MSSA->getMemoryAccess(Succ)) {
MP->unorderedDeleteIncomingBlock(BB);
if (MP->getNumIncomingValues() == 1)
removeMemoryAccess(MP);
}
// Drop all references of all accesses in BB
if (MemorySSA::AccessList *Acc = MSSA->getWritableBlockAccesses(BB))
for (MemoryAccess &MA : *Acc)
MA.dropAllReferences();
}
// Next, delete all memory accesses in each block
for (BasicBlock *BB : DeadBlocks) {
MemorySSA::AccessList *Acc = MSSA->getWritableBlockAccesses(BB);
if (!Acc)
continue;
for (auto AB = Acc->begin(), AE = Acc->end(); AB != AE;) {
MemoryAccess *MA = &*AB;
++AB;
MSSA->removeFromLookups(MA);
MSSA->removeFromLists(MA);
}
}
}
MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
MemorySSA::InsertionPlace Point) {