Reimplement the inner loop of DSE. It now uniformly uses getDependence(),

doesn't do its own local caching, and is slightly more aggressive about
free/store dse (see testcase).  This eliminates the last external client 
of MemDep::getDependenceFrom().


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60619 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-12-06 00:53:22 +00:00
parent dd17b25611
commit 5e600e67b1
2 changed files with 52 additions and 85 deletions

View File

@ -50,7 +50,7 @@ namespace {
bool runOnBasicBlock(BasicBlock &BB); bool runOnBasicBlock(BasicBlock &BB);
bool handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep); bool handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep);
bool handleEndBlock(BasicBlock &BB); bool handleEndBlock(BasicBlock &BB);
bool RemoveUndeadPointers(Value* pointer, uint64_t killPointerSize, bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize,
BasicBlock::iterator& BBI, BasicBlock::iterator& BBI,
SmallPtrSet<Value*, 64>& deadPointers); SmallPtrSet<Value*, 64>& deadPointers);
void DeleteDeadInstruction(Instruction *I, void DeleteDeadInstruction(Instruction *I,
@ -81,93 +81,60 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>(); MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
TargetData &TD = getAnalysis<TargetData>(); TargetData &TD = getAnalysis<TargetData>();
// Record the last-seen store to this pointer
DenseMap<Value*, StoreInst*> lastStore;
bool MadeChange = false; bool MadeChange = false;
// Do a top-down walk on the BB // Do a top-down walk on the BB
for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) { for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
Instruction *Inst = BBI++; Instruction *Inst = BBI++;
// If we find a store or a free... // If we find a store or a free, get it's memory dependence.
if (!isa<StoreInst>(Inst) && !isa<FreeInst>(Inst)) if (!isa<StoreInst>(Inst) && !isa<FreeInst>(Inst))
continue; continue;
Value* pointer = 0; MemDepResult InstDep = MD.getDependency(Inst);
if (StoreInst* S = dyn_cast<StoreInst>(Inst)) {
if (S->isVolatile())
continue;
pointer = S->getPointerOperand();
} else {
pointer = cast<FreeInst>(Inst)->getPointerOperand();
}
pointer = pointer->stripPointerCasts(); // Ignore non-local stores.
StoreInst *&last = lastStore[pointer]; // FIXME: cross-block DSE would be fun. :)
if (InstDep.isNonLocal()) continue;
// ... to a pointer that has been stored to before...
if (last) {
MemDepResult dep = MD.getDependency(Inst);
bool deletedStore = false;
// ... and no other memory dependencies are between them....
while (StoreInst *DepStore = dyn_cast_or_null<StoreInst>(dep.getInst())) {
if (DepStore != last ||
TD.getTypeStoreSize(last->getOperand(0)->getType()) >
TD.getTypeStoreSize(Inst->getOperand(0)->getType())) {
dep = MD.getDependencyFrom(Inst, DepStore, DepStore->getParent());
continue;
}
// Delete the store and now-dead instructions that feed it.
DeleteDeadInstruction(last);
NumFastStores++;
deletedStore = true;
MadeChange = true;
break;
}
// If we deleted a store, reinvestigate this instruction.
if (deletedStore) {
if (BBI != BB.begin())
--BBI;
continue;
}
}
// Handle frees whose dependencies are non-trivial. // Handle frees whose dependencies are non-trivial.
if (FreeInst* F = dyn_cast<FreeInst>(Inst)) { if (FreeInst *FI = dyn_cast<FreeInst>(Inst)) {
MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F)); MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep);
continue;
}
// No known stores after the free. StoreInst *SI = cast<StoreInst>(Inst);
last = 0;
} else { // If not a definite must-alias dependency, ignore it.
StoreInst* S = cast<StoreInst>(Inst); if (!InstDep.isDef())
continue;
// If this is a store-store dependence, then the previous store is dead so
// long as this store is at least as big as it.
if (StoreInst *DepStore = dyn_cast<StoreInst>(InstDep.getInst()))
if (TD.getTypeStoreSize(DepStore->getOperand(0)->getType()) <=
TD.getTypeStoreSize(SI->getOperand(0)->getType())) {
// Delete the store and now-dead instructions that feed it.
DeleteDeadInstruction(DepStore);
NumFastStores++;
MadeChange = true;
if (BBI != BB.begin())
--BBI;
continue;
}
// If we're storing the same value back to a pointer that we just // If we're storing the same value back to a pointer that we just
// loaded from, then the store can be removed; // loaded from, then the store can be removed.
if (LoadInst* L = dyn_cast<LoadInst>(S->getOperand(0))) { if (LoadInst *DepLoad = dyn_cast<LoadInst>(InstDep.getInst())) {
if (!S->isVolatile() && S->getParent() == L->getParent() && if (SI->getPointerOperand() == DepLoad->getPointerOperand() &&
S->getPointerOperand() == L->getPointerOperand()) { SI->getOperand(0) == DepLoad) {
MemDepResult dep = MD.getDependency(S); DeleteDeadInstruction(SI);
if (dep.isDef() && dep.getInst() == L) {
DeleteDeadInstruction(S);
if (BBI != BB.begin()) if (BBI != BB.begin())
--BBI; --BBI;
NumFastStores++; NumFastStores++;
MadeChange = true; MadeChange = true;
} else { continue;
// Update our most-recent-store map.
last = S;
}
} else {
// Update our most-recent-store map.
last = S;
}
} else {
// Update our most-recent-store map.
last = S;
} }
} }
} }
@ -182,29 +149,22 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose /// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
/// dependency is a store to a field of that structure. /// dependency is a store to a field of that structure.
bool DSE::handleFreeWithNonTrivialDependency(FreeInst* F, MemDepResult dep) { bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) {
TargetData &TD = getAnalysis<TargetData>();
AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
StoreInst* dependency = dyn_cast_or_null<StoreInst>(dep.getInst()); StoreInst *Dependency = dyn_cast_or_null<StoreInst>(Dep.getInst());
if (!dependency) if (!Dependency || Dependency->isVolatile())
return false;
else if (dependency->isVolatile())
return false; return false;
Value* depPointer = dependency->getPointerOperand(); Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject();
const Type* depType = dependency->getOperand(0)->getType();
unsigned depPointerSize = TD.getTypeStoreSize(depType);
// Check for aliasing // Check for aliasing.
AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0U, if (AA.alias(F->getPointerOperand(), 1, DepPointer, 1) !=
depPointer, depPointerSize); AliasAnalysis::MustAlias)
if (A != AliasAnalysis::MustAlias)
return false; return false;
// DCE instructions only used to calculate that store // DCE instructions only used to calculate that store
DeleteDeadInstruction(dependency); DeleteDeadInstruction(Dependency);
NumFastStores++; NumFastStores++;
return true; return true;
} }

View File

@ -6,3 +6,10 @@ define void @test(i32* %Q, i32* %P) {
free i32* %P free i32* %P
ret void ret void
} }
define void @test2({i32, i32}* %P) {
%Q = getelementptr {i32, i32} *%P, i32 0, i32 1
store i32 4, i32* %Q
free {i32,i32}* %P
ret void
}