MemoryDependenceAnalysis.cpp revision 0cd320362e91852c8f7f2c8c4841498aab7f92fa
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 if (resp.count(block)) 108 return resp[block] != None; 109 110 Instruction* localDep = getDependency(query, 0, block); 111 if (localDep != NonLocal) { 112 resp.insert(std::make_pair(block, localDep)); 113 return true; 114 } 115 116 bool inserted = false; 117 for (pred_iterator PI = pred_begin(block), PE = pred_end(block); 118 PI != PE; ++PI) 119 inserted |= nonLocalHelper(query, *PI, resp); 120 121 if (!inserted) 122 resp.insert(std::make_pair(block, None)); 123 124 return inserted; 125} 126 127bool MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query, 128 DenseMap<BasicBlock*, Value*>& resp) { 129 Instruction* localDep = getDependency(query); 130 if (localDep != NonLocal) { 131 resp.insert(std::make_pair(query->getParent(), localDep)); 132 return true; 133 } 134 135 bool inserted = false; 136 137 BasicBlock* parent = query->getParent(); 138 for (pred_iterator PI = pred_begin(parent), PE = pred_end(parent); 139 PI != PE; ++PI) { 140 inserted |= nonLocalHelper(query, *PI, resp); 141 } 142 143 if (!inserted) 144 resp.insert(std::make_pair(query->getParent(), None)); 145 146 return inserted; 147} 148 149/// getDependency - Return the instruction on which a memory operation 150/// depends. The local paramter indicates if the query should only 151/// evaluate dependencies within the same basic block. 152Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query, 153 Instruction* start, 154 BasicBlock* block) { 155 // Start looking for dependencies with the queried inst 156 BasicBlock::iterator QI = query; 157 158 // Check for a cached result 159 std::pair<Instruction*, bool> cachedResult = depGraphLocal[query]; 160 // If we have a _confirmed_ cached entry, return it 161 if (cachedResult.second) 162 return cachedResult.first; 163 else if (cachedResult.first && cachedResult.first != NonLocal) 164 // If we have an unconfirmed cached entry, we can start our search from there 165 QI = cachedResult.first; 166 167 if (start) 168 QI = start; 169 else if (!start && block) 170 QI = block->end(); 171 172 AliasAnalysis& AA = getAnalysis<AliasAnalysis>(); 173 TargetData& TD = getAnalysis<TargetData>(); 174 175 // Get the pointer value for which dependence will be determined 176 Value* dependee = 0; 177 uint64_t dependeeSize = 0; 178 bool queryIsVolatile = false; 179 if (StoreInst* S = dyn_cast<StoreInst>(query)) { 180 dependee = S->getPointerOperand(); 181 dependeeSize = TD.getTypeSize(S->getOperand(0)->getType()); 182 queryIsVolatile = S->isVolatile(); 183 } else if (LoadInst* L = dyn_cast<LoadInst>(query)) { 184 dependee = L->getPointerOperand(); 185 dependeeSize = TD.getTypeSize(L->getType()); 186 queryIsVolatile = L->isVolatile(); 187 } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) { 188 dependee = V->getOperand(0); 189 dependeeSize = TD.getTypeSize(V->getType()); 190 } else if (FreeInst* F = dyn_cast<FreeInst>(query)) { 191 dependee = F->getPointerOperand(); 192 193 // FreeInsts erase the entire structure, not just a field 194 dependeeSize = ~0UL; 195 } else if (CallSite::get(query).getInstruction() != 0) 196 return getCallSiteDependency(CallSite::get(query), start); 197 else if (isa<AllocationInst>(query)) 198 return None; 199 else 200 return None; 201 202 BasicBlock::iterator blockBegin = block ? block->begin() 203 : query->getParent()->begin(); 204 205 while (QI != blockBegin) { 206 --QI; 207 208 // If this inst is a memory op, get the pointer it accessed 209 Value* pointer = 0; 210 uint64_t pointerSize = 0; 211 if (StoreInst* S = dyn_cast<StoreInst>(QI)) { 212 // All volatile loads/stores depend on each other 213 if (queryIsVolatile && S->isVolatile()) { 214 if (!start || block) { 215 depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true))); 216 reverseDep.insert(std::make_pair(S, query)); 217 } 218 219 return S; 220 } 221 222 pointer = S->getPointerOperand(); 223 pointerSize = TD.getTypeSize(S->getOperand(0)->getType()); 224 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) { 225 // All volatile loads/stores depend on each other 226 if (queryIsVolatile && L->isVolatile()) { 227 if (!start || block) { 228 depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true))); 229 reverseDep.insert(std::make_pair(L, query)); 230 } 231 232 return L; 233 } 234 235 pointer = L->getPointerOperand(); 236 pointerSize = TD.getTypeSize(L->getType()); 237 } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) { 238 pointer = AI; 239 if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize())) 240 pointerSize = C->getZExtValue() * TD.getTypeSize(AI->getAllocatedType()); 241 else 242 pointerSize = ~0UL; 243 } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) { 244 pointer = V->getOperand(0); 245 pointerSize = TD.getTypeSize(V->getType()); 246 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) { 247 pointer = F->getPointerOperand(); 248 249 // FreeInsts erase the entire structure 250 pointerSize = ~0UL; 251 } else if (CallSite::get(QI).getInstruction() != 0) { 252 // Call insts need special handling. Check is they can modify our pointer 253 if (AA.getModRefInfo(CallSite::get(QI), dependee, dependeeSize) != 254 AliasAnalysis::NoModRef) { 255 if (!start || block) { 256 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true))); 257 reverseDep.insert(std::make_pair(QI, query)); 258 } 259 260 return QI; 261 } else { 262 continue; 263 } 264 } 265 266 // If we found a pointer, check if it could be the same as our pointer 267 if (pointer) { 268 AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize, 269 dependee, dependeeSize); 270 271 if (R != AliasAnalysis::NoAlias) { 272 if (!start || block) { 273 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true))); 274 reverseDep.insert(std::make_pair(QI, query)); 275 } 276 277 return QI; 278 } 279 } 280 } 281 282 // If we found nothing, return the non-local flag 283 if (!start || block) { 284 depGraphLocal.insert(std::make_pair(query, 285 std::make_pair(NonLocal, true))); 286 reverseDep.insert(std::make_pair(NonLocal, query)); 287 } 288 289 return NonLocal; 290} 291 292/// removeInstruction - Remove an instruction from the dependence analysis, 293/// updating the dependence of instructions that previously depended on it. 294void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) { 295 // Figure out the new dep for things that currently depend on rem 296 Instruction* newDep = NonLocal; 297 if (depGraphLocal[rem].first != NonLocal && 298 depGraphLocal[rem].second) { 299 // If we have dep info for rem, set them to it 300 BasicBlock::iterator RI = depGraphLocal[rem].first; 301 RI++; 302 newDep = RI; 303 } else if (depGraphLocal[rem].first == NonLocal && 304 depGraphLocal[rem].second ) { 305 // If we have a confirmed non-local flag, use it 306 newDep = NonLocal; 307 } else { 308 // Otherwise, use the immediate successor of rem 309 // NOTE: This is because, when getDependence is called, it will first check 310 // the immediate predecessor of what is in the cache. 311 BasicBlock::iterator RI = rem; 312 RI++; 313 newDep = RI; 314 } 315 316 std::multimap<Instruction*, Instruction*>::iterator I = reverseDep.find(rem); 317 while (I->first == rem) { 318 // Insert the new dependencies 319 // Mark it as unconfirmed as long as it is not the non-local flag 320 depGraphLocal[I->second] = std::make_pair(newDep, !newDep); 321 reverseDep.erase(I); 322 I = reverseDep.find(rem); 323 } 324 325 getAnalysis<AliasAnalysis>().deleteValue(rem); 326} 327