MemoryDependenceAnalysis.cpp revision 3dfcf33cf897b04c95e252bbd645e9930f608701
1//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation --*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the Owen Anderson and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements an analysis that determines, for a given memory 11// operation, what preceding memory operations it depends on. It builds on 12// alias analysis information, and tries to provide a lazy, caching interface to 13// a common kind of alias information query. 14// 15//===----------------------------------------------------------------------===// 16 17#include "llvm/Analysis/MemoryDependenceAnalysis.h" 18#include "llvm/Constants.h" 19#include "llvm/Instructions.h" 20#include "llvm/Function.h" 21#include "llvm/Analysis/AliasAnalysis.h" 22#include "llvm/Support/CFG.h" 23#include "llvm/Target/TargetData.h" 24 25using namespace llvm; 26 27char MemoryDependenceAnalysis::ID = 0; 28 29Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)-2; 30Instruction* MemoryDependenceAnalysis::None = (Instruction*)-3; 31 32// Register this pass... 33static RegisterPass<MemoryDependenceAnalysis> X("memdep", 34 "Memory Dependence Analysis"); 35 36/// getAnalysisUsage - Does not modify anything. It uses Alias Analysis. 37/// 38void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { 39 AU.setPreservesAll(); 40 AU.addRequiredTransitive<AliasAnalysis>(); 41 AU.addRequiredTransitive<TargetData>(); 42} 43 44// Find the dependency of a CallSite 45Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C, Instruction* start, 46 bool local) { 47 assert(local && "Non-local memory dependence analysis not yet implemented"); 48 49 AliasAnalysis& AA = getAnalysis<AliasAnalysis>(); 50 TargetData& TD = getAnalysis<TargetData>(); 51 BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin(); 52 BasicBlock::iterator QI = C.getInstruction(); 53 54 while (QI != blockBegin) { 55 --QI; 56 57 // If this inst is a memory op, get the pointer it accessed 58 Value* pointer = 0; 59 uint64_t pointerSize = 0; 60 if (StoreInst* S = dyn_cast<StoreInst>(QI)) { 61 pointer = S->getPointerOperand(); 62 pointerSize = TD.getTypeSize(S->getOperand(0)->getType()); 63 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) { 64 pointer = L->getPointerOperand(); 65 pointerSize = TD.getTypeSize(L->getType()); 66 } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) { 67 pointer = AI; 68 if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize())) 69 pointerSize = C->getZExtValue() * TD.getTypeSize(AI->getAllocatedType()); 70 else 71 pointerSize = ~0UL; 72 } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) { 73 pointer = V->getOperand(0); 74 pointerSize = TD.getTypeSize(V->getType()); 75 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) { 76 pointer = F->getPointerOperand(); 77 78 // FreeInsts erase the entire structure 79 pointerSize = ~0UL; 80 } else if (CallSite::get(QI).getInstruction() != 0) { 81 if (AA.getModRefInfo(C, CallSite::get(QI)) != AliasAnalysis::NoModRef) { 82 depGraphLocal.insert(std::make_pair(C.getInstruction(), std::make_pair(QI, true))); 83 reverseDep.insert(std::make_pair(QI, C.getInstruction())); 84 return QI; 85 } else { 86 continue; 87 } 88 } else 89 continue; 90 91 if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) { 92 depGraphLocal.insert(std::make_pair(C.getInstruction(), std::make_pair(QI, true))); 93 reverseDep.insert(std::make_pair(QI, C.getInstruction())); 94 return QI; 95 } 96 } 97 98 // No dependence found 99 depGraphLocal.insert(std::make_pair(C.getInstruction(), std::make_pair(NonLocal, true))); 100 reverseDep.insert(std::make_pair(NonLocal, C.getInstruction())); 101 return NonLocal; 102} 103 104bool MemoryDependenceAnalysis::nonLocalHelper(Instruction* query, 105 BasicBlock* block, 106 DenseMap<BasicBlock*, Value*>& resp, 107 SmallPtrSet<BasicBlock*, 4>& visited) { 108 if (resp.count(block)) 109 return resp[block] != None; 110 111 Instruction* localDep = getDependency(query, 0, block); 112 if (localDep != NonLocal) { 113 resp.insert(std::make_pair(block, localDep)); 114 return true; 115 } 116 117 visited.insert(block); 118 119 bool inserted = false; 120 for (pred_iterator PI = pred_begin(block), PE = pred_end(block); 121 PI != PE; ++PI) 122 if (!visited.count(*PI)) 123 inserted |= nonLocalHelper(query, *PI, resp, visited); 124 125 visited.erase(block); 126 127 if (!inserted) 128 resp.insert(std::make_pair(block, None)); 129 130 return inserted; 131} 132 133bool MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query, 134 DenseMap<BasicBlock*, Value*>& resp) { 135 Instruction* localDep = getDependency(query); 136 if (localDep != NonLocal) { 137 resp.insert(std::make_pair(query->getParent(), localDep)); 138 return true; 139 } 140 141 bool inserted = false; 142 SmallPtrSet<BasicBlock*, 4> visited; 143 visited.insert(query->getParent()); 144 145 BasicBlock* parent = query->getParent(); 146 for (pred_iterator PI = pred_begin(parent), PE = pred_end(parent); 147 PI != PE; ++PI) { 148 if (!visited.count(*PI)) 149 inserted |= nonLocalHelper(query, *PI, resp, visited); 150 } 151 152 if (!inserted) 153 resp.insert(std::make_pair(query->getParent(), None)); 154 155 return inserted; 156} 157 158/// getDependency - Return the instruction on which a memory operation 159/// depends. The local paramter indicates if the query should only 160/// evaluate dependencies within the same basic block. 161Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query, 162 Instruction* start, 163 BasicBlock* block) { 164 // Start looking for dependencies with the queried inst 165 BasicBlock::iterator QI = query; 166 167 // Check for a cached result 168 std::pair<Instruction*, bool> cachedResult = depGraphLocal[query]; 169 // If we have a _confirmed_ cached entry, return it 170 if (cachedResult.second) 171 return cachedResult.first; 172 else if (cachedResult.first && cachedResult.first != NonLocal) 173 // If we have an unconfirmed cached entry, we can start our search from there 174 QI = cachedResult.first; 175 176 if (start) 177 QI = start; 178 else if (!start && block) 179 QI = block->end(); 180 181 AliasAnalysis& AA = getAnalysis<AliasAnalysis>(); 182 TargetData& TD = getAnalysis<TargetData>(); 183 184 // Get the pointer value for which dependence will be determined 185 Value* dependee = 0; 186 uint64_t dependeeSize = 0; 187 bool queryIsVolatile = false; 188 if (StoreInst* S = dyn_cast<StoreInst>(query)) { 189 dependee = S->getPointerOperand(); 190 dependeeSize = TD.getTypeSize(S->getOperand(0)->getType()); 191 queryIsVolatile = S->isVolatile(); 192 } else if (LoadInst* L = dyn_cast<LoadInst>(query)) { 193 dependee = L->getPointerOperand(); 194 dependeeSize = TD.getTypeSize(L->getType()); 195 queryIsVolatile = L->isVolatile(); 196 } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) { 197 dependee = V->getOperand(0); 198 dependeeSize = TD.getTypeSize(V->getType()); 199 } else if (FreeInst* F = dyn_cast<FreeInst>(query)) { 200 dependee = F->getPointerOperand(); 201 202 // FreeInsts erase the entire structure, not just a field 203 dependeeSize = ~0UL; 204 } else if (CallSite::get(query).getInstruction() != 0) 205 return getCallSiteDependency(CallSite::get(query), start); 206 else if (isa<AllocationInst>(query)) 207 return None; 208 else 209 return None; 210 211 BasicBlock::iterator blockBegin = block ? block->begin() 212 : query->getParent()->begin(); 213 214 while (QI != blockBegin) { 215 --QI; 216 217 // If this inst is a memory op, get the pointer it accessed 218 Value* pointer = 0; 219 uint64_t pointerSize = 0; 220 if (StoreInst* S = dyn_cast<StoreInst>(QI)) { 221 // All volatile loads/stores depend on each other 222 if (queryIsVolatile && S->isVolatile()) { 223 if (!start || block) { 224 depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true))); 225 reverseDep.insert(std::make_pair(S, query)); 226 } 227 228 return S; 229 } 230 231 pointer = S->getPointerOperand(); 232 pointerSize = TD.getTypeSize(S->getOperand(0)->getType()); 233 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) { 234 // All volatile loads/stores depend on each other 235 if (queryIsVolatile && L->isVolatile()) { 236 if (!start || block) { 237 depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true))); 238 reverseDep.insert(std::make_pair(L, query)); 239 } 240 241 return L; 242 } 243 244 pointer = L->getPointerOperand(); 245 pointerSize = TD.getTypeSize(L->getType()); 246 } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) { 247 pointer = AI; 248 if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize())) 249 pointerSize = C->getZExtValue() * TD.getTypeSize(AI->getAllocatedType()); 250 else 251 pointerSize = ~0UL; 252 } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) { 253 pointer = V->getOperand(0); 254 pointerSize = TD.getTypeSize(V->getType()); 255 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) { 256 pointer = F->getPointerOperand(); 257 258 // FreeInsts erase the entire structure 259 pointerSize = ~0UL; 260 } else if (CallSite::get(QI).getInstruction() != 0) { 261 // Call insts need special handling. Check is they can modify our pointer 262 if (AA.getModRefInfo(CallSite::get(QI), dependee, dependeeSize) != 263 AliasAnalysis::NoModRef) { 264 if (!start || block) { 265 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true))); 266 reverseDep.insert(std::make_pair(QI, query)); 267 } 268 269 return QI; 270 } else { 271 continue; 272 } 273 } 274 275 // If we found a pointer, check if it could be the same as our pointer 276 if (pointer) { 277 AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize, 278 dependee, dependeeSize); 279 280 if (R != AliasAnalysis::NoAlias) { 281 if (!start || block) { 282 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true))); 283 reverseDep.insert(std::make_pair(QI, query)); 284 } 285 286 return QI; 287 } 288 } 289 } 290 291 // If we found nothing, return the non-local flag 292 if (!start || block) { 293 depGraphLocal.insert(std::make_pair(query, 294 std::make_pair(NonLocal, true))); 295 reverseDep.insert(std::make_pair(NonLocal, query)); 296 } 297 298 return NonLocal; 299} 300 301/// removeInstruction - Remove an instruction from the dependence analysis, 302/// updating the dependence of instructions that previously depended on it. 303void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) { 304 // Figure out the new dep for things that currently depend on rem 305 Instruction* newDep = NonLocal; 306 if (depGraphLocal[rem].first != NonLocal && 307 depGraphLocal[rem].second) { 308 // If we have dep info for rem, set them to it 309 BasicBlock::iterator RI = depGraphLocal[rem].first; 310 RI++; 311 newDep = RI; 312 } else if (depGraphLocal[rem].first == NonLocal && 313 depGraphLocal[rem].second ) { 314 // If we have a confirmed non-local flag, use it 315 newDep = NonLocal; 316 } else { 317 // Otherwise, use the immediate successor of rem 318 // NOTE: This is because, when getDependence is called, it will first check 319 // the immediate predecessor of what is in the cache. 320 BasicBlock::iterator RI = rem; 321 RI++; 322 newDep = RI; 323 } 324 325 std::multimap<Instruction*, Instruction*>::iterator I = reverseDep.find(rem); 326 while (I->first == rem) { 327 // Insert the new dependencies 328 // Mark it as unconfirmed as long as it is not the non-local flag 329 depGraphLocal[I->second] = std::make_pair(newDep, !newDep); 330 reverseDep.erase(I); 331 I = reverseDep.find(rem); 332 } 333 334 getAnalysis<AliasAnalysis>().deleteValue(rem); 335} 336