mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
Reimplement the internal abstraction used by MemDep in terms
of a pointer/int pair instead of a manually bitmangled pointer. This forces clients to think a little more about checking the appropriate pieces and will be useful for internal implementation improvements later. I'm not particularly happy with this. After going through this I don't think that the clients of memdep should be exposed to the internal type at all. I'll fix this in a subsequent commit. This has no functionality change. llvm-svn: 60230
This commit is contained in:
parent
7ae87447ed
commit
e9295510b5
@ -17,6 +17,7 @@
|
|||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Function;
|
class Function;
|
||||||
@ -29,38 +30,54 @@ namespace llvm {
|
|||||||
/// It builds on alias analysis information, and tries to provide a lazy,
|
/// It builds on alias analysis information, and tries to provide a lazy,
|
||||||
/// caching interface to a common kind of alias information query.
|
/// caching interface to a common kind of alias information query.
|
||||||
class MemoryDependenceAnalysis : public FunctionPass {
|
class MemoryDependenceAnalysis : public FunctionPass {
|
||||||
|
public:
|
||||||
|
/// DepType - This enum is used to indicate what flavor of dependence this
|
||||||
|
/// is. If the type is Normal, there is an associated instruction pointer.
|
||||||
|
enum DepType {
|
||||||
|
/// Normal - This is a normal instruction dependence. The pointer member
|
||||||
|
/// of the DepResultTy pair holds the instruction.
|
||||||
|
Normal = 0,
|
||||||
|
|
||||||
|
/// None - This dependence type indicates that the query does not depend
|
||||||
|
/// on any instructions, either because it scanned to the start of the
|
||||||
|
/// function or it scanned to the definition of the memory
|
||||||
|
/// (alloca/malloc).
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// NonLocal - This marker indicates that the query has no dependency in
|
||||||
|
/// the specified block. To find out more, the client should query other
|
||||||
|
/// predecessor blocks.
|
||||||
|
NonLocal,
|
||||||
|
|
||||||
|
/// Dirty - This is an internal marker indicating that that a cache entry
|
||||||
|
/// is dirty.
|
||||||
|
Dirty
|
||||||
|
};
|
||||||
|
typedef PointerIntPair<Instruction*, 2, DepType> DepResultTy;
|
||||||
private:
|
private:
|
||||||
// A map from instructions to their dependency, with a boolean
|
// A map from instructions to their dependency, with a boolean
|
||||||
// flags for whether this mapping is confirmed or not.
|
// flags for whether this mapping is confirmed or not.
|
||||||
typedef DenseMap<Instruction*, std::pair<Instruction*, bool> > depMapType;
|
typedef DenseMap<Instruction*,
|
||||||
depMapType depGraphLocal;
|
std::pair<DepResultTy, bool> > LocalDepMapType;
|
||||||
|
LocalDepMapType LocalDeps;
|
||||||
|
|
||||||
// A map from instructions to their non-local dependencies.
|
// A map from instructions to their non-local dependencies.
|
||||||
typedef DenseMap<Instruction*,
|
typedef DenseMap<Instruction*,
|
||||||
DenseMap<BasicBlock*, Value*> > nonLocalDepMapType;
|
DenseMap<BasicBlock*, DepResultTy> > nonLocalDepMapType;
|
||||||
nonLocalDepMapType depGraphNonLocal;
|
nonLocalDepMapType depGraphNonLocal;
|
||||||
|
|
||||||
// A reverse mapping from dependencies to the dependees. This is
|
// A reverse mapping from dependencies to the dependees. This is
|
||||||
// used when removing instructions to keep the cache coherent.
|
// used when removing instructions to keep the cache coherent.
|
||||||
typedef DenseMap<Value*, SmallPtrSet<Instruction*, 4> > reverseDepMapType;
|
typedef DenseMap<DepResultTy,
|
||||||
|
SmallPtrSet<Instruction*, 4> > reverseDepMapType;
|
||||||
reverseDepMapType reverseDep;
|
reverseDepMapType reverseDep;
|
||||||
|
|
||||||
// A reverse mapping form dependencies to the non-local dependees.
|
// A reverse mapping form dependencies to the non-local dependees.
|
||||||
reverseDepMapType reverseDepNonLocal;
|
reverseDepMapType reverseDepNonLocal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Special marker indicating that the query has no dependency
|
|
||||||
// in the specified block.
|
|
||||||
static Instruction* const NonLocal;
|
|
||||||
|
|
||||||
// Special marker indicating that the query has no dependency at all
|
|
||||||
static Instruction* const None;
|
|
||||||
|
|
||||||
// Special marker indicating a dirty cache entry
|
|
||||||
static Instruction* const Dirty;
|
|
||||||
|
|
||||||
static char ID; // Class identification, replacement for typeinfo
|
|
||||||
MemoryDependenceAnalysis() : FunctionPass(&ID) {}
|
MemoryDependenceAnalysis() : FunctionPass(&ID) {}
|
||||||
|
static char ID;
|
||||||
|
|
||||||
/// Pass Implementation stuff. This doesn't do any analysis.
|
/// Pass Implementation stuff. This doesn't do any analysis.
|
||||||
///
|
///
|
||||||
@ -68,7 +85,7 @@ namespace llvm {
|
|||||||
|
|
||||||
/// Clean up memory in between runs
|
/// Clean up memory in between runs
|
||||||
void releaseMemory() {
|
void releaseMemory() {
|
||||||
depGraphLocal.clear();
|
LocalDeps.clear();
|
||||||
depGraphNonLocal.clear();
|
depGraphNonLocal.clear();
|
||||||
reverseDep.clear();
|
reverseDep.clear();
|
||||||
reverseDepNonLocal.clear();
|
reverseDepNonLocal.clear();
|
||||||
@ -81,33 +98,33 @@ namespace llvm {
|
|||||||
|
|
||||||
/// getDependency - Return the instruction on which a memory operation
|
/// getDependency - Return the instruction on which a memory operation
|
||||||
/// depends, starting with start.
|
/// depends, starting with start.
|
||||||
Instruction* getDependency(Instruction* query, Instruction* start = 0,
|
DepResultTy getDependency(Instruction *query, Instruction *start = 0,
|
||||||
BasicBlock* block = 0);
|
BasicBlock *block = 0);
|
||||||
|
|
||||||
/// getNonLocalDependency - Fills the passed-in map with the non-local
|
/// getNonLocalDependency - Fills the passed-in map with the non-local
|
||||||
/// dependencies of the queries. The map will contain NonLocal for
|
/// dependencies of the queries. The map will contain NonLocal for
|
||||||
/// blocks between the query and its dependencies.
|
/// blocks between the query and its dependencies.
|
||||||
void getNonLocalDependency(Instruction* query,
|
void getNonLocalDependency(Instruction* query,
|
||||||
DenseMap<BasicBlock*, Value*>& resp);
|
DenseMap<BasicBlock*, DepResultTy> &resp);
|
||||||
|
|
||||||
/// removeInstruction - Remove an instruction from the dependence analysis,
|
/// removeInstruction - Remove an instruction from the dependence analysis,
|
||||||
/// updating the dependence of instructions that previously depended on it.
|
/// updating the dependence of instructions that previously depended on it.
|
||||||
void removeInstruction(Instruction* rem);
|
void removeInstruction(Instruction *InstToRemove);
|
||||||
|
|
||||||
/// dropInstruction - Remove an instruction from the analysis, making
|
/// dropInstruction - Remove an instruction from the analysis, making
|
||||||
/// absolutely conservative assumptions when updating the cache. This is
|
/// absolutely conservative assumptions when updating the cache. This is
|
||||||
/// useful, for example when an instruction is changed rather than removed.
|
/// useful, for example when an instruction is changed rather than removed.
|
||||||
void dropInstruction(Instruction* drop);
|
void dropInstruction(Instruction *InstToDrop);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// verifyRemoved - Verify that the specified instruction does not occur
|
/// verifyRemoved - Verify that the specified instruction does not occur
|
||||||
/// in our internal data structures.
|
/// in our internal data structures.
|
||||||
void verifyRemoved(Instruction *Inst) const;
|
void verifyRemoved(Instruction *Inst) const;
|
||||||
|
|
||||||
Instruction* getCallSiteDependency(CallSite C, Instruction* start,
|
DepResultTy getCallSiteDependency(CallSite C, Instruction* start,
|
||||||
BasicBlock* block);
|
BasicBlock* block);
|
||||||
void nonLocalHelper(Instruction* query, BasicBlock* block,
|
void nonLocalHelper(Instruction* query, BasicBlock* block,
|
||||||
DenseMap<BasicBlock*, Value*>& resp);
|
DenseMap<BasicBlock*, DepResultTy>& resp);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -41,10 +41,6 @@ STATISTIC(NumUncacheNonlocal, "Number of uncached non-local responses");
|
|||||||
|
|
||||||
char MemoryDependenceAnalysis::ID = 0;
|
char MemoryDependenceAnalysis::ID = 0;
|
||||||
|
|
||||||
Instruction* const MemoryDependenceAnalysis::NonLocal = (Instruction*)-3;
|
|
||||||
Instruction* const MemoryDependenceAnalysis::None = (Instruction*)-4;
|
|
||||||
Instruction* const MemoryDependenceAnalysis::Dirty = (Instruction*)-5;
|
|
||||||
|
|
||||||
// Register this pass...
|
// Register this pass...
|
||||||
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
|
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
|
||||||
"Memory Dependence Analysis", false, true);
|
"Memory Dependence Analysis", false, true);
|
||||||
@ -52,18 +48,19 @@ static RegisterPass<MemoryDependenceAnalysis> X("memdep",
|
|||||||
/// verifyRemoved - Verify that the specified instruction does not occur
|
/// verifyRemoved - Verify that the specified instruction does not occur
|
||||||
/// in our internal data structures.
|
/// in our internal data structures.
|
||||||
void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const {
|
void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const {
|
||||||
for (depMapType::const_iterator I = depGraphLocal.begin(),
|
for (LocalDepMapType::const_iterator I = LocalDeps.begin(),
|
||||||
E = depGraphLocal.end(); I != E; ++I) {
|
E = LocalDeps.end(); I != E; ++I) {
|
||||||
assert(I->first != D && "Inst occurs in data structures");
|
assert(I->first != D && "Inst occurs in data structures");
|
||||||
assert(I->second.first != D && "Inst occurs in data structures");
|
assert(I->second.first.getPointer() != D &&
|
||||||
|
"Inst occurs in data structures");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nonLocalDepMapType::const_iterator I = depGraphNonLocal.begin(),
|
for (nonLocalDepMapType::const_iterator I = depGraphNonLocal.begin(),
|
||||||
E = depGraphNonLocal.end(); I != E; ++I) {
|
E = depGraphNonLocal.end(); I != E; ++I) {
|
||||||
assert(I->first != D && "Inst occurs in data structures");
|
assert(I->first != D && "Inst occurs in data structures");
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator II = I->second.begin(),
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator II = I->second.begin(),
|
||||||
EE = I->second.end(); II != EE; ++II)
|
EE = I->second.end(); II != EE; ++II)
|
||||||
assert(II->second != D && "Inst occurs in data structures");
|
assert(II->second.getPointer() != D && "Inst occurs in data structures");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (reverseDepMapType::const_iterator I = reverseDep.begin(),
|
for (reverseDepMapType::const_iterator I = reverseDep.begin(),
|
||||||
@ -90,12 +87,10 @@ void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
|||||||
|
|
||||||
/// getCallSiteDependency - Private helper for finding the local dependencies
|
/// getCallSiteDependency - Private helper for finding the local dependencies
|
||||||
/// of a call site.
|
/// of a call site.
|
||||||
Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
|
MemoryDependenceAnalysis::DepResultTy
|
||||||
Instruction* start,
|
MemoryDependenceAnalysis::
|
||||||
BasicBlock* block) {
|
getCallSiteDependency(CallSite C, Instruction *start, BasicBlock *block) {
|
||||||
|
std::pair<DepResultTy, bool> &cachedResult = LocalDeps[C.getInstruction()];
|
||||||
std::pair<Instruction*, bool>& cachedResult =
|
|
||||||
depGraphLocal[C.getInstruction()];
|
|
||||||
AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
|
AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
|
||||||
TargetData& TD = getAnalysis<TargetData>();
|
TargetData& TD = getAnalysis<TargetData>();
|
||||||
BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin();
|
BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin();
|
||||||
@ -141,11 +136,11 @@ Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
|
|||||||
AA.getModRefBehavior(CallSite::get(QI));
|
AA.getModRefBehavior(CallSite::get(QI));
|
||||||
if (result != AliasAnalysis::DoesNotAccessMemory) {
|
if (result != AliasAnalysis::DoesNotAccessMemory) {
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = QI;
|
cachedResult.first = DepResultTy(QI, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[QI].insert(C.getInstruction());
|
reverseDep[DepResultTy(QI, Normal)].insert(C.getInstruction());
|
||||||
}
|
}
|
||||||
return QI;
|
return DepResultTy(QI, Normal);
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -154,33 +149,33 @@ Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
|
|||||||
|
|
||||||
if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) {
|
if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) {
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = QI;
|
cachedResult.first = DepResultTy(QI, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[QI].insert(C.getInstruction());
|
reverseDep[DepResultTy(QI, Normal)].insert(C.getInstruction());
|
||||||
}
|
}
|
||||||
return QI;
|
return DepResultTy(QI, Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No dependence found
|
// No dependence found
|
||||||
cachedResult.first = NonLocal;
|
cachedResult.first = DepResultTy(0, NonLocal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[NonLocal].insert(C.getInstruction());
|
reverseDep[DepResultTy(0, NonLocal)].insert(C.getInstruction());
|
||||||
return NonLocal;
|
return DepResultTy(0, NonLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// nonLocalHelper - Private helper used to calculate non-local dependencies
|
/// nonLocalHelper - Private helper used to calculate non-local dependencies
|
||||||
/// by doing DFS on the predecessors of a block to find its dependencies
|
/// by doing DFS on the predecessors of a block to find its dependencies.
|
||||||
void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
||||||
BasicBlock* block,
|
BasicBlock* block,
|
||||||
DenseMap<BasicBlock*, Value*>& resp) {
|
DenseMap<BasicBlock*, DepResultTy> &resp) {
|
||||||
// Set of blocks that we've already visited in our DFS
|
// Set of blocks that we've already visited in our DFS
|
||||||
SmallPtrSet<BasicBlock*, 4> visited;
|
SmallPtrSet<BasicBlock*, 4> visited;
|
||||||
// If we're updating a dirtied cache entry, we don't need to reprocess
|
// If we're updating a dirtied cache entry, we don't need to reprocess
|
||||||
// already computed entries.
|
// already computed entries.
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = resp.begin(),
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator I = resp.begin(),
|
||||||
E = resp.end(); I != E; ++I)
|
E = resp.end(); I != E; ++I)
|
||||||
if (I->second != Dirty)
|
if (I->second.getInt() != Dirty)
|
||||||
visited.insert(I->first);
|
visited.insert(I->first);
|
||||||
|
|
||||||
// Current stack of the DFS
|
// Current stack of the DFS
|
||||||
@ -204,8 +199,8 @@ void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
|||||||
if (BB != block) {
|
if (BB != block) {
|
||||||
visited.insert(BB);
|
visited.insert(BB);
|
||||||
|
|
||||||
Instruction* localDep = getDependency(query, 0, BB);
|
DepResultTy localDep = getDependency(query, 0, BB);
|
||||||
if (localDep != NonLocal) {
|
if (localDep.getInt() != NonLocal) {
|
||||||
resp.insert(std::make_pair(BB, localDep));
|
resp.insert(std::make_pair(BB, localDep));
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
|
|
||||||
@ -217,8 +212,8 @@ void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
|||||||
} else if (BB == block) {
|
} else if (BB == block) {
|
||||||
visited.insert(BB);
|
visited.insert(BB);
|
||||||
|
|
||||||
Instruction* localDep = getDependency(query, 0, BB);
|
DepResultTy localDep = getDependency(query, 0, BB);
|
||||||
if (localDep != query)
|
if (localDep != DepResultTy(query, Normal))
|
||||||
resp.insert(std::make_pair(BB, localDep));
|
resp.insert(std::make_pair(BB, localDep));
|
||||||
|
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
@ -246,12 +241,12 @@ void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
|||||||
// If we didn't insert because we have no predecessors, then this
|
// If we didn't insert because we have no predecessors, then this
|
||||||
// query has no dependency at all.
|
// query has no dependency at all.
|
||||||
else if (!inserted && !predOnStack) {
|
else if (!inserted && !predOnStack) {
|
||||||
resp.insert(std::make_pair(BB, None));
|
resp.insert(std::make_pair(BB, DepResultTy(0, None)));
|
||||||
// If we didn't insert because our predecessors are already on the stack,
|
// If we didn't insert because our predecessors are already on the stack,
|
||||||
// then we might still have a dependency, but it will be discovered during
|
// then we might still have a dependency, but it will be discovered during
|
||||||
// backtracking.
|
// backtracking.
|
||||||
} else if (!inserted && predOnStack){
|
} else if (!inserted && predOnStack){
|
||||||
resp.insert(std::make_pair(BB, NonLocal));
|
resp.insert(std::make_pair(BB, DepResultTy(0, NonLocal)));
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
@ -262,21 +257,21 @@ void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
|
|||||||
/// dependencies of the queries. The map will contain NonLocal for
|
/// dependencies of the queries. The map will contain NonLocal for
|
||||||
/// blocks between the query and its dependencies.
|
/// blocks between the query and its dependencies.
|
||||||
void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
|
void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
|
||||||
DenseMap<BasicBlock*, Value*>& resp) {
|
DenseMap<BasicBlock*, DepResultTy> &resp) {
|
||||||
if (depGraphNonLocal.count(query)) {
|
if (depGraphNonLocal.count(query)) {
|
||||||
DenseMap<BasicBlock*, Value*>& cached = depGraphNonLocal[query];
|
DenseMap<BasicBlock*, DepResultTy> &cached = depGraphNonLocal[query];
|
||||||
NumCacheNonlocal++;
|
NumCacheNonlocal++;
|
||||||
|
|
||||||
SmallVector<BasicBlock*, 4> dirtied;
|
SmallVector<BasicBlock*, 4> dirtied;
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = cached.begin(),
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator I = cached.begin(),
|
||||||
E = cached.end(); I != E; ++I)
|
E = cached.end(); I != E; ++I)
|
||||||
if (I->second == Dirty)
|
if (I->second.getInt() == Dirty)
|
||||||
dirtied.push_back(I->first);
|
dirtied.push_back(I->first);
|
||||||
|
|
||||||
for (SmallVector<BasicBlock*, 4>::iterator I = dirtied.begin(),
|
for (SmallVector<BasicBlock*, 4>::iterator I = dirtied.begin(),
|
||||||
E = dirtied.end(); I != E; ++I) {
|
E = dirtied.end(); I != E; ++I) {
|
||||||
Instruction* localDep = getDependency(query, 0, *I);
|
DepResultTy localDep = getDependency(query, 0, *I);
|
||||||
if (localDep != NonLocal)
|
if (localDep.getInt() != NonLocal)
|
||||||
cached[*I] = localDep;
|
cached[*I] = localDep;
|
||||||
else {
|
else {
|
||||||
cached.erase(*I);
|
cached.erase(*I);
|
||||||
@ -287,8 +282,8 @@ void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
|
|||||||
resp = cached;
|
resp = cached;
|
||||||
|
|
||||||
// Update the reverse non-local dependency cache
|
// Update the reverse non-local dependency cache
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = resp.begin(), E = resp.end();
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator I = resp.begin(),
|
||||||
I != E; ++I)
|
E = resp.end(); I != E; ++I)
|
||||||
reverseDepNonLocal[I->second].insert(query);
|
reverseDepNonLocal[I->second].insert(query);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -299,8 +294,8 @@ void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
|
|||||||
nonLocalHelper(query, query->getParent(), resp);
|
nonLocalHelper(query, query->getParent(), resp);
|
||||||
|
|
||||||
// Update the non-local dependency cache
|
// Update the non-local dependency cache
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = resp.begin(), E = resp.end();
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator I = resp.begin(),
|
||||||
I != E; ++I) {
|
E = resp.end(); I != E; ++I) {
|
||||||
depGraphNonLocal[query].insert(*I);
|
depGraphNonLocal[query].insert(*I);
|
||||||
reverseDepNonLocal[I->second].insert(query);
|
reverseDepNonLocal[I->second].insert(query);
|
||||||
}
|
}
|
||||||
@ -309,21 +304,24 @@ void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
|
|||||||
/// getDependency - Return the instruction on which a memory operation
|
/// getDependency - Return the instruction on which a memory operation
|
||||||
/// depends. The local parameter indicates if the query should only
|
/// depends. The local parameter indicates if the query should only
|
||||||
/// evaluate dependencies within the same basic block.
|
/// evaluate dependencies within the same basic block.
|
||||||
Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
MemoryDependenceAnalysis::DepResultTy
|
||||||
Instruction* start,
|
MemoryDependenceAnalysis::getDependency(Instruction *query,
|
||||||
BasicBlock* block) {
|
Instruction *start,
|
||||||
|
BasicBlock *block) {
|
||||||
// Start looking for dependencies with the queried inst
|
// Start looking for dependencies with the queried inst
|
||||||
BasicBlock::iterator QI = query;
|
BasicBlock::iterator QI = query;
|
||||||
|
|
||||||
// Check for a cached result
|
// Check for a cached result
|
||||||
std::pair<Instruction*, bool>& cachedResult = depGraphLocal[query];
|
std::pair<DepResultTy, bool>& cachedResult = LocalDeps[query];
|
||||||
// If we have a _confirmed_ cached entry, return it
|
// If we have a _confirmed_ cached entry, return it
|
||||||
if (!block && !start) {
|
if (!block && !start) {
|
||||||
if (cachedResult.second)
|
if (cachedResult.second)
|
||||||
return cachedResult.first;
|
return cachedResult.first;
|
||||||
else if (cachedResult.first && cachedResult.first != NonLocal)
|
else if (cachedResult.first.getInt() == Normal &&
|
||||||
// If we have an unconfirmed cached entry, we can start our search from there
|
cachedResult.first.getPointer())
|
||||||
QI = cachedResult.first;
|
// If we have an unconfirmed cached entry, we can start our search from
|
||||||
|
// it.
|
||||||
|
QI = cachedResult.first.getPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start)
|
if (start)
|
||||||
@ -357,9 +355,9 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
} else if (CallSite::get(query).getInstruction() != 0)
|
} else if (CallSite::get(query).getInstruction() != 0)
|
||||||
return getCallSiteDependency(CallSite::get(query), start, block);
|
return getCallSiteDependency(CallSite::get(query), start, block);
|
||||||
else if (isa<AllocationInst>(query))
|
else if (isa<AllocationInst>(query))
|
||||||
return None;
|
return DepResultTy(0, None);
|
||||||
else
|
else
|
||||||
return None;
|
return DepResultTy(0, None);
|
||||||
|
|
||||||
BasicBlock::iterator blockBegin = block ? block->begin()
|
BasicBlock::iterator blockBegin = block ? block->begin()
|
||||||
: query->getParent()->begin();
|
: query->getParent()->begin();
|
||||||
@ -375,12 +373,12 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
// All volatile loads/stores depend on each other
|
// All volatile loads/stores depend on each other
|
||||||
if (queryIsVolatile && S->isVolatile()) {
|
if (queryIsVolatile && S->isVolatile()) {
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = S;
|
cachedResult.first = DepResultTy(S, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[S].insert(query);
|
reverseDep[DepResultTy(S, Normal)].insert(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return S;
|
return DepResultTy(S, Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer = S->getPointerOperand();
|
pointer = S->getPointerOperand();
|
||||||
@ -389,12 +387,12 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
// All volatile loads/stores depend on each other
|
// All volatile loads/stores depend on each other
|
||||||
if (queryIsVolatile && L->isVolatile()) {
|
if (queryIsVolatile && L->isVolatile()) {
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = L;
|
cachedResult.first = DepResultTy(L, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[L].insert(query);
|
reverseDep[DepResultTy(L, Normal)].insert(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return L;
|
return DepResultTy(L, Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer = L->getPointerOperand();
|
pointer = L->getPointerOperand();
|
||||||
@ -417,7 +415,7 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
} else if (CallSite::get(QI).getInstruction() != 0) {
|
} else if (CallSite::get(QI).getInstruction() != 0) {
|
||||||
// Call insts need special handling. Check if they can modify our pointer
|
// Call insts need special handling. Check if they can modify our pointer
|
||||||
AliasAnalysis::ModRefResult MR = AA.getModRefInfo(CallSite::get(QI),
|
AliasAnalysis::ModRefResult MR = AA.getModRefInfo(CallSite::get(QI),
|
||||||
dependee, dependeeSize);
|
dependee, dependeeSize);
|
||||||
|
|
||||||
if (MR != AliasAnalysis::NoModRef) {
|
if (MR != AliasAnalysis::NoModRef) {
|
||||||
// Loads don't depend on read-only calls
|
// Loads don't depend on read-only calls
|
||||||
@ -425,12 +423,11 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = QI;
|
cachedResult.first = DepResultTy(QI, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[QI].insert(query);
|
reverseDep[DepResultTy(QI, Normal)].insert(query);
|
||||||
}
|
}
|
||||||
|
return DepResultTy(QI, Normal);
|
||||||
return QI;
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -448,64 +445,63 @@ Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = QI;
|
cachedResult.first = DepResultTy(QI, Normal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[QI].insert(query);
|
reverseDep[DepResultTy(QI, Normal)].insert(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QI;
|
return DepResultTy(QI, Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we found nothing, return the non-local flag
|
// If we found nothing, return the non-local flag
|
||||||
if (!start && !block) {
|
if (!start && !block) {
|
||||||
cachedResult.first = NonLocal;
|
cachedResult.first = DepResultTy(0, NonLocal);
|
||||||
cachedResult.second = true;
|
cachedResult.second = true;
|
||||||
reverseDep[NonLocal].insert(query);
|
reverseDep[DepResultTy(0, NonLocal)].insert(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NonLocal;
|
return DepResultTy(0, NonLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dropInstruction - Remove an instruction from the analysis, making
|
/// dropInstruction - Remove an instruction from the analysis, making
|
||||||
/// absolutely conservative assumptions when updating the cache. This is
|
/// absolutely conservative assumptions when updating the cache. This is
|
||||||
/// useful, for example when an instruction is changed rather than removed.
|
/// useful, for example when an instruction is changed rather than removed.
|
||||||
void MemoryDependenceAnalysis::dropInstruction(Instruction* drop) {
|
void MemoryDependenceAnalysis::dropInstruction(Instruction* drop) {
|
||||||
depMapType::iterator depGraphEntry = depGraphLocal.find(drop);
|
LocalDepMapType::iterator depGraphEntry = LocalDeps.find(drop);
|
||||||
if (depGraphEntry != depGraphLocal.end())
|
if (depGraphEntry != LocalDeps.end())
|
||||||
reverseDep[depGraphEntry->second.first].erase(drop);
|
reverseDep[depGraphEntry->second.first].erase(drop);
|
||||||
|
|
||||||
// Drop dependency information for things that depended on this instr
|
// Drop dependency information for things that depended on this instr
|
||||||
SmallPtrSet<Instruction*, 4>& set = reverseDep[drop];
|
SmallPtrSet<Instruction*, 4>& set = reverseDep[DepResultTy(drop, Normal)];
|
||||||
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
depGraphLocal.erase(*I);
|
LocalDeps.erase(*I);
|
||||||
|
|
||||||
depGraphLocal.erase(drop);
|
LocalDeps.erase(drop);
|
||||||
reverseDep.erase(drop);
|
reverseDep.erase(DepResultTy(drop, Normal));
|
||||||
|
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator DI =
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
|
||||||
depGraphNonLocal[drop].begin(), DE = depGraphNonLocal[drop].end();
|
depGraphNonLocal[drop].begin(), DE = depGraphNonLocal[drop].end();
|
||||||
DI != DE; ++DI)
|
DI != DE; ++DI)
|
||||||
if (DI->second != None)
|
if (DI->second.getInt() != None)
|
||||||
reverseDepNonLocal[DI->second].erase(drop);
|
reverseDepNonLocal[DI->second].erase(drop);
|
||||||
|
|
||||||
if (reverseDepNonLocal.count(drop)) {
|
if (reverseDepNonLocal.count(DepResultTy(drop, Normal))) {
|
||||||
SmallPtrSet<Instruction*, 4>& set = reverseDepNonLocal[drop];
|
SmallPtrSet<Instruction*, 4>& set =
|
||||||
|
reverseDepNonLocal[DepResultTy(drop, Normal)];
|
||||||
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator DI =
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
|
||||||
depGraphNonLocal[*I].begin(), DE = depGraphNonLocal[*I].end();
|
depGraphNonLocal[*I].begin(), DE = depGraphNonLocal[*I].end();
|
||||||
DI != DE; ++DI)
|
DI != DE; ++DI)
|
||||||
if (DI->second == drop)
|
if (DI->second == DepResultTy(drop, Normal))
|
||||||
DI->second = Dirty;
|
DI->second = DepResultTy(0, Dirty);
|
||||||
}
|
}
|
||||||
|
|
||||||
reverseDepNonLocal.erase(drop);
|
reverseDepNonLocal.erase(DepResultTy(drop, Normal));
|
||||||
nonLocalDepMapType::iterator I = depGraphNonLocal.find(drop);
|
depGraphNonLocal.erase(drop);
|
||||||
if (I != depGraphNonLocal.end())
|
|
||||||
depGraphNonLocal.erase(I);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// removeInstruction - Remove an instruction from the dependence analysis,
|
/// removeInstruction - Remove an instruction from the dependence analysis,
|
||||||
@ -514,10 +510,10 @@ void MemoryDependenceAnalysis::dropInstruction(Instruction* drop) {
|
|||||||
void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
||||||
// Walk through the Non-local dependencies, removing this one as the value
|
// Walk through the Non-local dependencies, removing this one as the value
|
||||||
// for any cached queries.
|
// for any cached queries.
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator DI =
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
|
||||||
depGraphNonLocal[RemInst].begin(), DE = depGraphNonLocal[RemInst].end();
|
depGraphNonLocal[RemInst].begin(), DE = depGraphNonLocal[RemInst].end();
|
||||||
DI != DE; ++DI)
|
DI != DE; ++DI)
|
||||||
if (DI->second != None)
|
if (DI->second.getInt() != None)
|
||||||
reverseDepNonLocal[DI->second].erase(RemInst);
|
reverseDepNonLocal[DI->second].erase(RemInst);
|
||||||
|
|
||||||
// Shortly after this, we will look for things that depend on RemInst. In
|
// Shortly after this, we will look for things that depend on RemInst. In
|
||||||
@ -525,36 +521,34 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
|||||||
// could completely delete any entries that depend on this, but it is better
|
// could completely delete any entries that depend on this, but it is better
|
||||||
// to make a more accurate approximation where possible. Compute that better
|
// to make a more accurate approximation where possible. Compute that better
|
||||||
// approximation if we can.
|
// approximation if we can.
|
||||||
Instruction *NewDependency = 0;
|
DepResultTy NewDependency;
|
||||||
bool NewDependencyConfirmed = false;
|
bool NewDependencyConfirmed = false;
|
||||||
|
|
||||||
// If we have a cached local dependence query for this instruction, remove it.
|
// If we have a cached local dependence query for this instruction, remove it.
|
||||||
//
|
//
|
||||||
depMapType::iterator LocalDepEntry = depGraphLocal.find(RemInst);
|
LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst);
|
||||||
if (LocalDepEntry != depGraphLocal.end()) {
|
if (LocalDepEntry != LocalDeps.end()) {
|
||||||
Instruction *LocalDepInst = LocalDepEntry->second.first;
|
DepResultTy LocalDep = LocalDepEntry->second.first;
|
||||||
bool IsConfirmed = LocalDepEntry->second.second;
|
bool IsConfirmed = LocalDepEntry->second.second;
|
||||||
|
|
||||||
// Remove this local dependency info.
|
// Remove this local dependency info.
|
||||||
depGraphLocal.erase(LocalDepEntry);
|
LocalDeps.erase(LocalDepEntry);
|
||||||
|
|
||||||
// Remove us from DepInst's reverse set now that the local dep info is gone.
|
// Remove us from DepInst's reverse set now that the local dep info is gone.
|
||||||
reverseDep[LocalDepInst].erase(RemInst);
|
reverseDep[LocalDep].erase(RemInst);
|
||||||
|
|
||||||
// If we have unconfirmed info, don't trust it.
|
// If we have unconfirmed info, don't trust it.
|
||||||
if (IsConfirmed) {
|
if (IsConfirmed) {
|
||||||
// If we have a confirmed non-local flag, use it.
|
// If we have a confirmed non-local flag, use it.
|
||||||
if (LocalDepInst == NonLocal || LocalDepInst == None) {
|
if (LocalDep.getInt() == NonLocal || LocalDep.getInt() == None) {
|
||||||
// The only time this dependency is confirmed is if it is non-local.
|
// The only time this dependency is confirmed is if it is non-local.
|
||||||
NewDependency = LocalDepInst;
|
NewDependency = LocalDep;
|
||||||
NewDependencyConfirmed = true;
|
NewDependencyConfirmed = true;
|
||||||
} else {
|
} else {
|
||||||
// If we have dep info for RemInst, set them to it.
|
// If we have dep info for RemInst, set them to it.
|
||||||
NewDependency = next(BasicBlock::iterator(LocalDepInst));
|
Instruction *NDI = next(BasicBlock::iterator(LocalDep.getPointer()));
|
||||||
|
if (NDI != RemInst) // Don't use RemInst for the new dependency!
|
||||||
// Don't use RI for the new dependency!
|
NewDependency = DepResultTy(NDI, Normal);
|
||||||
if (NewDependency == RemInst)
|
|
||||||
NewDependency = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -563,12 +557,13 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
|||||||
// use the immediate successor of RemInst. We use the successor because
|
// use the immediate successor of RemInst. We use the successor because
|
||||||
// getDependence starts by checking the immediate predecessor of what is in
|
// getDependence starts by checking the immediate predecessor of what is in
|
||||||
// the cache.
|
// the cache.
|
||||||
if (NewDependency == 0)
|
if (NewDependency == DepResultTy(0, Normal))
|
||||||
NewDependency = next(BasicBlock::iterator(RemInst));
|
NewDependency = DepResultTy(next(BasicBlock::iterator(RemInst)), Normal);
|
||||||
|
|
||||||
// Loop over all of the things that depend on the instruction we're removing.
|
// Loop over all of the things that depend on the instruction we're removing.
|
||||||
//
|
//
|
||||||
reverseDepMapType::iterator ReverseDepIt = reverseDep.find(RemInst);
|
reverseDepMapType::iterator ReverseDepIt =
|
||||||
|
reverseDep.find(DepResultTy(RemInst, Normal));
|
||||||
if (ReverseDepIt != reverseDep.end()) {
|
if (ReverseDepIt != reverseDep.end()) {
|
||||||
SmallPtrSet<Instruction*, 4> &ReverseDeps = ReverseDepIt->second;
|
SmallPtrSet<Instruction*, 4> &ReverseDeps = ReverseDepIt->second;
|
||||||
for (SmallPtrSet<Instruction*, 4>::iterator I = ReverseDeps.begin(),
|
for (SmallPtrSet<Instruction*, 4>::iterator I = ReverseDeps.begin(),
|
||||||
@ -580,28 +575,29 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
|||||||
if (InstDependingOnRemInst == RemInst) continue;
|
if (InstDependingOnRemInst == RemInst) continue;
|
||||||
|
|
||||||
// Insert the new dependencies.
|
// Insert the new dependencies.
|
||||||
depGraphLocal[InstDependingOnRemInst] =
|
LocalDeps[InstDependingOnRemInst] =
|
||||||
std::make_pair(NewDependency, NewDependencyConfirmed);
|
std::make_pair(NewDependency, NewDependencyConfirmed);
|
||||||
|
|
||||||
// If our NewDependency is an instruction, make sure to remember that new
|
// If our NewDependency is an instruction, make sure to remember that new
|
||||||
// things depend on it.
|
// things depend on it.
|
||||||
if (NewDependency != NonLocal && NewDependency != None)
|
// FIXME: Just insert all deps!
|
||||||
|
if (NewDependency.getInt() != NonLocal && NewDependency.getInt() != None)
|
||||||
reverseDep[NewDependency].insert(InstDependingOnRemInst);
|
reverseDep[NewDependency].insert(InstDependingOnRemInst);
|
||||||
}
|
}
|
||||||
reverseDep.erase(RemInst);
|
reverseDep.erase(DepResultTy(RemInst, Normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReverseDepIt = reverseDepNonLocal.find(RemInst);
|
ReverseDepIt = reverseDepNonLocal.find(DepResultTy(RemInst, Normal));
|
||||||
if (ReverseDepIt != reverseDepNonLocal.end()) {
|
if (ReverseDepIt != reverseDepNonLocal.end()) {
|
||||||
SmallPtrSet<Instruction*, 4>& set = ReverseDepIt->second;
|
SmallPtrSet<Instruction*, 4>& set = ReverseDepIt->second;
|
||||||
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator DI =
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator DI =
|
||||||
depGraphNonLocal[*I].begin(), DE = depGraphNonLocal[*I].end();
|
depGraphNonLocal[*I].begin(), DE = depGraphNonLocal[*I].end();
|
||||||
DI != DE; ++DI)
|
DI != DE; ++DI)
|
||||||
if (DI->second == RemInst)
|
if (DI->second == DepResultTy(RemInst, Normal))
|
||||||
DI->second = Dirty;
|
DI->second = DepResultTy(0, Dirty);
|
||||||
reverseDepNonLocal.erase(RemInst);
|
reverseDepNonLocal.erase(ReverseDepIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
depGraphNonLocal.erase(RemInst);
|
depGraphNonLocal.erase(RemInst);
|
||||||
|
@ -46,9 +46,11 @@ namespace {
|
|||||||
Changed |= runOnBasicBlock(*I);
|
Changed |= runOnBasicBlock(*I);
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef MemoryDependenceAnalysis::DepResultTy DepResultTy;
|
||||||
|
|
||||||
bool runOnBasicBlock(BasicBlock &BB);
|
bool runOnBasicBlock(BasicBlock &BB);
|
||||||
bool handleFreeWithNonTrivialDependency(FreeInst *F, Instruction *Dep);
|
bool handleFreeWithNonTrivialDependency(FreeInst *F, DepResultTy Dep);
|
||||||
bool handleEndBlock(BasicBlock &BB);
|
bool handleEndBlock(BasicBlock &BB);
|
||||||
bool RemoveUndeadPointers(Value* pointer, uint64_t killPointerSize,
|
bool RemoveUndeadPointers(Value* pointer, uint64_t killPointerSize,
|
||||||
BasicBlock::iterator& BBI,
|
BasicBlock::iterator& BBI,
|
||||||
@ -108,17 +110,16 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
|||||||
|
|
||||||
// ... to a pointer that has been stored to before...
|
// ... to a pointer that has been stored to before...
|
||||||
if (last) {
|
if (last) {
|
||||||
Instruction* dep = MD.getDependency(Inst);
|
DepResultTy dep = MD.getDependency(Inst);
|
||||||
bool deletedStore = false;
|
bool deletedStore = false;
|
||||||
|
|
||||||
// ... and no other memory dependencies are between them....
|
// ... and no other memory dependencies are between them....
|
||||||
while (dep != MemoryDependenceAnalysis::None &&
|
while (dep.getInt() == MemoryDependenceAnalysis::Normal &&
|
||||||
dep != MemoryDependenceAnalysis::NonLocal &&
|
isa<StoreInst>(dep.getPointer())) {
|
||||||
isa<StoreInst>(dep)) {
|
if (dep.getPointer() != last ||
|
||||||
if (dep != last ||
|
|
||||||
TD.getTypeStoreSize(last->getOperand(0)->getType()) >
|
TD.getTypeStoreSize(last->getOperand(0)->getType()) >
|
||||||
TD.getTypeStoreSize(Inst->getOperand(0)->getType())) {
|
TD.getTypeStoreSize(Inst->getOperand(0)->getType())) {
|
||||||
dep = MD.getDependency(Inst, dep);
|
dep = MD.getDependency(Inst, dep.getPointer());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,14 +152,14 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
|||||||
// 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* L = dyn_cast<LoadInst>(S->getOperand(0))) {
|
||||||
// FIXME: Don't do dep query if Parents don't match and other stuff!
|
// FIXME: Don't do dep query if Parents don't match and other stuff!
|
||||||
Instruction* dep = MD.getDependency(S);
|
DepResultTy dep = MD.getDependency(S);
|
||||||
DominatorTree& DT = getAnalysis<DominatorTree>();
|
DominatorTree& DT = getAnalysis<DominatorTree>();
|
||||||
|
|
||||||
if (!S->isVolatile() && S->getParent() == L->getParent() &&
|
if (!S->isVolatile() && S->getParent() == L->getParent() &&
|
||||||
S->getPointerOperand() == L->getPointerOperand() &&
|
S->getPointerOperand() == L->getPointerOperand() &&
|
||||||
(dep == MemoryDependenceAnalysis::None ||
|
(dep.getInt() == MemoryDependenceAnalysis::None ||
|
||||||
dep == MemoryDependenceAnalysis::NonLocal ||
|
dep.getInt() == MemoryDependenceAnalysis::NonLocal ||
|
||||||
DT.dominates(dep, L))) {
|
DT.dominates(dep.getPointer(), L))) {
|
||||||
|
|
||||||
DeleteDeadInstruction(S);
|
DeleteDeadInstruction(S);
|
||||||
if (!isa<TerminatorInst>(BB.begin()))
|
if (!isa<TerminatorInst>(BB.begin()))
|
||||||
@ -184,15 +185,15 @@ 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, Instruction* dep) {
|
bool DSE::handleFreeWithNonTrivialDependency(FreeInst* F, DepResultTy dep) {
|
||||||
TargetData &TD = getAnalysis<TargetData>();
|
TargetData &TD = getAnalysis<TargetData>();
|
||||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||||
|
|
||||||
if (dep == MemoryDependenceAnalysis::None ||
|
if (dep.getInt() == MemoryDependenceAnalysis::None ||
|
||||||
dep == MemoryDependenceAnalysis::NonLocal)
|
dep.getInt() == MemoryDependenceAnalysis::NonLocal)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
StoreInst* dependency = dyn_cast<StoreInst>(dep);
|
StoreInst* dependency = dyn_cast<StoreInst>(dep.getPointer());
|
||||||
if (!dependency)
|
if (!dependency)
|
||||||
return false;
|
return false;
|
||||||
else if (dependency->isVolatile())
|
else if (dependency->isVolatile())
|
||||||
|
@ -456,19 +456,21 @@ uint32_t ValueTable::lookup_or_add(Value* V) {
|
|||||||
return nextValueNumber++;
|
return nextValueNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction* local_dep = MD->getDependency(C);
|
MemoryDependenceAnalysis::DepResultTy local_dep = MD->getDependency(C);
|
||||||
|
|
||||||
if (local_dep == MemoryDependenceAnalysis::None) {
|
if (local_dep.getInt() == MemoryDependenceAnalysis::None) {
|
||||||
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
||||||
return nextValueNumber++;
|
return nextValueNumber++;
|
||||||
} else if (local_dep != MemoryDependenceAnalysis::NonLocal) {
|
} else if (local_dep.getInt() != MemoryDependenceAnalysis::NonLocal) {
|
||||||
if (!isa<CallInst>(local_dep)) {
|
// FIXME: INDENT PROPERLY!
|
||||||
|
if (!isa<CallInst>(local_dep.getPointer())) {
|
||||||
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
||||||
return nextValueNumber++;
|
return nextValueNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallInst* local_cdep = cast<CallInst>(local_dep);
|
CallInst* local_cdep = cast<CallInst>(local_dep.getPointer());
|
||||||
|
|
||||||
|
// FIXME: INDENT PROPERLY.
|
||||||
if (local_cdep->getCalledFunction() != C->getCalledFunction() ||
|
if (local_cdep->getCalledFunction() != C->getCalledFunction() ||
|
||||||
local_cdep->getNumOperands() != C->getNumOperands()) {
|
local_cdep->getNumOperands() != C->getNumOperands()) {
|
||||||
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
||||||
@ -493,19 +495,20 @@ uint32_t ValueTable::lookup_or_add(Value* V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DenseMap<BasicBlock*, Value*> deps;
|
DenseMap<BasicBlock*, MemoryDependenceAnalysis::DepResultTy> deps;
|
||||||
MD->getNonLocalDependency(C, deps);
|
MD->getNonLocalDependency(C, deps);
|
||||||
CallInst* cdep = 0;
|
CallInst* cdep = 0;
|
||||||
|
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = deps.begin(),
|
for (DenseMap<BasicBlock*, MemoryDependenceAnalysis::DepResultTy>
|
||||||
E = deps.end(); I != E; ++I) {
|
::iterator I = deps.begin(), E = deps.end(); I != E; ++I) {
|
||||||
if (I->second == MemoryDependenceAnalysis::None) {
|
if (I->second.getInt() == MemoryDependenceAnalysis::None) {
|
||||||
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
||||||
|
|
||||||
return nextValueNumber++;
|
return nextValueNumber++;
|
||||||
} else if (I->second != MemoryDependenceAnalysis::NonLocal) {
|
} else if (I->second.getInt() != MemoryDependenceAnalysis::NonLocal) {
|
||||||
|
// FIXME: INDENT PROPERLY
|
||||||
if (DT->properlyDominates(I->first, C->getParent())) {
|
if (DT->properlyDominates(I->first, C->getParent())) {
|
||||||
if (CallInst* CD = dyn_cast<CallInst>(I->second))
|
if (CallInst* CD = dyn_cast<CallInst>(I->second.getPointer()))
|
||||||
cdep = CD;
|
cdep = CD;
|
||||||
else {
|
else {
|
||||||
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
valueNumbering.insert(std::make_pair(V, nextValueNumber));
|
||||||
@ -718,6 +721,8 @@ namespace {
|
|||||||
AU.addPreserved<AliasAnalysis>();
|
AU.addPreserved<AliasAnalysis>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef MemoryDependenceAnalysis::DepResultTy DepResultTy;
|
||||||
|
|
||||||
// Helper fuctions
|
// Helper fuctions
|
||||||
// FIXME: eliminate or document these better
|
// FIXME: eliminate or document these better
|
||||||
bool processLoad(LoadInst* L,
|
bool processLoad(LoadInst* L,
|
||||||
@ -861,7 +866,7 @@ bool GVN::processNonLocalLoad(LoadInst* L,
|
|||||||
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
||||||
|
|
||||||
// Find the non-local dependencies of the load
|
// Find the non-local dependencies of the load
|
||||||
DenseMap<BasicBlock*, Value*> deps;
|
DenseMap<BasicBlock*, DepResultTy> deps;
|
||||||
MD.getNonLocalDependency(L, deps);
|
MD.getNonLocalDependency(L, deps);
|
||||||
|
|
||||||
// If we had to process more than one hundred blocks to find the
|
// If we had to process more than one hundred blocks to find the
|
||||||
@ -873,19 +878,19 @@ bool GVN::processNonLocalLoad(LoadInst* L,
|
|||||||
DenseMap<BasicBlock*, Value*> repl;
|
DenseMap<BasicBlock*, Value*> repl;
|
||||||
|
|
||||||
// Filter out useless results (non-locals, etc)
|
// Filter out useless results (non-locals, etc)
|
||||||
for (DenseMap<BasicBlock*, Value*>::iterator I = deps.begin(), E = deps.end();
|
for (DenseMap<BasicBlock*, DepResultTy>::iterator I = deps.begin(),
|
||||||
I != E; ++I) {
|
E = deps.end(); I != E; ++I) {
|
||||||
if (I->second == MemoryDependenceAnalysis::None)
|
if (I->second.getInt() == MemoryDependenceAnalysis::None)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (I->second == MemoryDependenceAnalysis::NonLocal)
|
if (I->second.getInt() == MemoryDependenceAnalysis::NonLocal)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (StoreInst* S = dyn_cast<StoreInst>(I->second)) {
|
if (StoreInst* S = dyn_cast<StoreInst>(I->second.getPointer())) {
|
||||||
if (S->getPointerOperand() != L->getPointerOperand())
|
if (S->getPointerOperand() != L->getPointerOperand())
|
||||||
return false;
|
return false;
|
||||||
repl[I->first] = S->getOperand(0);
|
repl[I->first] = S->getOperand(0);
|
||||||
} else if (LoadInst* LD = dyn_cast<LoadInst>(I->second)) {
|
} else if (LoadInst* LD = dyn_cast<LoadInst>(I->second.getPointer())) {
|
||||||
if (LD->getPointerOperand() != L->getPointerOperand())
|
if (LD->getPointerOperand() != L->getPointerOperand())
|
||||||
return false;
|
return false;
|
||||||
repl[I->first] = LD;
|
repl[I->first] = LD;
|
||||||
@ -936,8 +941,8 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
|
|||||||
// ... to a pointer that has been loaded from before...
|
// ... to a pointer that has been loaded from before...
|
||||||
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
|
||||||
bool removedNonLocal = false;
|
bool removedNonLocal = false;
|
||||||
Instruction* dep = MD.getDependency(L);
|
DepResultTy dep = MD.getDependency(L);
|
||||||
if (dep == MemoryDependenceAnalysis::NonLocal &&
|
if (dep.getInt() == MemoryDependenceAnalysis::NonLocal &&
|
||||||
L->getParent() != &L->getParent()->getParent()->getEntryBlock()) {
|
L->getParent() != &L->getParent()->getParent()->getEntryBlock()) {
|
||||||
removedNonLocal = processNonLocalLoad(L, toErase);
|
removedNonLocal = processNonLocalLoad(L, toErase);
|
||||||
|
|
||||||
@ -952,11 +957,10 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
|
|||||||
|
|
||||||
// Walk up the dependency chain until we either find
|
// Walk up the dependency chain until we either find
|
||||||
// a dependency we can use, or we can't walk any further
|
// a dependency we can use, or we can't walk any further
|
||||||
while (dep != MemoryDependenceAnalysis::None &&
|
while (dep.getInt() == MemoryDependenceAnalysis::Normal &&
|
||||||
dep != MemoryDependenceAnalysis::NonLocal &&
|
(isa<LoadInst>(dep.getPointer()) || isa<StoreInst>(dep.getPointer()))){
|
||||||
(isa<LoadInst>(dep) || isa<StoreInst>(dep))) {
|
|
||||||
// ... that depends on a store ...
|
// ... that depends on a store ...
|
||||||
if (StoreInst* S = dyn_cast<StoreInst>(dep)) {
|
if (StoreInst* S = dyn_cast<StoreInst>(dep.getPointer())) {
|
||||||
if (S->getPointerOperand() == pointer) {
|
if (S->getPointerOperand() == pointer) {
|
||||||
// Remove it!
|
// Remove it!
|
||||||
MD.removeInstruction(L);
|
MD.removeInstruction(L);
|
||||||
@ -974,7 +978,7 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
|
|||||||
// If we don't depend on a store, and we haven't
|
// If we don't depend on a store, and we haven't
|
||||||
// been loaded before, bail.
|
// been loaded before, bail.
|
||||||
break;
|
break;
|
||||||
} else if (dep == last) {
|
} else if (dep.getPointer() == last) {
|
||||||
// Remove it!
|
// Remove it!
|
||||||
MD.removeInstruction(L);
|
MD.removeInstruction(L);
|
||||||
|
|
||||||
@ -985,16 +989,15 @@ bool GVN::processLoad(LoadInst *L, DenseMap<Value*, LoadInst*> &lastLoad,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
dep = MD.getDependency(L, dep);
|
dep = MD.getDependency(L, dep.getPointer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dep != MemoryDependenceAnalysis::None &&
|
if (dep.getInt() == MemoryDependenceAnalysis::Normal &&
|
||||||
dep != MemoryDependenceAnalysis::NonLocal &&
|
isa<AllocationInst>(dep.getPointer())) {
|
||||||
isa<AllocationInst>(dep)) {
|
|
||||||
// Check that this load is actually from the
|
// Check that this load is actually from the
|
||||||
// allocation we found
|
// allocation we found
|
||||||
if (L->getOperand(0)->getUnderlyingObject() == dep) {
|
if (L->getOperand(0)->getUnderlyingObject() == dep.getPointer()) {
|
||||||
// If this load depends directly on an allocation, there isn't
|
// If this load depends directly on an allocation, there isn't
|
||||||
// anything stored there; therefore, we can optimize this load
|
// anything stored there; therefore, we can optimize this load
|
||||||
// to undef.
|
// to undef.
|
||||||
|
@ -629,18 +629,18 @@ bool MemCpyOpt::processMemCpy(MemCpyInst* M) {
|
|||||||
// The are two possible optimizations we can do for memcpy:
|
// The are two possible optimizations we can do for memcpy:
|
||||||
// a) memcpy-memcpy xform which exposes redundance for DSE
|
// a) memcpy-memcpy xform which exposes redundance for DSE
|
||||||
// b) call-memcpy xform for return slot optimization
|
// b) call-memcpy xform for return slot optimization
|
||||||
Instruction* dep = MD.getDependency(M);
|
MemoryDependenceAnalysis::DepResultTy dep = MD.getDependency(M);
|
||||||
if (dep == MemoryDependenceAnalysis::None ||
|
if (dep.getInt() == MemoryDependenceAnalysis::None ||
|
||||||
dep == MemoryDependenceAnalysis::NonLocal)
|
dep.getInt() == MemoryDependenceAnalysis::NonLocal)
|
||||||
return false;
|
return false;
|
||||||
else if (!isa<MemCpyInst>(dep)) {
|
else if (!isa<MemCpyInst>(dep.getPointer())) {
|
||||||
if (CallInst* C = dyn_cast<CallInst>(dep))
|
if (CallInst* C = dyn_cast<CallInst>(dep.getPointer()))
|
||||||
return performCallSlotOptzn(M, C);
|
return performCallSlotOptzn(M, C);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemCpyInst* MDep = cast<MemCpyInst>(dep);
|
MemCpyInst* MDep = cast<MemCpyInst>(dep.getPointer());
|
||||||
|
|
||||||
// We can only transforms memcpy's where the dest of one is the source of the
|
// We can only transforms memcpy's where the dest of one is the source of the
|
||||||
// other
|
// other
|
||||||
@ -691,7 +691,7 @@ bool MemCpyOpt::processMemCpy(MemCpyInst* M) {
|
|||||||
|
|
||||||
// If C and M don't interfere, then this is a valid transformation. If they
|
// If C and M don't interfere, then this is a valid transformation. If they
|
||||||
// did, this would mean that the two sources overlap, which would be bad.
|
// did, this would mean that the two sources overlap, which would be bad.
|
||||||
if (MD.getDependency(C) == MDep) {
|
if (MD.getDependency(C) == dep) {
|
||||||
MD.dropInstruction(M);
|
MD.dropInstruction(M);
|
||||||
M->eraseFromParent();
|
M->eraseFromParent();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user