blob: 4bd877142a2ba99213b59cd259ec0656cae838a8 [file] [log] [blame]
Owen Anderson78e02f72007-07-06 23:14:35 +00001//===- 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"
Owen Anderson7a616a12007-07-10 17:25:03 +000018#include "llvm/Constants.h"
Owen Anderson78e02f72007-07-06 23:14:35 +000019#include "llvm/Instructions.h"
20#include "llvm/Function.h"
21#include "llvm/Analysis/AliasAnalysis.h"
Owen Anderson4beedbd2007-07-24 21:52:37 +000022#include "llvm/Support/CFG.h"
Owen Anderson78e02f72007-07-06 23:14:35 +000023#include "llvm/Target/TargetData.h"
24
25using namespace llvm;
26
27char MemoryDependenceAnalysis::ID = 0;
28
Owen Anderson0cd32032007-07-25 19:57:03 +000029Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)-2;
30Instruction* MemoryDependenceAnalysis::None = (Instruction*)-3;
Owen Anderson78e02f72007-07-06 23:14:35 +000031
32// Register this pass...
Owen Anderson776ee1f2007-07-10 20:21:08 +000033static RegisterPass<MemoryDependenceAnalysis> X("memdep",
34 "Memory Dependence Analysis");
Owen Anderson78e02f72007-07-06 23:14:35 +000035
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
Owen Anderson5f323202007-07-10 17:59:22 +000044// Find the dependency of a CallSite
Owen Andersonfaac5182007-07-16 21:52:50 +000045Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C, Instruction* start,
46 bool local) {
Owen Anderson5f323202007-07-10 17:59:22 +000047 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()))
Owen Anderson8e850482007-07-10 20:48:38 +000069 pointerSize = C->getZExtValue() * TD.getTypeSize(AI->getAllocatedType());
Owen Anderson5f323202007-07-10 17:59:22 +000070 else
71 pointerSize = ~0UL;
Owen Anderson06b6e822007-07-10 18:43:15 +000072 } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
73 pointer = V->getOperand(0);
74 pointerSize = TD.getTypeSize(V->getType());
Owen Anderson5f323202007-07-10 17:59:22 +000075 } 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 }
Owen Anderson202da142007-07-10 20:39:07 +000088 } else
89 continue;
Owen Anderson5f323202007-07-10 17:59:22 +000090
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
Owen Anderson0cd32032007-07-25 19:57:03 +0000104bool MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
105 BasicBlock* block,
Owen Anderson3dfcf332007-07-25 21:26:36 +0000106 DenseMap<BasicBlock*, Value*>& resp,
107 SmallPtrSet<BasicBlock*, 4>& visited) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000108 if (resp.count(block))
109 return resp[block] != None;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000110
Owen Anderson0cd32032007-07-25 19:57:03 +0000111 Instruction* localDep = getDependency(query, 0, block);
Owen Anderson4beedbd2007-07-24 21:52:37 +0000112 if (localDep != NonLocal) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000113 resp.insert(std::make_pair(block, localDep));
114 return true;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000115 }
116
Owen Anderson3dfcf332007-07-25 21:26:36 +0000117 visited.insert(block);
118
Owen Anderson0cd32032007-07-25 19:57:03 +0000119 bool inserted = false;
Owen Andersona377a242007-07-26 18:57:04 +0000120 bool predOnStack = false;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000121 for (pred_iterator PI = pred_begin(block), PE = pred_end(block);
Owen Anderson0cd32032007-07-25 19:57:03 +0000122 PI != PE; ++PI)
Owen Anderson3dfcf332007-07-25 21:26:36 +0000123 if (!visited.count(*PI))
124 inserted |= nonLocalHelper(query, *PI, resp, visited);
Owen Andersona377a242007-07-26 18:57:04 +0000125 else
126 predOnStack = true;
127
Owen Anderson3dfcf332007-07-25 21:26:36 +0000128 visited.erase(block);
Owen Andersona377a242007-07-26 18:57:04 +0000129
130 if (!inserted && !predOnStack)
131 resp.insert(std::make_pair(block, None));
Owen Anderson4beedbd2007-07-24 21:52:37 +0000132
Owen Anderson0cd32032007-07-25 19:57:03 +0000133 return inserted;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000134}
135
Owen Anderson0cd32032007-07-25 19:57:03 +0000136bool MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
137 DenseMap<BasicBlock*, Value*>& resp) {
Owen Anderson4beedbd2007-07-24 21:52:37 +0000138 Instruction* localDep = getDependency(query);
139 if (localDep != NonLocal) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000140 resp.insert(std::make_pair(query->getParent(), localDep));
141 return true;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000142 }
143
Owen Anderson0cd32032007-07-25 19:57:03 +0000144 bool inserted = false;
Owen Anderson3dfcf332007-07-25 21:26:36 +0000145 SmallPtrSet<BasicBlock*, 4> visited;
146 visited.insert(query->getParent());
Owen Anderson0cd32032007-07-25 19:57:03 +0000147
Owen Anderson4beedbd2007-07-24 21:52:37 +0000148 BasicBlock* parent = query->getParent();
149 for (pred_iterator PI = pred_begin(parent), PE = pred_end(parent);
150 PI != PE; ++PI) {
Owen Anderson3dfcf332007-07-25 21:26:36 +0000151 if (!visited.count(*PI))
152 inserted |= nonLocalHelper(query, *PI, resp, visited);
Owen Anderson4beedbd2007-07-24 21:52:37 +0000153 }
154
Owen Anderson0cd32032007-07-25 19:57:03 +0000155 if (!inserted)
156 resp.insert(std::make_pair(query->getParent(), None));
Owen Anderson4beedbd2007-07-24 21:52:37 +0000157
Owen Anderson0cd32032007-07-25 19:57:03 +0000158 return inserted;
Owen Anderson4beedbd2007-07-24 21:52:37 +0000159}
160
Owen Anderson78e02f72007-07-06 23:14:35 +0000161/// getDependency - Return the instruction on which a memory operation
Owen Anderson6b278fc2007-07-10 17:08:11 +0000162/// depends. The local paramter indicates if the query should only
163/// evaluate dependencies within the same basic block.
Owen Anderson78e02f72007-07-06 23:14:35 +0000164Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
Owen Andersonfaac5182007-07-16 21:52:50 +0000165 Instruction* start,
Owen Anderson4beedbd2007-07-24 21:52:37 +0000166 BasicBlock* block) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000167 // Start looking for dependencies with the queried inst
168 BasicBlock::iterator QI = query;
169
170 // Check for a cached result
171 std::pair<Instruction*, bool> cachedResult = depGraphLocal[query];
172 // If we have a _confirmed_ cached entry, return it
173 if (cachedResult.second)
174 return cachedResult.first;
Owen Anderson0cd32032007-07-25 19:57:03 +0000175 else if (cachedResult.first && cachedResult.first != NonLocal)
Owen Anderson78e02f72007-07-06 23:14:35 +0000176 // If we have an unconfirmed cached entry, we can start our search from there
177 QI = cachedResult.first;
178
Owen Andersonfaac5182007-07-16 21:52:50 +0000179 if (start)
180 QI = start;
Owen Anderson0cd32032007-07-25 19:57:03 +0000181 else if (!start && block)
182 QI = block->end();
Owen Andersonfaac5182007-07-16 21:52:50 +0000183
Owen Anderson78e02f72007-07-06 23:14:35 +0000184 AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
Owen Anderson6b278fc2007-07-10 17:08:11 +0000185 TargetData& TD = getAnalysis<TargetData>();
Owen Anderson78e02f72007-07-06 23:14:35 +0000186
187 // Get the pointer value for which dependence will be determined
188 Value* dependee = 0;
Owen Anderson6b278fc2007-07-10 17:08:11 +0000189 uint64_t dependeeSize = 0;
Owen Andersone314eb32007-07-10 18:11:42 +0000190 bool queryIsVolatile = false;
Owen Andersonfaac5182007-07-16 21:52:50 +0000191 if (StoreInst* S = dyn_cast<StoreInst>(query)) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000192 dependee = S->getPointerOperand();
Owen Anderson7a616a12007-07-10 17:25:03 +0000193 dependeeSize = TD.getTypeSize(S->getOperand(0)->getType());
Owen Andersone314eb32007-07-10 18:11:42 +0000194 queryIsVolatile = S->isVolatile();
Owen Andersonfaac5182007-07-16 21:52:50 +0000195 } else if (LoadInst* L = dyn_cast<LoadInst>(query)) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000196 dependee = L->getPointerOperand();
Owen Anderson7a616a12007-07-10 17:25:03 +0000197 dependeeSize = TD.getTypeSize(L->getType());
Owen Andersone314eb32007-07-10 18:11:42 +0000198 queryIsVolatile = L->isVolatile();
Owen Andersonfaac5182007-07-16 21:52:50 +0000199 } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) {
Owen Anderson06b6e822007-07-10 18:43:15 +0000200 dependee = V->getOperand(0);
201 dependeeSize = TD.getTypeSize(V->getType());
Owen Andersonfaac5182007-07-16 21:52:50 +0000202 } else if (FreeInst* F = dyn_cast<FreeInst>(query)) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000203 dependee = F->getPointerOperand();
Owen Anderson6b278fc2007-07-10 17:08:11 +0000204
205 // FreeInsts erase the entire structure, not just a field
206 dependeeSize = ~0UL;
Owen Andersonfaac5182007-07-16 21:52:50 +0000207 } else if (CallSite::get(query).getInstruction() != 0)
208 return getCallSiteDependency(CallSite::get(query), start);
Owen Anderson5f323202007-07-10 17:59:22 +0000209 else if (isa<AllocationInst>(query))
Owen Anderson78e02f72007-07-06 23:14:35 +0000210 return None;
Owen Anderson7a616a12007-07-10 17:25:03 +0000211 else
Owen Anderson6b278fc2007-07-10 17:08:11 +0000212 return None;
Owen Anderson78e02f72007-07-06 23:14:35 +0000213
Owen Anderson4beedbd2007-07-24 21:52:37 +0000214 BasicBlock::iterator blockBegin = block ? block->begin()
215 : query->getParent()->begin();
Owen Anderson78e02f72007-07-06 23:14:35 +0000216
217 while (QI != blockBegin) {
Owen Anderson6b278fc2007-07-10 17:08:11 +0000218 --QI;
219
Owen Anderson78e02f72007-07-06 23:14:35 +0000220 // If this inst is a memory op, get the pointer it accessed
221 Value* pointer = 0;
Owen Anderson6b278fc2007-07-10 17:08:11 +0000222 uint64_t pointerSize = 0;
223 if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
Owen Andersone314eb32007-07-10 18:11:42 +0000224 // All volatile loads/stores depend on each other
225 if (queryIsVolatile && S->isVolatile()) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000226 if (!start || block) {
Owen Andersonfaac5182007-07-16 21:52:50 +0000227 depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true)));
228 reverseDep.insert(std::make_pair(S, query));
229 }
230
Owen Andersone314eb32007-07-10 18:11:42 +0000231 return S;
232 }
233
Owen Anderson78e02f72007-07-06 23:14:35 +0000234 pointer = S->getPointerOperand();
Owen Anderson7a616a12007-07-10 17:25:03 +0000235 pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
Owen Anderson6b278fc2007-07-10 17:08:11 +0000236 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
Owen Andersone314eb32007-07-10 18:11:42 +0000237 // All volatile loads/stores depend on each other
238 if (queryIsVolatile && L->isVolatile()) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000239 if (!start || block) {
Owen Andersonfaac5182007-07-16 21:52:50 +0000240 depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true)));
241 reverseDep.insert(std::make_pair(L, query));
242 }
243
Owen Andersone314eb32007-07-10 18:11:42 +0000244 return L;
245 }
246
Owen Anderson78e02f72007-07-06 23:14:35 +0000247 pointer = L->getPointerOperand();
Owen Anderson7a616a12007-07-10 17:25:03 +0000248 pointerSize = TD.getTypeSize(L->getType());
Owen Anderson6b278fc2007-07-10 17:08:11 +0000249 } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
250 pointer = AI;
Owen Anderson7a616a12007-07-10 17:25:03 +0000251 if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
Owen Anderson8e850482007-07-10 20:48:38 +0000252 pointerSize = C->getZExtValue() * TD.getTypeSize(AI->getAllocatedType());
Owen Anderson6b278fc2007-07-10 17:08:11 +0000253 else
254 pointerSize = ~0UL;
Owen Anderson06b6e822007-07-10 18:43:15 +0000255 } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
256 pointer = V->getOperand(0);
257 pointerSize = TD.getTypeSize(V->getType());
Owen Anderson6b278fc2007-07-10 17:08:11 +0000258 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000259 pointer = F->getPointerOperand();
Owen Anderson6b278fc2007-07-10 17:08:11 +0000260
261 // FreeInsts erase the entire structure
262 pointerSize = ~0UL;
Owen Anderson5f323202007-07-10 17:59:22 +0000263 } else if (CallSite::get(QI).getInstruction() != 0) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000264 // Call insts need special handling. Check is they can modify our pointer
Owen Anderson5f323202007-07-10 17:59:22 +0000265 if (AA.getModRefInfo(CallSite::get(QI), dependee, dependeeSize) !=
266 AliasAnalysis::NoModRef) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000267 if (!start || block) {
Owen Andersonfaac5182007-07-16 21:52:50 +0000268 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true)));
269 reverseDep.insert(std::make_pair(QI, query));
270 }
271
Owen Anderson5f323202007-07-10 17:59:22 +0000272 return QI;
Owen Anderson7a616a12007-07-10 17:25:03 +0000273 } else {
274 continue;
275 }
Owen Anderson78e02f72007-07-06 23:14:35 +0000276 }
277
278 // If we found a pointer, check if it could be the same as our pointer
279 if (pointer) {
Owen Anderson6b278fc2007-07-10 17:08:11 +0000280 AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize,
281 dependee, dependeeSize);
Owen Anderson78e02f72007-07-06 23:14:35 +0000282
283 if (R != AliasAnalysis::NoAlias) {
Owen Anderson0cd32032007-07-25 19:57:03 +0000284 if (!start || block) {
Owen Andersonfaac5182007-07-16 21:52:50 +0000285 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true)));
286 reverseDep.insert(std::make_pair(QI, query));
287 }
288
Owen Anderson78e02f72007-07-06 23:14:35 +0000289 return QI;
290 }
291 }
Owen Anderson78e02f72007-07-06 23:14:35 +0000292 }
293
294 // If we found nothing, return the non-local flag
Owen Anderson0cd32032007-07-25 19:57:03 +0000295 if (!start || block) {
Owen Andersonfaac5182007-07-16 21:52:50 +0000296 depGraphLocal.insert(std::make_pair(query,
297 std::make_pair(NonLocal, true)));
298 reverseDep.insert(std::make_pair(NonLocal, query));
299 }
Owen Anderson78e02f72007-07-06 23:14:35 +0000300
301 return NonLocal;
302}
303
304/// removeInstruction - Remove an instruction from the dependence analysis,
305/// updating the dependence of instructions that previously depended on it.
306void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
307 // Figure out the new dep for things that currently depend on rem
308 Instruction* newDep = NonLocal;
Owen Anderson521a2022007-07-20 06:16:07 +0000309 if (depGraphLocal[rem].first != NonLocal &&
310 depGraphLocal[rem].second) {
Owen Anderson78e02f72007-07-06 23:14:35 +0000311 // If we have dep info for rem, set them to it
312 BasicBlock::iterator RI = depGraphLocal[rem].first;
313 RI++;
314 newDep = RI;
315 } else if (depGraphLocal[rem].first == NonLocal &&
316 depGraphLocal[rem].second ) {
317 // If we have a confirmed non-local flag, use it
318 newDep = NonLocal;
319 } else {
320 // Otherwise, use the immediate successor of rem
321 // NOTE: This is because, when getDependence is called, it will first check
322 // the immediate predecessor of what is in the cache.
323 BasicBlock::iterator RI = rem;
324 RI++;
325 newDep = RI;
326 }
327
328 std::multimap<Instruction*, Instruction*>::iterator I = reverseDep.find(rem);
329 while (I->first == rem) {
330 // Insert the new dependencies
331 // Mark it as unconfirmed as long as it is not the non-local flag
332 depGraphLocal[I->second] = std::make_pair(newDep, !newDep);
333 reverseDep.erase(I);
334 I = reverseDep.find(rem);
335 }
Owen Anderson1cb960a2007-07-12 00:06:21 +0000336
337 getAnalysis<AliasAnalysis>().deleteValue(rem);
Owen Anderson78e02f72007-07-06 23:14:35 +0000338}