MemoryDependenceAnalysis.cpp revision 80b1f09693dd849620330da76b445fa0b3873dd1
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
29const Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)-3;
30const Instruction* MemoryDependenceAnalysis::None = (Instruction*)-4;
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
45const Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
46                                                           Instruction* start,
47                                                            BasicBlock* block) {
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  if (start) {
55    QI = start;
56    blockBegin = start->getParent()->end();
57  } else if (!start && block) {
58    QI = block->end();
59    blockBegin = block->end();
60  }
61
62  while (QI != blockBegin) {
63    --QI;
64
65    // If this inst is a memory op, get the pointer it accessed
66    Value* pointer = 0;
67    uint64_t pointerSize = 0;
68    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
69      pointer = S->getPointerOperand();
70      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
71    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
72      pointer = L->getPointerOperand();
73      pointerSize = TD.getTypeSize(L->getType());
74    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
75      pointer = AI;
76      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
77        pointerSize = C->getZExtValue() * \
78                      TD.getTypeSize(AI->getAllocatedType());
79      else
80        pointerSize = ~0UL;
81    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
82      pointer = V->getOperand(0);
83      pointerSize = TD.getTypeSize(V->getType());
84    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
85      pointer = F->getPointerOperand();
86
87      // FreeInsts erase the entire structure
88      pointerSize = ~0UL;
89    } else if (CallSite::get(QI).getInstruction() != 0) {
90      if (AA.getModRefInfo(C, CallSite::get(QI)) != AliasAnalysis::NoModRef) {
91        if (!start && !block) {
92          depGraphLocal.insert(std::make_pair(C.getInstruction(),
93                                              std::make_pair(QI, true)));
94          reverseDep[QI].insert(C.getInstruction());
95        }
96        return QI;
97      } else {
98        continue;
99      }
100    } else
101      continue;
102
103    if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) {
104      if (!start && !block) {
105        depGraphLocal.insert(std::make_pair(C.getInstruction(),
106                                            std::make_pair(QI, true)));
107        reverseDep[QI].insert(C.getInstruction());
108      }
109      return QI;
110    }
111  }
112
113  // No dependence found
114  depGraphLocal.insert(std::make_pair(C.getInstruction(),
115                                      std::make_pair(NonLocal, true)));
116  reverseDep[NonLocal].insert(C.getInstruction());
117  return NonLocal;
118}
119
120void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
121                                              BasicBlock* block,
122                                         DenseMap<BasicBlock*, Value*>& resp) {
123  SmallPtrSet<BasicBlock*, 4> visited;
124  SmallVector<BasicBlock*, 4> stack;
125  stack.push_back(block);
126
127  while (!stack.empty()) {
128    BasicBlock* BB = stack.back();
129
130    if (visited.count(BB)) {
131      stack.pop_back();
132      continue;
133    }
134
135    if (BB != block) {
136      visited.insert(BB);
137
138      const Instruction* localDep = getDependency(query, 0, BB);
139      if (localDep != NonLocal) {
140        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));
141        stack.pop_back();
142
143        continue;
144      }
145    } else if (BB == block && stack.size() > 1) {
146      visited.insert(BB);
147
148      const Instruction* localDep = getDependency(query, 0, BB);
149      if (localDep != query)
150        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));
151
152      stack.pop_back();
153
154      continue;
155    }
156
157    bool predOnStack = false;
158    bool inserted = false;
159    for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
160         PI != PE; ++PI)
161      if (!visited.count(*PI)) {
162        stack.push_back(*PI);
163        inserted = true;
164      } else
165        predOnStack = true;
166
167    if (inserted)
168      continue;
169    else if (!inserted && !predOnStack) {
170      resp.insert(std::make_pair(BB, const_cast<Instruction*>(None)));
171    } else if (!inserted && predOnStack){
172      resp.insert(std::make_pair(BB, const_cast<Instruction*>(NonLocal)));
173    }
174
175    stack.pop_back();
176  }
177}
178
179/// getNonLocalDependency - Fills the passed-in map with the non-local
180/// dependencies of the queries.  The map will contain NonLocal for
181/// blocks between the query and its dependencies.
182void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
183                                         DenseMap<BasicBlock*, Value*>& resp) {
184  const Instruction* localDep = getDependency(query);
185  if (localDep != NonLocal) {
186    resp.insert(std::make_pair(query->getParent(),
187                               const_cast<Instruction*>(localDep)));
188    return;
189  }
190
191  nonLocalHelper(query, query->getParent(), resp);
192}
193
194/// getDependency - Return the instruction on which a memory operation
195/// depends.  The local paramter indicates if the query should only
196/// evaluate dependencies within the same basic block.
197const Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
198                                                     Instruction* start,
199                                                     BasicBlock* block) {
200  // Start looking for dependencies with the queried inst
201  BasicBlock::iterator QI = query;
202
203  // Check for a cached result
204  std::pair<const Instruction*, bool> cachedResult = depGraphLocal[query];
205  // If we have a _confirmed_ cached entry, return it
206  if (cachedResult.second)
207    return cachedResult.first;
208  else if (cachedResult.first && cachedResult.first != NonLocal)
209  // If we have an unconfirmed cached entry, we can start our search from there
210    QI = const_cast<Instruction*>(cachedResult.first);
211
212  if (start)
213    QI = start;
214  else if (!start && block)
215    QI = block->end();
216
217  AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
218  TargetData& TD = getAnalysis<TargetData>();
219
220  // Get the pointer value for which dependence will be determined
221  Value* dependee = 0;
222  uint64_t dependeeSize = 0;
223  bool queryIsVolatile = false;
224  if (StoreInst* S = dyn_cast<StoreInst>(query)) {
225    dependee = S->getPointerOperand();
226    dependeeSize = TD.getTypeSize(S->getOperand(0)->getType());
227    queryIsVolatile = S->isVolatile();
228  } else if (LoadInst* L = dyn_cast<LoadInst>(query)) {
229    dependee = L->getPointerOperand();
230    dependeeSize = TD.getTypeSize(L->getType());
231    queryIsVolatile = L->isVolatile();
232  } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) {
233    dependee = V->getOperand(0);
234    dependeeSize = TD.getTypeSize(V->getType());
235  } else if (FreeInst* F = dyn_cast<FreeInst>(query)) {
236    dependee = F->getPointerOperand();
237
238    // FreeInsts erase the entire structure, not just a field
239    dependeeSize = ~0UL;
240  } else if (CallSite::get(query).getInstruction() != 0)
241    return getCallSiteDependency(CallSite::get(query), start, block);
242  else if (isa<AllocationInst>(query))
243    return None;
244  else
245    return None;
246
247  BasicBlock::iterator blockBegin = block ? block->begin()
248                                          : query->getParent()->begin();
249
250  while (QI != blockBegin) {
251    --QI;
252
253    // If this inst is a memory op, get the pointer it accessed
254    Value* pointer = 0;
255    uint64_t pointerSize = 0;
256    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
257      // All volatile loads/stores depend on each other
258      if (queryIsVolatile && S->isVolatile()) {
259        if (!start && !block) {
260          depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true)));
261          reverseDep[S].insert(query);
262        }
263
264        return S;
265      }
266
267      pointer = S->getPointerOperand();
268      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
269    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
270      // All volatile loads/stores depend on each other
271      if (queryIsVolatile && L->isVolatile()) {
272        if (!start && !block) {
273          depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true)));
274          reverseDep[L].insert(query);
275        }
276
277        return L;
278      }
279
280      pointer = L->getPointerOperand();
281      pointerSize = TD.getTypeSize(L->getType());
282    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
283      pointer = AI;
284      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
285        pointerSize = C->getZExtValue() * \
286                      TD.getTypeSize(AI->getAllocatedType());
287      else
288        pointerSize = ~0UL;
289    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
290      pointer = V->getOperand(0);
291      pointerSize = TD.getTypeSize(V->getType());
292    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
293      pointer = F->getPointerOperand();
294
295      // FreeInsts erase the entire structure
296      pointerSize = ~0UL;
297    } else if (CallSite::get(QI).getInstruction() != 0) {
298      // Call insts need special handling. Check if they can modify our pointer
299      AliasAnalysis::ModRefResult MR = AA.getModRefInfo(CallSite::get(QI),
300                                                      dependee, dependeeSize);
301
302      if (MR != AliasAnalysis::NoModRef) {
303        // Loads don't depend on read-only calls
304        if (isa<LoadInst>(query) && MR == AliasAnalysis::Ref)
305          continue;
306
307        if (!start && !block) {
308          depGraphLocal.insert(std::make_pair(query,
309                                              std::make_pair(QI, true)));
310          reverseDep[QI].insert(query);
311        }
312
313        return QI;
314      } else {
315        continue;
316      }
317    }
318
319    // If we found a pointer, check if it could be the same as our pointer
320    if (pointer) {
321      AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize,
322                                              dependee, dependeeSize);
323
324      if (R != AliasAnalysis::NoAlias) {
325        // May-alias loads don't depend on each other
326        if (isa<LoadInst>(query) && isa<LoadInst>(QI) &&
327            R == AliasAnalysis::MayAlias)
328          continue;
329
330        if (!start && !block) {
331          depGraphLocal.insert(std::make_pair(query,
332                                              std::make_pair(QI, true)));
333          reverseDep[QI].insert(query);
334        }
335
336        return QI;
337      }
338    }
339  }
340
341  // If we found nothing, return the non-local flag
342  if (!start && !block) {
343    depGraphLocal.insert(std::make_pair(query,
344                                        std::make_pair(NonLocal, true)));
345    reverseDep[NonLocal].insert(query);
346  }
347
348  return NonLocal;
349}
350
351/// removeInstruction - Remove an instruction from the dependence analysis,
352/// updating the dependence of instructions that previously depended on it.
353void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
354  // Figure out the new dep for things that currently depend on rem
355  const Instruction* newDep = NonLocal;
356
357  depMapType::iterator depGraphEntry = depGraphLocal.find(rem);
358  // We assume here that it's not in the reverse map if it's not in
359  // the dep map.  Checking it could be expensive, so don't do it.
360
361  if (depGraphEntry != depGraphLocal.end()) {
362    if (depGraphEntry->second.first != NonLocal &&
363        depGraphEntry->second.second) {
364      // If we have dep info for rem, set them to it
365      BasicBlock::iterator RI =
366                         const_cast<Instruction*>(depGraphEntry->second.first);
367      RI++;
368      newDep = RI;
369    } else if (depGraphEntry->second.first == NonLocal &&
370               depGraphEntry->second.second ) {
371      // If we have a confirmed non-local flag, use it
372      newDep = NonLocal;
373    } else {
374      // Otherwise, use the immediate successor of rem
375      // NOTE: This is because, when getDependence is called, it will first
376      // check the immediate predecessor of what is in the cache.
377      BasicBlock::iterator RI = rem;
378      RI++;
379      newDep = RI;
380    }
381
382    SmallPtrSet<Instruction*, 4>& set = reverseDep[rem];
383    for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
384         I != E; ++I) {
385      // Insert the new dependencies
386      // Mark it as unconfirmed as long as it is not the non-local flag
387      depGraphLocal[*I] = std::make_pair(newDep, !newDep);
388    }
389    reverseDep.erase(rem);
390  }
391
392  getAnalysis<AliasAnalysis>().deleteValue(rem);
393}
394