blob: 215b4e2ba7140cca776a77c386082fa290d33c7d [file] [log] [blame]
Vikram S. Adve96b21c12002-12-08 13:26:29 +00001//===- MemoryDepAnalysis.cpp - Compute dep graph for memory ops --*-C++-*--===//
2//
3// This file implements a pass (MemoryDepAnalysis) that computes memory-based
4// data dependences between instructions for each function in a module.
5// Memory-based dependences occur due to load and store operations, but
6// also the side-effects of call instructions.
7//
8// The result of this pass is a DependenceGraph for each function
9// representing the memory-based data dependences between instructions.
10//===----------------------------------------------------------------------===//
11
12#include "llvm/Analysis/MemoryDepAnalysis.h"
13#include "llvm/Analysis/IPModRef.h"
14#include "llvm/Analysis/DataStructure.h"
15#include "llvm/Analysis/DSGraph.h"
16#include "llvm/Module.h"
Vikram S. Adve96b21c12002-12-08 13:26:29 +000017#include "llvm/iMemory.h"
18#include "llvm/iOther.h"
19#include "llvm/Support/InstVisitor.h"
20#include "llvm/Support/CFG.h"
21#include "Support/TarjanSCCIterator.h"
22#include "Support/Statistic.h"
Vikram S. Adve96b21c12002-12-08 13:26:29 +000023#include "Support/STLExtras.h"
24#include "Support/hash_map"
25#include "Support/hash_set"
Vikram S. Adve96b21c12002-12-08 13:26:29 +000026
27
28///--------------------------------------------------------------------------
29/// struct ModRefTable:
30///
31/// A data structure that tracks ModRefInfo for instructions:
32/// -- modRefMap is a map of Instruction* -> ModRefInfo for the instr.
33/// -- definers is a vector of instructions that define any node
34/// -- users is a vector of instructions that reference any node
35/// -- numUsersBeforeDef is a vector indicating that the number of users
36/// seen before definers[i] is numUsersBeforeDef[i].
37///
38/// numUsersBeforeDef[] effectively tells us the exact interleaving of
39/// definers and users within the ModRefTable.
40/// This is only maintained when constructing the table for one SCC, and
41/// not copied over from one table to another since it is no longer useful.
42///--------------------------------------------------------------------------
43
Chris Lattner95008bc2003-08-31 19:40:57 +000044struct ModRefTable {
Vikram S. Adve96b21c12002-12-08 13:26:29 +000045 typedef hash_map<Instruction*, ModRefInfo> ModRefMap;
46 typedef ModRefMap::const_iterator const_map_iterator;
47 typedef ModRefMap:: iterator map_iterator;
48 typedef std::vector<Instruction*>::const_iterator const_ref_iterator;
49 typedef std::vector<Instruction*>:: iterator ref_iterator;
50
51 ModRefMap modRefMap;
52 std::vector<Instruction*> definers;
53 std::vector<Instruction*> users;
54 std::vector<unsigned> numUsersBeforeDef;
55
56 // Iterators to enumerate all the defining instructions
57 const_ref_iterator defsBegin() const { return definers.begin(); }
58 ref_iterator defsBegin() { return definers.begin(); }
59 const_ref_iterator defsEnd() const { return definers.end(); }
60 ref_iterator defsEnd() { return definers.end(); }
61
62 // Iterators to enumerate all the user instructions
63 const_ref_iterator usersBegin() const { return users.begin(); }
64 ref_iterator usersBegin() { return users.begin(); }
65 const_ref_iterator usersEnd() const { return users.end(); }
66 ref_iterator usersEnd() { return users.end(); }
67
68 // Iterator identifying the last user that was seen *before* a
69 // specified def. In particular, all users in the half-closed range
70 // [ usersBegin(), usersBeforeDef_End(defPtr) )
71 // were seen *before* the specified def. All users in the half-closed range
72 // [ usersBeforeDef_End(defPtr), usersEnd() )
73 // were seen *after* the specified def.
74 //
75 ref_iterator usersBeforeDef_End(const_ref_iterator defPtr) {
76 unsigned defIndex = (unsigned) (defPtr - defsBegin());
77 assert(defIndex < numUsersBeforeDef.size());
78 assert(usersBegin() + numUsersBeforeDef[defIndex] <= usersEnd());
79 return usersBegin() + numUsersBeforeDef[defIndex];
80 }
81 const_ref_iterator usersBeforeDef_End(const_ref_iterator defPtr) const {
82 return const_cast<ModRefTable*>(this)->usersBeforeDef_End(defPtr);
83 }
84
85 //
86 // Modifier methods
87 //
88 void AddDef(Instruction* D) {
89 definers.push_back(D);
90 numUsersBeforeDef.push_back(users.size());
91 }
92 void AddUse(Instruction* U) {
93 users.push_back(U);
94 }
95 void Insert(const ModRefTable& fromTable) {
96 modRefMap.insert(fromTable.modRefMap.begin(), fromTable.modRefMap.end());
97 definers.insert(definers.end(),
98 fromTable.definers.begin(), fromTable.definers.end());
99 users.insert(users.end(),
100 fromTable.users.begin(), fromTable.users.end());
101 numUsersBeforeDef.clear(); /* fromTable.numUsersBeforeDef is ignored */
102 }
103};
104
105
106///--------------------------------------------------------------------------
107/// class ModRefInfoBuilder:
108///
109/// A simple InstVisitor<> class that retrieves the Mod/Ref info for
110/// Load/Store/Call instructions and inserts this information in
111/// a ModRefTable. It also records all instructions that Mod any node
112/// and all that use any node.
113///--------------------------------------------------------------------------
114
Chris Lattner80431272003-08-06 17:16:24 +0000115class ModRefInfoBuilder : public InstVisitor<ModRefInfoBuilder> {
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000116 const DSGraph& funcGraph;
117 const FunctionModRefInfo& funcModRef;
118 ModRefTable& modRefTable;
119
Chris Lattner80431272003-08-06 17:16:24 +0000120 ModRefInfoBuilder(); // DO NOT IMPLEMENT
121 ModRefInfoBuilder(const ModRefInfoBuilder&); // DO NOT IMPLEMENT
122 void operator=(const ModRefInfoBuilder&); // DO NOT IMPLEMENT
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000123
124public:
125 /*ctor*/ ModRefInfoBuilder(const DSGraph& _funcGraph,
126 const FunctionModRefInfo& _funcModRef,
127 ModRefTable& _modRefTable)
128 : funcGraph(_funcGraph), funcModRef(_funcModRef), modRefTable(_modRefTable)
129 {
130 }
131
132 // At a call instruction, retrieve the ModRefInfo using IPModRef results.
133 // Add the call to the defs list if it modifies any nodes and to the uses
134 // list if it refs any nodes.
135 //
136 void visitCallInst (CallInst& callInst) {
137 ModRefInfo safeModRef(funcGraph.getGraphSize());
138 const ModRefInfo* callModRef = funcModRef.getModRefInfo(callInst);
139 if (callModRef == NULL)
140 { // call to external/unknown function: mark all nodes as Mod and Ref
141 safeModRef.getModSet().set();
142 safeModRef.getRefSet().set();
143 callModRef = &safeModRef;
144 }
145
146 modRefTable.modRefMap.insert(std::make_pair(&callInst,
147 ModRefInfo(*callModRef)));
148 if (callModRef->getModSet().any())
149 modRefTable.AddDef(&callInst);
150 if (callModRef->getRefSet().any())
151 modRefTable.AddUse(&callInst);
152 }
153
154 // At a store instruction, add to the mod set the single node pointed to
155 // by the pointer argument of the store. Interestingly, if there is no
156 // such node, that would be a null pointer reference!
157 void visitStoreInst (StoreInst& storeInst) {
158 const DSNodeHandle& ptrNode =
159 funcGraph.getNodeForValue(storeInst.getPointerOperand());
160 if (const DSNode* target = ptrNode.getNode())
161 {
162 unsigned nodeId = funcModRef.getNodeId(target);
163 ModRefInfo& minfo =
164 modRefTable.modRefMap.insert(
165 std::make_pair(&storeInst,
166 ModRefInfo(funcGraph.getGraphSize()))).first->second;
167 minfo.setNodeIsMod(nodeId);
168 modRefTable.AddDef(&storeInst);
169 }
170 else
171 std::cerr << "Warning: Uninitialized pointer reference!\n";
172 }
173
174 // At a load instruction, add to the ref set the single node pointed to
175 // by the pointer argument of the load. Interestingly, if there is no
176 // such node, that would be a null pointer reference!
177 void visitLoadInst (LoadInst& loadInst) {
178 const DSNodeHandle& ptrNode =
179 funcGraph.getNodeForValue(loadInst.getPointerOperand());
180 if (const DSNode* target = ptrNode.getNode())
181 {
182 unsigned nodeId = funcModRef.getNodeId(target);
183 ModRefInfo& minfo =
184 modRefTable.modRefMap.insert(
185 std::make_pair(&loadInst,
186 ModRefInfo(funcGraph.getGraphSize()))).first->second;
187 minfo.setNodeIsRef(nodeId);
188 modRefTable.AddUse(&loadInst);
189 }
190 else
191 std::cerr << "Warning: Uninitialized pointer reference!\n";
192 }
193};
194
195
196//----------------------------------------------------------------------------
197// class MemoryDepAnalysis: A dep. graph for load/store/call instructions
198//----------------------------------------------------------------------------
199
Chris Lattner95008bc2003-08-31 19:40:57 +0000200
201/// getAnalysisUsage - This does not modify anything. It uses the Top-Down DS
202/// Graph and IPModRef.
203///
204void MemoryDepAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
205 AU.setPreservesAll();
206 AU.addRequired<TDDataStructures>();
207 AU.addRequired<IPModRef>();
208}
209
210
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000211/// Basic dependence gathering algorithm, using TarjanSCCIterator on CFG:
212///
213/// for every SCC S in the CFG in PostOrder on the SCC DAG
214/// {
215/// for every basic block BB in S in *postorder*
216/// for every instruction I in BB in reverse
217/// Add (I, ModRef[I]) to ModRefCurrent
218/// if (Mod[I] != NULL)
219/// Add I to DefSetCurrent: { I \in S : Mod[I] != NULL }
220/// if (Ref[I] != NULL)
221/// Add I to UseSetCurrent: { I : Ref[I] != NULL }
222///
223/// for every def D in DefSetCurrent
224///
225/// // NOTE: D comes after itself iff S contains a loop
226/// if (HasLoop(S) && D & D)
227/// Add output-dep: D -> D2
228///
229/// for every def D2 *after* D in DefSetCurrent
230/// // NOTE: D2 comes before D in execution order
231/// if (D & D2)
232/// Add output-dep: D2 -> D
233/// if (HasLoop(S))
234/// Add output-dep: D -> D2
235///
236/// for every use U in UseSetCurrent that was seen *before* D
237/// // NOTE: U comes after D in execution order
238/// if (U & D)
239/// if (U != D || HasLoop(S))
240/// Add true-dep: D -> U
241/// if (HasLoop(S))
242/// Add anti-dep: U -> D
243///
244/// for every use U in UseSetCurrent that was seen *after* D
245/// // NOTE: U comes before D in execution order
246/// if (U & D)
247/// if (U != D || HasLoop(S))
248/// Add anti-dep: U -> D
249/// if (HasLoop(S))
250/// Add true-dep: D -> U
251///
252/// for every def Dnext in DefSetAfter
253/// // NOTE: Dnext comes after D in execution order
254/// if (Dnext & D)
255/// Add output-dep: D -> Dnext
256///
257/// for every use Unext in UseSetAfter
258/// // NOTE: Unext comes after D in execution order
259/// if (Unext & D)
260/// Add true-dep: D -> Unext
261///
262/// for every use U in UseSetCurrent
263/// for every def Dnext in DefSetAfter
264/// // NOTE: Dnext comes after U in execution order
265/// if (Dnext & D)
266/// Add anti-dep: U -> Dnext
267///
268/// Add ModRefCurrent to ModRefAfter: { (I, ModRef[I] ) }
269/// Add DefSetCurrent to DefSetAfter: { I : Mod[I] != NULL }
270/// Add UseSetCurrent to UseSetAfter: { I : Ref[I] != NULL }
271/// }
272///
273///
Chris Lattnerfe8d8802003-08-31 19:46:48 +0000274void MemoryDepAnalysis::ProcessSCC(std::vector<BasicBlock*> &S,
275 ModRefTable& ModRefAfter, bool hasLoop) {
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000276 ModRefTable ModRefCurrent;
277 ModRefTable::ModRefMap& mapCurrent = ModRefCurrent.modRefMap;
278 ModRefTable::ModRefMap& mapAfter = ModRefAfter.modRefMap;
279
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000280 // Builder class fills out a ModRefTable one instruction at a time.
281 // To use it, we just invoke it's visit function for each basic block:
282 //
283 // for each basic block BB in the SCC in *postorder*
284 // for each instruction I in BB in *reverse*
285 // ModRefInfoBuilder::visit(I)
286 // : Add (I, ModRef[I]) to ModRefCurrent.modRefMap
287 // : Add I to ModRefCurrent.definers if it defines any node
288 // : Add I to ModRefCurrent.users if it uses any node
289 //
290 ModRefInfoBuilder builder(*funcGraph, *funcModRef, ModRefCurrent);
Chris Lattnerfe8d8802003-08-31 19:46:48 +0000291 for (std::vector<BasicBlock*>::iterator BI = S.begin(), BE = S.end();
292 BI != BE; ++BI)
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000293 // Note: BBs in the SCC<> created by TarjanSCCIterator are in postorder.
294 for (BasicBlock::reverse_iterator II=(*BI)->rbegin(), IE=(*BI)->rend();
295 II != IE; ++II)
296 builder.visit(*II);
297
298 /// for every def D in DefSetCurrent
299 ///
300 for (ModRefTable::ref_iterator II=ModRefCurrent.defsBegin(),
301 IE=ModRefCurrent.defsEnd(); II != IE; ++II)
302 {
303 /// // NOTE: D comes after itself iff S contains a loop
304 /// if (HasLoop(S))
305 /// Add output-dep: D -> D2
306 if (hasLoop)
307 funcDepGraph->AddSimpleDependence(**II, **II, OutputDependence);
308
309 /// for every def D2 *after* D in DefSetCurrent
310 /// // NOTE: D2 comes before D in execution order
311 /// if (D2 & D)
312 /// Add output-dep: D2 -> D
313 /// if (HasLoop(S))
314 /// Add output-dep: D -> D2
315 for (ModRefTable::ref_iterator JI=II+1; JI != IE; ++JI)
316 if (!Disjoint(mapCurrent.find(*II)->second.getModSet(),
317 mapCurrent.find(*JI)->second.getModSet()))
318 {
319 funcDepGraph->AddSimpleDependence(**JI, **II, OutputDependence);
320 if (hasLoop)
321 funcDepGraph->AddSimpleDependence(**II, **JI, OutputDependence);
322 }
323
324 /// for every use U in UseSetCurrent that was seen *before* D
325 /// // NOTE: U comes after D in execution order
326 /// if (U & D)
327 /// if (U != D || HasLoop(S))
328 /// Add true-dep: U -> D
329 /// if (HasLoop(S))
330 /// Add anti-dep: D -> U
331 ModRefTable::ref_iterator JI=ModRefCurrent.usersBegin();
332 ModRefTable::ref_iterator JE = ModRefCurrent.usersBeforeDef_End(II);
333 for ( ; JI != JE; ++JI)
334 if (!Disjoint(mapCurrent.find(*II)->second.getModSet(),
335 mapCurrent.find(*JI)->second.getRefSet()))
336 {
337 if (*II != *JI || hasLoop)
338 funcDepGraph->AddSimpleDependence(**II, **JI, TrueDependence);
339 if (hasLoop)
340 funcDepGraph->AddSimpleDependence(**JI, **II, AntiDependence);
341 }
342
343 /// for every use U in UseSetCurrent that was seen *after* D
344 /// // NOTE: U comes before D in execution order
345 /// if (U & D)
346 /// if (U != D || HasLoop(S))
347 /// Add anti-dep: U -> D
348 /// if (HasLoop(S))
349 /// Add true-dep: D -> U
350 for (/*continue JI*/ JE = ModRefCurrent.usersEnd(); JI != JE; ++JI)
351 if (!Disjoint(mapCurrent.find(*II)->second.getModSet(),
352 mapCurrent.find(*JI)->second.getRefSet()))
353 {
354 if (*II != *JI || hasLoop)
355 funcDepGraph->AddSimpleDependence(**JI, **II, AntiDependence);
356 if (hasLoop)
357 funcDepGraph->AddSimpleDependence(**II, **JI, TrueDependence);
358 }
359
360 /// for every def Dnext in DefSetPrev
361 /// // NOTE: Dnext comes after D in execution order
362 /// if (Dnext & D)
363 /// Add output-dep: D -> Dnext
364 for (ModRefTable::ref_iterator JI=ModRefAfter.defsBegin(),
365 JE=ModRefAfter.defsEnd(); JI != JE; ++JI)
366 if (!Disjoint(mapCurrent.find(*II)->second.getModSet(),
367 mapAfter.find(*JI)->second.getModSet()))
368 funcDepGraph->AddSimpleDependence(**II, **JI, OutputDependence);
369
370 /// for every use Unext in UseSetAfter
371 /// // NOTE: Unext comes after D in execution order
372 /// if (Unext & D)
373 /// Add true-dep: D -> Unext
374 for (ModRefTable::ref_iterator JI=ModRefAfter.usersBegin(),
375 JE=ModRefAfter.usersEnd(); JI != JE; ++JI)
376 if (!Disjoint(mapCurrent.find(*II)->second.getModSet(),
377 mapAfter.find(*JI)->second.getRefSet()))
378 funcDepGraph->AddSimpleDependence(**II, **JI, TrueDependence);
379 }
380
381 ///
382 /// for every use U in UseSetCurrent
383 /// for every def Dnext in DefSetAfter
384 /// // NOTE: Dnext comes after U in execution order
385 /// if (Dnext & D)
386 /// Add anti-dep: U -> Dnext
387 for (ModRefTable::ref_iterator II=ModRefCurrent.usersBegin(),
388 IE=ModRefCurrent.usersEnd(); II != IE; ++II)
389 for (ModRefTable::ref_iterator JI=ModRefAfter.defsBegin(),
390 JE=ModRefAfter.defsEnd(); JI != JE; ++JI)
391 if (!Disjoint(mapCurrent.find(*II)->second.getRefSet(),
392 mapAfter.find(*JI)->second.getModSet()))
393 funcDepGraph->AddSimpleDependence(**II, **JI, AntiDependence);
394
395 /// Add ModRefCurrent to ModRefAfter: { (I, ModRef[I] ) }
396 /// Add DefSetCurrent to DefSetAfter: { I : Mod[I] != NULL }
397 /// Add UseSetCurrent to UseSetAfter: { I : Ref[I] != NULL }
398 ModRefAfter.Insert(ModRefCurrent);
399}
400
401
402/// Debugging support methods
403///
404void MemoryDepAnalysis::print(std::ostream &O) const
405{
406 // TEMPORARY LOOP
407 for (hash_map<Function*, DependenceGraph*>::const_iterator
408 I = funcMap.begin(), E = funcMap.end(); I != E; ++I)
409 {
410 Function* func = I->first;
411 DependenceGraph* depGraph = I->second;
412
413 O << "\n================================================================\n";
414 O << "DEPENDENCE GRAPH FOR MEMORY OPERATIONS IN FUNCTION " << func->getName();
415 O << "\n================================================================\n\n";
416 depGraph->print(*func, O);
417
418 }
419}
420
421
422///
423/// Run the pass on a function
424///
Chris Lattner0c0023b2003-08-31 19:29:52 +0000425bool MemoryDepAnalysis::runOnFunction(Function &F) {
426 assert(!F.isExternal());
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000427
428 // Get the FunctionModRefInfo holding IPModRef results for this function.
429 // Use the TD graph recorded within the FunctionModRefInfo object, which
430 // may not be the same as the original TD graph computed by DS analysis.
431 //
Chris Lattner0c0023b2003-08-31 19:29:52 +0000432 funcModRef = &getAnalysis<IPModRef>().getFunctionModRefInfo(F);
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000433 funcGraph = &funcModRef->getFuncGraph();
434
435 // TEMPORARY: ptr to depGraph (later just becomes "this").
Chris Lattner0c0023b2003-08-31 19:29:52 +0000436 assert(!funcMap.count(&F) && "Analyzing function twice?");
437 funcDepGraph = funcMap[&F] = new DependenceGraph();
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000438
439 ModRefTable ModRefAfter;
440
441 SCC<Function*>* nextSCC;
Chris Lattner0c0023b2003-08-31 19:29:52 +0000442 for (TarjanSCC_iterator<Function*> I = tarj_begin(&F), E = tarj_end(&F);
443 I != E; ++I)
Chris Lattnerfe8d8802003-08-31 19:46:48 +0000444 ProcessSCC(*I, ModRefAfter, (*I).HasLoop());
Vikram S. Adve96b21c12002-12-08 13:26:29 +0000445
446 return true;
447}
448
449
450//-------------------------------------------------------------------------
451// TEMPORARY FUNCTIONS TO MAKE THIS A MODULE PASS ---
452// These functions will go away once this class becomes a FunctionPass.
453//
454
455// Driver function to compute dependence graphs for every function.
456// This is temporary and will go away once this is a FunctionPass.
457//
458bool MemoryDepAnalysis::run(Module& M)
459{
460 for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
461 if (! FI->isExternal())
462 runOnFunction(*FI); // automatically inserts each depGraph into funcMap
463 return true;
464}
465
466// Release all the dependence graphs in the map.
467void MemoryDepAnalysis::releaseMemory()
468{
469 for (hash_map<Function*, DependenceGraph*>::const_iterator
470 I = funcMap.begin(), E = funcMap.end(); I != E; ++I)
471 delete I->second;
472 funcMap.clear();
473
474 // Clear pointers because the pass constructor will not be invoked again.
475 funcDepGraph = NULL;
476 funcGraph = NULL;
477 funcModRef = NULL;
478}
479
480MemoryDepAnalysis::~MemoryDepAnalysis()
481{
482 releaseMemory();
483}
484
485//----END TEMPORARY FUNCTIONS----------------------------------------------
486
487
488void MemoryDepAnalysis::dump() const
489{
490 this->print(std::cerr);
491}
492
493static RegisterAnalysis<MemoryDepAnalysis>
494Z("memdep", "Memory Dependence Analysis");
495