blob: 8c6886da9020fde6e2ea157ae5f3b93b553ff78e [file] [log] [blame]
Owen Andersonc0daf5f2007-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 Anderson2552a122007-07-10 17:25:03 +000018#include "llvm/Constants.h"
Owen Andersonc0daf5f2007-07-06 23:14:35 +000019#include "llvm/Instructions.h"
20#include "llvm/Function.h"
21#include "llvm/Analysis/AliasAnalysis.h"
22#include "llvm/Target/TargetData.h"
23
24using namespace llvm;
25
26char MemoryDependenceAnalysis::ID = 0;
27
28Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)0;
29Instruction* MemoryDependenceAnalysis::None = (Instruction*)~0;
30
31// Register this pass...
32RegisterPass<MemoryDependenceAnalysis> X("memdep",
33 "Memory Dependence Analysis");
34
35/// getAnalysisUsage - Does not modify anything. It uses Alias Analysis.
36///
37void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
38 AU.setPreservesAll();
39 AU.addRequiredTransitive<AliasAnalysis>();
40 AU.addRequiredTransitive<TargetData>();
41}
42
43/// getDependency - Return the instruction on which a memory operation
Owen Anderson47352db2007-07-10 17:08:11 +000044/// depends. The local paramter indicates if the query should only
45/// evaluate dependencies within the same basic block.
Owen Andersonc0daf5f2007-07-06 23:14:35 +000046Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
47 bool local) {
48 if (!local)
49 assert(0 && "Non-local memory dependence is not yet supported.");
50
51 // Start looking for dependencies with the queried inst
52 BasicBlock::iterator QI = query;
53
54 // Check for a cached result
55 std::pair<Instruction*, bool> cachedResult = depGraphLocal[query];
56 // If we have a _confirmed_ cached entry, return it
57 if (cachedResult.second)
58 return cachedResult.first;
59 else if (cachedResult.first != NonLocal)
60 // If we have an unconfirmed cached entry, we can start our search from there
61 QI = cachedResult.first;
62
63 AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
Owen Anderson47352db2007-07-10 17:08:11 +000064 TargetData& TD = getAnalysis<TargetData>();
Owen Andersonc0daf5f2007-07-06 23:14:35 +000065
66 // Get the pointer value for which dependence will be determined
67 Value* dependee = 0;
Owen Anderson47352db2007-07-10 17:08:11 +000068 uint64_t dependeeSize = 0;
69 if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +000070 dependee = S->getPointerOperand();
Owen Anderson2552a122007-07-10 17:25:03 +000071 dependeeSize = TD.getTypeSize(S->getOperand(0)->getType());
Owen Anderson47352db2007-07-10 17:08:11 +000072 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +000073 dependee = L->getPointerOperand();
Owen Anderson2552a122007-07-10 17:25:03 +000074 dependeeSize = TD.getTypeSize(L->getType());
Owen Anderson47352db2007-07-10 17:08:11 +000075 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +000076 dependee = F->getPointerOperand();
Owen Anderson47352db2007-07-10 17:08:11 +000077
78 // FreeInsts erase the entire structure, not just a field
79 dependeeSize = ~0UL;
Owen Anderson2552a122007-07-10 17:25:03 +000080 } else if (isa<AllocationInst>(query))
Owen Andersonc0daf5f2007-07-06 23:14:35 +000081 return None;
Owen Anderson2552a122007-07-10 17:25:03 +000082 else
Owen Anderson47352db2007-07-10 17:08:11 +000083 // FIXME: Call/InvokeInsts need proper handling
84 return None;
Owen Andersonc0daf5f2007-07-06 23:14:35 +000085
Owen Andersonc0daf5f2007-07-06 23:14:35 +000086
Owen Anderson47352db2007-07-10 17:08:11 +000087 BasicBlock::iterator blockBegin = query->getParent()->begin();
Owen Andersonc0daf5f2007-07-06 23:14:35 +000088
89 while (QI != blockBegin) {
Owen Anderson47352db2007-07-10 17:08:11 +000090 --QI;
91
Owen Andersonc0daf5f2007-07-06 23:14:35 +000092 // If this inst is a memory op, get the pointer it accessed
93 Value* pointer = 0;
Owen Anderson47352db2007-07-10 17:08:11 +000094 uint64_t pointerSize = 0;
95 if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +000096 pointer = S->getPointerOperand();
Owen Anderson2552a122007-07-10 17:25:03 +000097 pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
Owen Anderson47352db2007-07-10 17:08:11 +000098 } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +000099 pointer = L->getPointerOperand();
Owen Anderson2552a122007-07-10 17:25:03 +0000100 pointerSize = TD.getTypeSize(L->getType());
Owen Anderson47352db2007-07-10 17:08:11 +0000101 } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
102 pointer = AI;
Owen Anderson2552a122007-07-10 17:25:03 +0000103 if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
104 pointerSize = C->getZExtValue();
Owen Anderson47352db2007-07-10 17:08:11 +0000105 else
106 pointerSize = ~0UL;
107 } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000108 pointer = F->getPointerOperand();
Owen Anderson47352db2007-07-10 17:08:11 +0000109
110 // FreeInsts erase the entire structure
111 pointerSize = ~0UL;
Owen Anderson2552a122007-07-10 17:25:03 +0000112 } else if (CallInst* C = dyn_cast<CallInst>(QI)) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000113 // Call insts need special handling. Check is they can modify our pointer
Owen Anderson47352db2007-07-10 17:08:11 +0000114 if (AA.getModRefInfo(C, dependee, dependeeSize) != AliasAnalysis::NoModRef) {
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000115 depGraphLocal.insert(std::make_pair(query, std::make_pair(C, true)));
116 reverseDep.insert(std::make_pair(C, query));
117 return C;
118 } else {
119 continue;
120 }
Owen Anderson2552a122007-07-10 17:25:03 +0000121 } else if (InvokeInst* I = dyn_cast<InvokeInst>(QI)) {
122 // Invoke insts need special handling. Check is they can modify our pointer
123 if (AA.getModRefInfo(I, dependee, dependeeSize) != AliasAnalysis::NoModRef) {
124 depGraphLocal.insert(std::make_pair(query, std::make_pair(I, true)));
125 reverseDep.insert(std::make_pair(I, query));
126 return I;
127 } else {
128 continue;
129 }
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000130 }
131
132 // If we found a pointer, check if it could be the same as our pointer
133 if (pointer) {
Owen Anderson47352db2007-07-10 17:08:11 +0000134 AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize,
135 dependee, dependeeSize);
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000136
137 if (R != AliasAnalysis::NoAlias) {
138 depGraphLocal.insert(std::make_pair(query, std::make_pair(QI, true)));
139 reverseDep.insert(std::make_pair(QI, query));
140 return QI;
141 }
142 }
Owen Andersonc0daf5f2007-07-06 23:14:35 +0000143 }
144
145 // If we found nothing, return the non-local flag
146 depGraphLocal.insert(std::make_pair(query,
147 std::make_pair(NonLocal, true)));
148 reverseDep.insert(std::make_pair(NonLocal, query));
149
150 return NonLocal;
151}
152
153/// removeInstruction - Remove an instruction from the dependence analysis,
154/// updating the dependence of instructions that previously depended on it.
155void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
156 // Figure out the new dep for things that currently depend on rem
157 Instruction* newDep = NonLocal;
158 if (depGraphLocal[rem].first != NonLocal) {
159 // If we have dep info for rem, set them to it
160 BasicBlock::iterator RI = depGraphLocal[rem].first;
161 RI++;
162 newDep = RI;
163 } else if (depGraphLocal[rem].first == NonLocal &&
164 depGraphLocal[rem].second ) {
165 // If we have a confirmed non-local flag, use it
166 newDep = NonLocal;
167 } else {
168 // Otherwise, use the immediate successor of rem
169 // NOTE: This is because, when getDependence is called, it will first check
170 // the immediate predecessor of what is in the cache.
171 BasicBlock::iterator RI = rem;
172 RI++;
173 newDep = RI;
174 }
175
176 std::multimap<Instruction*, Instruction*>::iterator I = reverseDep.find(rem);
177 while (I->first == rem) {
178 // Insert the new dependencies
179 // Mark it as unconfirmed as long as it is not the non-local flag
180 depGraphLocal[I->second] = std::make_pair(newDep, !newDep);
181 reverseDep.erase(I);
182 I = reverseDep.find(rem);
183 }
184}