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