using namespace llvm;
-namespace {
- // Control the calculation of non-local dependencies by only examining the
- // predecessors if the basic block has less than X amount (50 by default).
- cl::opt<int>
- PredLimit("nonlocaldep-threshold", cl::Hidden, cl::init(50),
- cl::desc("Control the calculation of non-local"
- "dependencies (default = 50)"));
-}
+// Control the calculation of non-local dependencies by only examining the
+// predecessors if the basic block has less than X amount (50 by default).
+static cl::opt<int>
+PredLimit("nonlocaldep-threshold", cl::Hidden, cl::init(50),
+ cl::desc("Control the calculation of non-local"
+ "dependencies (default = 50)"));
STATISTIC(NumCacheNonlocal, "Number of cached non-local responses");
STATISTIC(NumUncacheNonlocal, "Number of uncached non-local responses");
// Register this pass...
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
- "Memory Dependence Analysis");
+ "Memory Dependence Analysis", false, true);
void MemoryDependenceAnalysis::ping(Instruction *D) {
for (depMapType::iterator I = depGraphLocal.begin(), E = depGraphLocal.end();
for (nonLocalDepMapType::iterator I = depGraphNonLocal.begin(), E = depGraphNonLocal.end();
I != E; ++I) {
assert(I->first != D);
+ for (DenseMap<BasicBlock*, Value*>::iterator II = I->second.begin(),
+ EE = I->second.end(); II != EE; ++II)
+ assert(II->second != D);
}
for (reverseDepMapType::iterator I = reverseDep.begin(), E = reverseDep.end();
BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin();
BasicBlock::iterator QI = C.getInstruction();
- // If the starting point was specifiy, use it
+ // If the starting point was specified, use it
if (start) {
QI = start;
- blockBegin = start->getParent()->end();
+ blockBegin = start->getParent()->begin();
// If the starting point wasn't specified, but the block was, use it
} else if (!start && block) {
QI = block->end();
- blockBegin = block->end();
+ blockBegin = block->begin();
}
// Walk backwards through the block, looking for dependencies
// FreeInsts erase the entire structure
pointerSize = ~0UL;
- } else if (isa<CallInst>(QI)) {
+ } else if (CallSite::get(QI).getInstruction() != 0) {
AliasAnalysis::ModRefBehavior result =
AA.getModRefBehavior(CallSite::get(QI));
- if (result != AliasAnalysis::DoesNotAccessMemory &&
- result != AliasAnalysis::OnlyReadsMemory) {
+ if (result != AliasAnalysis::DoesNotAccessMemory) {
if (!start && !block) {
cachedResult.first = QI;
cachedResult.second = true;
// Current stack of the DFS
SmallVector<BasicBlock*, 4> stack;
- stack.push_back(block);
+ for (pred_iterator PI = pred_begin(block), PE = pred_end(block);
+ PI != PE; ++PI)
+ stack.push_back(*PI);
// Do a basic DFS
while (!stack.empty()) {
// If we re-encounter the starting block, we still need to search it
// because there might be a dependency in the starting block AFTER
// the position of the query. This is necessary to get loops right.
- } else if (BB == block && stack.size() > 1) {
+ } else if (BB == block) {
visited.insert(BB);
Instruction* localDep = getDependency(query, 0, BB);
resp = cached;
+ // Update the reverse non-local dependency cache
+ for (DenseMap<BasicBlock*, Value*>::iterator I = resp.begin(), E = resp.end();
+ I != E; ++I)
+ reverseDepNonLocal[I->second].insert(query);
+
return;
} else
NumUncacheNonlocal++;
}
/// getDependency - Return the instruction on which a memory operation
-/// depends. The local paramter indicates if the query should only
+/// depends. The local parameter indicates if the query should only
/// evaluate dependencies within the same basic block.
Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
Instruction* start,
return NonLocal;
}
+/// dropInstruction - Remove an instruction from the analysis, making
+/// absolutely conservative assumptions when updating the cache. This is
+/// useful, for example when an instruction is changed rather than removed.
+void MemoryDependenceAnalysis::dropInstruction(Instruction* drop) {
+ depMapType::iterator depGraphEntry = depGraphLocal.find(drop);
+ if (depGraphEntry != depGraphLocal.end())
+ reverseDep[depGraphEntry->second.first].erase(drop);
+
+ // Drop dependency information for things that depended on this instr
+ SmallPtrSet<Instruction*, 4>& set = reverseDep[drop];
+ for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
+ I != E; ++I)
+ depGraphLocal.erase(*I);
+
+ depGraphLocal.erase(drop);
+ reverseDep.erase(drop);
+
+ for (DenseMap<BasicBlock*, Value*>::iterator DI =
+ depGraphNonLocal[drop].begin(), DE = depGraphNonLocal[drop].end();
+ DI != DE; ++DI)
+ if (DI->second != None)
+ reverseDepNonLocal[DI->second].erase(drop);
+
+ if (reverseDepNonLocal.count(drop)) {
+ SmallPtrSet<Instruction*, 4>& set = reverseDepNonLocal[drop];
+ for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
+ I != E; ++I)
+ for (DenseMap<BasicBlock*, Value*>::iterator DI =
+ depGraphNonLocal[*I].begin(), DE = depGraphNonLocal[*I].end();
+ DI != DE; ++DI)
+ if (DI->second == drop)
+ DI->second = Dirty;
+ }
+
+ reverseDepNonLocal.erase(drop);
+ nonLocalDepMapType::iterator I = depGraphNonLocal.find(drop);
+ if (I != depGraphNonLocal.end())
+ depGraphNonLocal.erase(I);
+}
+
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
/// This method attempts to keep the cache coherent using the reverse map.
depMapType::iterator depGraphEntry = depGraphLocal.find(rem);
if (depGraphEntry != depGraphLocal.end()) {
- reverseDep[depGraphLocal[rem].first].erase(rem);
+ reverseDep[depGraphEntry->second.first].erase(rem);
if (depGraphEntry->second.first != NonLocal &&
depGraphEntry->second.first != None &&
// If we have dep info for rem, set them to it
BasicBlock::iterator RI = depGraphEntry->second.first;
RI++;
+
+ // If RI is rem, then we use rem's immediate successor.
+ if (RI == (BasicBlock::iterator)rem) RI++;
+
newDep = RI;
} else if ( (depGraphEntry->second.first == NonLocal ||
depGraphEntry->second.first == None ) &&