blob: ed1e4e16085e34757020c67eba62b691c5f8ac9a [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"
18#include "llvm/Instructions.h"
19#include "llvm/Function.h"
20#include "llvm/Analysis/AliasAnalysis.h"
21#include "llvm/Target/TargetData.h"
22
23using namespace llvm;
24
25char MemoryDependenceAnalysis::ID = 0;
26
27Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)0;
28Instruction* MemoryDependenceAnalysis::None = (Instruction*)~0;
29
30// Register this pass...
31RegisterPass<MemoryDependenceAnalysis> X("memdep",
32 "Memory Dependence Analysis");
33
34/// getAnalysisUsage - Does not modify anything. It uses Alias Analysis.
35///
36void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
37 AU.setPreservesAll();
38 AU.addRequiredTransitive<AliasAnalysis>();
39 AU.addRequiredTransitive<TargetData>();
40}
41
42/// getDependency - Return the instruction on which a memory operation
43/// depends. NOTE: A return value of NULL indicates that no dependency
44/// was found in the parent block.
45Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
46 bool local) {
47 if (!local)
48 assert(0 && "Non-local memory dependence is not yet supported.");
49
50 // Start looking for dependencies with the queried inst
51 BasicBlock::iterator QI = query;
52
53 // Check for a cached result
54 std::pair<Instruction*, bool> cachedResult = depGraphLocal[query];
55 // If we have a _confirmed_ cached entry, return it
56 if (cachedResult.second)
57 return cachedResult.first;
58 else if (cachedResult.first != NonLocal)
59 // If we have an unconfirmed cached entry, we can start our search from there
60 QI = cachedResult.first;
61
62 AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
63
64 BasicBlock::iterator blockBegin = query->getParent()->begin();
65
66 // Get the pointer value for which dependence will be determined
67 Value* dependee = 0;
68 if (StoreInst* S = dyn_cast<StoreInst>(QI))
69 dependee = S->getPointerOperand();
70 else if (LoadInst* L = dyn_cast<LoadInst>(QI))
71 dependee = L->getPointerOperand();
72 else if (FreeInst* F = dyn_cast<FreeInst>(QI))
73 dependee = F->getPointerOperand();
74 else if (isa<AllocationInst>(query)) {
75 // Allocations don't depend on anything
76 depGraphLocal.insert(std::make_pair(query, std::make_pair(None,
77 true)));
78 reverseDep.insert(std::make_pair(None, query));
79 return None;
80 } else {
81 // Non-memory operations depend on their immediate predecessor
82 --QI;
83 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true)));
84 reverseDep.insert(std::make_pair(QI, query));
85 return QI;
86 }
87
88 // Start with the predecessor of the queried inst
89 --QI;
90
91 TargetData& TD = getAnalysis<TargetData>();
92
93 while (QI != blockBegin) {
94 // If this inst is a memory op, get the pointer it accessed
95 Value* pointer = 0;
96 if (StoreInst* S = dyn_cast<StoreInst>(QI))
97 pointer = S->getPointerOperand();
98 else if (LoadInst* L = dyn_cast<LoadInst>(QI))
99 pointer = L->getPointerOperand();
100 else if (isa<AllocationInst>(QI))
101 pointer = QI;
102 else if (FreeInst* F = dyn_cast<FreeInst>(QI))
103 pointer = F->getPointerOperand();
104 else if (CallInst* C = dyn_cast<CallInst>(QI)) {
105 // Call insts need special handling. Check is they can modify our pointer
106 if (AA.getModRefInfo(C, dependee, TD.getTypeSize(dependee->getType())) !=
107 AliasAnalysis::NoModRef) {
108 depGraphLocal.insert(std::make_pair(query, std::make_pair(C, true)));
109 reverseDep.insert(std::make_pair(C, query));
110 return C;
111 } else {
112 continue;
113 }
114 }
115
116 // If we found a pointer, check if it could be the same as our pointer
117 if (pointer) {
118 AliasAnalysis::AliasResult R = AA.alias(
119 pointer, TD.getTypeSize(pointer->getType()),
120 dependee, TD.getTypeSize(dependee->getType()));
121
122 if (R != AliasAnalysis::NoAlias) {
123 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true)));
124 reverseDep.insert(std::make_pair(QI, query));
125 return QI;
126 }
127 }
128
129 QI--;
130 }
131
132 // If we found nothing, return the non-local flag
133 depGraphLocal.insert(std::make_pair(query,
134 std::make_pair(NonLocal, true)));
135 reverseDep.insert(std::make_pair(NonLocal, query));
136
137 return NonLocal;
138}
139
140/// removeInstruction - Remove an instruction from the dependence analysis,
141/// updating the dependence of instructions that previously depended on it.
142void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
143 // Figure out the new dep for things that currently depend on rem
144 Instruction* newDep = NonLocal;
145 if (depGraphLocal[rem].first != NonLocal) {
146 // If we have dep info for rem, set them to it
147 BasicBlock::iterator RI = depGraphLocal[rem].first;
148 RI++;
149 newDep = RI;
150 } else if (depGraphLocal[rem].first == NonLocal &&
151 depGraphLocal[rem].second ) {
152 // If we have a confirmed non-local flag, use it
153 newDep = NonLocal;
154 } else {
155 // Otherwise, use the immediate successor of rem
156 // NOTE: This is because, when getDependence is called, it will first check
157 // the immediate predecessor of what is in the cache.
158 BasicBlock::iterator RI = rem;
159 RI++;
160 newDep = RI;
161 }
162
163 std::multimap<Instruction*, Instruction*>::iterator I = reverseDep.find(rem);
164 while (I->first == rem) {
165 // Insert the new dependencies
166 // Mark it as unconfirmed as long as it is not the non-local flag
167 depGraphLocal[I->second] = std::make_pair(newDep, !newDep);
168 reverseDep.erase(I);
169 I = reverseDep.find(rem);
170 }
171}