[DSE,MemorySSA] Check for underlying objects first.

isWriteAtEndOfFunction needs to check all memory uses of Def, which is
much more expensive than getting the underlying objects in practice.
Switch the call order, as recommended by the TODO, which was added as
per an earlier review.

This shaves off a bit of compile-time.
This commit is contained in:
Florian Hahn 2020-08-14 15:25:01 +01:00
parent a275acc4a9
commit df4756ec6c
1 changed files with 19 additions and 20 deletions

View File

@ -2045,29 +2045,28 @@ struct DSEState {
!isRemovable(Def->getMemoryInst()))
continue;
// TODO: Consider doing the underlying object check first, if it is
// beneficial compile-time wise.
if (isWriteAtEndOfFunction(Def)) {
Instruction *DefI = Def->getMemoryInst();
// See through pointer-to-pointer bitcasts
SmallVector<const Value *, 4> Pointers;
getUnderlyingObjects(getLocForWriteEx(DefI)->Ptr, Pointers);
Instruction *DefI = Def->getMemoryInst();
SmallVector<const Value *, 4> Pointers;
auto DefLoc = getLocForWriteEx(DefI);
if (!DefLoc)
continue;
getUnderlyingObjects(DefLoc->Ptr, Pointers);
bool CanKill = true;
for (const Value *Pointer : Pointers) {
if (!InvisibleToCallerAfterRet.count(Pointer)) {
CanKill = false;
break;
}
}
if (CanKill && isWriteAtEndOfFunction(Def)) {
// See through pointer-to-pointer bitcasts
LLVM_DEBUG(dbgs() << " ... MemoryDef is not accessed until the end "
"of the function\n");
bool CanKill = true;
for (const Value *Pointer : Pointers) {
if (!InvisibleToCallerAfterRet.count(Pointer)) {
CanKill = false;
break;
}
}
if (CanKill) {
deleteDeadInstruction(DefI);
++NumFastStores;
MadeChange = true;
}
deleteDeadInstruction(DefI);
++NumFastStores;
MadeChange = true;
}
}
return MadeChange;