mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
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:
parent
dd17b25611
commit
5e600e67b1
@ -50,7 +50,7 @@ namespace {
|
||||
bool runOnBasicBlock(BasicBlock &BB);
|
||||
bool handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep);
|
||||
bool handleEndBlock(BasicBlock &BB);
|
||||
bool RemoveUndeadPointers(Value* pointer, uint64_t killPointerSize,
|
||||
bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize,
|
||||
BasicBlock::iterator& BBI,
|
||||
SmallPtrSet<Value*, 64>& deadPointers);
|
||||
void DeleteDeadInstruction(Instruction *I,
|
||||
@ -81,93 +81,60 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
||||
TargetData &TD = getAnalysis<TargetData>();
|
||||
|
||||
// Record the last-seen store to this pointer
|
||||
DenseMap<Value*, StoreInst*> lastStore;
|
||||
|
||||
bool MadeChange = false;
|
||||
|
||||
// Do a top-down walk on the BB
|
||||
for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
|
||||
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))
|
||||
continue;
|
||||
|
||||
Value* pointer = 0;
|
||||
if (StoreInst* S = dyn_cast<StoreInst>(Inst)) {
|
||||
if (S->isVolatile())
|
||||
continue;
|
||||
pointer = S->getPointerOperand();
|
||||
} else {
|
||||
pointer = cast<FreeInst>(Inst)->getPointerOperand();
|
||||
}
|
||||
|
||||
pointer = pointer->stripPointerCasts();
|
||||
StoreInst *&last = lastStore[pointer];
|
||||
|
||||
// ... to a pointer that has been stored to before...
|
||||
if (last) {
|
||||
MemDepResult dep = MD.getDependency(Inst);
|
||||
bool deletedStore = false;
|
||||
MemDepResult InstDep = MD.getDependency(Inst);
|
||||
|
||||
// ... 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;
|
||||
}
|
||||
|
||||
// Ignore non-local stores.
|
||||
// FIXME: cross-block DSE would be fun. :)
|
||||
if (InstDep.isNonLocal()) continue;
|
||||
|
||||
// Handle frees whose dependencies are non-trivial.
|
||||
if (FreeInst *FI = dyn_cast<FreeInst>(Inst)) {
|
||||
MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep);
|
||||
continue;
|
||||
}
|
||||
|
||||
StoreInst *SI = cast<StoreInst>(Inst);
|
||||
|
||||
// If not a definite must-alias dependency, ignore it.
|
||||
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(last);
|
||||
DeleteDeadInstruction(DepStore);
|
||||
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.
|
||||
if (FreeInst* F = dyn_cast<FreeInst>(Inst)) {
|
||||
MadeChange |= handleFreeWithNonTrivialDependency(F, MD.getDependency(F));
|
||||
|
||||
// No known stores after the free.
|
||||
last = 0;
|
||||
} else {
|
||||
StoreInst* S = cast<StoreInst>(Inst);
|
||||
|
||||
// If we're storing the same value back to a pointer that we just
|
||||
// loaded from, then the store can be removed;
|
||||
if (LoadInst* L = dyn_cast<LoadInst>(S->getOperand(0))) {
|
||||
if (!S->isVolatile() && S->getParent() == L->getParent() &&
|
||||
S->getPointerOperand() == L->getPointerOperand()) {
|
||||
MemDepResult dep = MD.getDependency(S);
|
||||
if (dep.isDef() && dep.getInst() == L) {
|
||||
DeleteDeadInstruction(S);
|
||||
if (BBI != BB.begin())
|
||||
--BBI;
|
||||
NumFastStores++;
|
||||
MadeChange = true;
|
||||
} else {
|
||||
// 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;
|
||||
// If we're storing the same value back to a pointer that we just
|
||||
// loaded from, then the store can be removed.
|
||||
if (LoadInst *DepLoad = dyn_cast<LoadInst>(InstDep.getInst())) {
|
||||
if (SI->getPointerOperand() == DepLoad->getPointerOperand() &&
|
||||
SI->getOperand(0) == DepLoad) {
|
||||
DeleteDeadInstruction(SI);
|
||||
if (BBI != BB.begin())
|
||||
--BBI;
|
||||
NumFastStores++;
|
||||
MadeChange = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,29 +149,22 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||
|
||||
/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
|
||||
/// dependency is a store to a field of that structure.
|
||||
bool DSE::handleFreeWithNonTrivialDependency(FreeInst* F, MemDepResult dep) {
|
||||
TargetData &TD = getAnalysis<TargetData>();
|
||||
bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) {
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
|
||||
StoreInst* dependency = dyn_cast_or_null<StoreInst>(dep.getInst());
|
||||
if (!dependency)
|
||||
return false;
|
||||
else if (dependency->isVolatile())
|
||||
StoreInst *Dependency = dyn_cast_or_null<StoreInst>(Dep.getInst());
|
||||
if (!Dependency || Dependency->isVolatile())
|
||||
return false;
|
||||
|
||||
Value* depPointer = dependency->getPointerOperand();
|
||||
const Type* depType = dependency->getOperand(0)->getType();
|
||||
unsigned depPointerSize = TD.getTypeStoreSize(depType);
|
||||
Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject();
|
||||
|
||||
// Check for aliasing
|
||||
AliasAnalysis::AliasResult A = AA.alias(F->getPointerOperand(), ~0U,
|
||||
depPointer, depPointerSize);
|
||||
|
||||
if (A != AliasAnalysis::MustAlias)
|
||||
// Check for aliasing.
|
||||
if (AA.alias(F->getPointerOperand(), 1, DepPointer, 1) !=
|
||||
AliasAnalysis::MustAlias)
|
||||
return false;
|
||||
|
||||
// DCE instructions only used to calculate that store
|
||||
DeleteDeadInstruction(dependency);
|
||||
DeleteDeadInstruction(Dependency);
|
||||
NumFastStores++;
|
||||
return true;
|
||||
}
|
||||
|
@ -6,3 +6,10 @@ define void @test(i32* %Q, i32* %P) {
|
||||
free i32* %P
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user