llvm.org GIT mirror llvm / d81ccc2
Implement offline variable substitution in order to reduce memory and time usage. Fixup operator == to make this work, and add a resize method to DenseMap so we can resize our hashtable once we know how big it should be. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42269 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Berlin 12 years ago
3 changed file(s) with 962 addition(s) and 106 deletion(s). Raw diff Collapse all Expand all
9898
9999 bool empty() const { return NumEntries == 0; }
100100 unsigned size() const { return NumEntries; }
101
102 /// Grow the densemap so that it has at least Size buckets. Does not shrink
103 void resize(size_t Size) { grow(Size); }
101104
102105 void clear() {
103106 // If the capacity of the array is huge, and the # elements used is small,
227230 // causing infinite loops in lookup.
228231 if (NumEntries*4 >= NumBuckets*3 ||
229232 NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) {
230 this->grow();
233 this->grow(NumBuckets * 2);
231234 LookupBucketFor(Key, TheBucket);
232235 }
233236 ++NumEntries;
309312 new (&Buckets[i].first) KeyT(EmptyKey);
310313 }
311314
312 void grow() {
315 void grow(unsigned AtLeast) {
313316 unsigned OldNumBuckets = NumBuckets;
314317 BucketT *OldBuckets = Buckets;
315318
316319 // Double the number of buckets.
317 NumBuckets <<= 1;
320 while (NumBuckets <= AtLeast)
321 NumBuckets <<= 1;
318322 NumTombstones = 0;
319323 Buckets = reinterpret_cast(new char[sizeof(BucketT)*NumBuckets]);
320324
7474 }
7575
7676 friend struct ilist_traits >;
77
7877 public:
7978 explicit SparseBitVectorElement(unsigned Idx) {
8079 ElementIndex = Idx;
285284 allzero = false;
286285 }
287286 BecameZero = allzero;
287 }
288 // Get a hash value for this element;
289 uint64_t getHashValue() const {
290 uint64_t HashVal = 0;
291 for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
292 HashVal ^= Bits[i];
293 }
294 return HashVal;
288295 }
289296 };
290297
543550 return false;
544551 }
545552
546 bool operator!=(const SparseBitVector &RHS) {
553 bool operator!=(const SparseBitVector &RHS) const {
547554 return !(*this == RHS);
548555 }
549556
550 bool operator==(const SparseBitVector &RHS) {
557 bool operator==(const SparseBitVector &RHS) const {
551558 ElementListConstIter Iter1 = Elements.begin();
552559 ElementListConstIter Iter2 = RHS.Elements.begin();
553560
554 while (Iter2 != RHS.Elements.end()) {
555 if (Iter1->index() != Iter2->index()
556 || *Iter1 != *Iter2)
561 for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end();
562 ++Iter1, ++Iter2) {
563 if (*Iter1 != *Iter2)
557564 return false;
558 ++Iter1;
559 ++Iter2;
560 }
561 return Iter1 == Elements.end();
565 }
566 return Iter1 == Elements.end() && Iter2 == RHS.Elements.end();
562567 }
563568
564569 // Union our bitmap with the RHS and return true if we changed.
788793 return iterator(this, ~0);
789794 }
790795
796 // Get a hash value for this bitmap.
797 uint64_t getHashValue() const {
798 uint64_t HashVal = 0;
799 for (ElementListConstIter Iter = Elements.begin();
800 Iter != Elements.end();
801 ++Iter) {
802 HashVal ^= Iter->index();
803 HashVal ^= Iter->getHashValue();
804 }
805 return HashVal;
806 }
791807 };
792808
793809 // Convenience functions to allow Or and And without dereferencing in the user
827843 for (bi = LHS.begin(); bi != LHS.end(); ++bi) {
828844 out << *bi << " ";
829845 }
830 out << "\n";
846 out << " ]\n";
831847 }
832
833848 }
834849
850
851
835852 #endif
1515 // This algorithm is implemented as three stages:
1616 // 1. Object identification.
1717 // 2. Inclusion constraint identification.
18 // 3. Inclusion constraint solving.
18 // 3. Offline constraint graph optimization
19 // 4. Inclusion constraint solving.
1920 //
2021 // The object identification stage identifies all of the memory objects in the
2122 // program, which includes globals, heap allocated objects, and stack allocated
2829 // B can point to. Constraints can handle copies, loads, and stores, and
2930 // address taking.
3031 //
32 // The Offline constraint graph optimization portion includes offline variable
33 // substitution algorithms intended to pointer and location equivalences.
34 // Pointer equivalences are those pointers that will have the same points-to
35 // sets, and location equivalences are those variables that always appear
36 // together in points-to sets.
37 //
3138 // The inclusion constraint solving phase iteratively propagates the inclusion
3239 // constraints until a fixed point is reached. This is an O(N^3) algorithm.
3340 //
3441 // Function constraints are handled as if they were structs with X fields.
3542 // Thus, an access to argument X of function Y is an access to node index
3643 // getNode(Y) + X. This representation allows handling of indirect calls
37 // without any issues. To wit, an indirect call Y(a,b) is equivalence to
44 // without any issues. To wit, an indirect call Y(a,b) is equivalent to
3845 // *(Y + 1) = a, *(Y + 2) = b.
3946 // The return node for a function is always located at getNode(F) +
4047 // CallReturnPos. The arguments start at getNode(F) + CallArgPos.
4148 //
4249 // Future Improvements:
43 // Offline variable substitution, offline detection of online
44 // cycles. Use of BDD's.
50 // Offline detection of online cycles. Use of BDD's.
4551 //===----------------------------------------------------------------------===//
4652
4753 #define DEBUG_TYPE "anders-aa"
5864 #include "llvm/Support/Debug.h"
5965 #include "llvm/ADT/Statistic.h"
6066 #include "llvm/ADT/SparseBitVector.h"
67 #include "llvm/ADT/DenseMap.h"
6168 #include
6269 #include
6370 #include
6572 #include
6673
6774 using namespace llvm;
68 STATISTIC(NumIters , "Number of iterations to reach convergence");
69 STATISTIC(NumConstraints , "Number of constraints");
70 STATISTIC(NumNodes , "Number of nodes");
71 STATISTIC(NumUnified , "Number of variables unified");
75 STATISTIC(NumIters , "Number of iterations to reach convergence");
76 STATISTIC(NumConstraints, "Number of constraints");
77 STATISTIC(NumNodes , "Number of nodes");
78 STATISTIC(NumUnified , "Number of variables unified");
7279
7380 namespace {
7481 const unsigned SelfRep = (unsigned)-1;
7582 const unsigned Unvisited = (unsigned)-1;
7683 // Position of the function return node relative to the function node.
77 const unsigned CallReturnPos = 2;
84 const unsigned CallReturnPos = 1;
7885 // Position of the function call node relative to the function node.
79 const unsigned CallFirstArgPos = 3;
86 const unsigned CallFirstArgPos = 2;
87
88 struct BitmapKeyInfo {
89 static inline SparseBitVector<> *getEmptyKey() {
90 return reinterpret_cast *>(-1);
91 }
92 static inline SparseBitVector<> *getTombstoneKey() {
93 return reinterpret_cast *>(-2);
94 }
95 static unsigned getHashValue(const SparseBitVector<> *bitmap) {
96 return bitmap->getHashValue();
97 }
98 static bool isEqual(const SparseBitVector<> *LHS,
99 const SparseBitVector<> *RHS) {
100 if (LHS == RHS)
101 return true;
102 else if (LHS == getEmptyKey() || RHS == getEmptyKey()
103 || LHS == getTombstoneKey() || RHS == getTombstoneKey())
104 return false;
105
106 return *LHS == *RHS;
107 }
108
109 static bool isPod() { return true; }
110 };
80111
81112 class VISIBILITY_HIDDEN Andersens : public ModulePass, public AliasAnalysis,
82113 private InstVisitor {
88119 /// 'store' for statements like "*A = B", and AddressOf for statements like
89120 /// A = alloca; The Offset is applied as *(A + K) = B for stores,
90121 /// A = *(B + K) for loads, and A = B + K for copies. It is
91 /// illegal on addressof constraints (Because it is statically
122 /// illegal on addressof constraints (because it is statically
92123 /// resolvable to A = &C where C = B + K)
93124
94125 struct Constraint {
104135 }
105136 };
106137
107 // Node class - This class is used to represent a node
108 // in the constraint graph. Due to various optimizations,
109 // not always the case that there is a mapping from a Node to a
110 // Value. In particular, we add artificial
111 // Node's that represent the set of pointed-to variables
112 // shared for each location equivalent Node.
138 // Node class - This class is used to represent a node in the constraint
139 // graph. Due to various optimizations, not always the case that there is a
140 // mapping from a Node to a Value. In particular, we add artificial Node's
141 // that represent the set of pointed-to variables shared for each location
142 // equivalent Node.
113143 struct Node {
114 Value *Val;
144 Value *Val;
115145 SparseBitVector<> *Edges;
116146 SparseBitVector<> *PointsTo;
117147 SparseBitVector<> *OldPointsTo;
118148 bool Changed;
119149 std::list Constraints;
120150
121 // Nodes in cycles (or in equivalence classes) are united
122 // together using a standard union-find representation with path
123 // compression. NodeRep gives the index into GraphNodes
124 // representative for this one.
125 unsigned NodeRep; public:
126
127 Node() : Val(0), Edges(0), PointsTo(0), OldPointsTo(0), Changed(false),
128 NodeRep(SelfRep) {
129 }
151 // Pointer and location equivalence labels
152 unsigned PointerEquivLabel;
153 unsigned LocationEquivLabel;
154 // Predecessor edges, both real and implicit
155 SparseBitVector<> *PredEdges;
156 SparseBitVector<> *ImplicitPredEdges;
157 // Set of nodes that point to us, only use for location equivalence.
158 SparseBitVector<> *PointedToBy;
159 // Number of incoming edges, used during variable substitution to early
160 // free the points-to sets
161 unsigned NumInEdges;
162 // True if our ponits-to set is in the Set2PEClass map
163 bool StoredInHash;
164 // True if our node has no indirect constraints (Complex or otherwise)
165 bool Direct;
166 // True if the node is address taken, *or* it is part of a group of nodes
167 // that must be kept together. This is set to true for functions and
168 // their arg nodes, which must be kept at the same position relative to
169 // their base function node.
170 // kept at the same position relative to their base function node.
171 bool AddressTaken;
172
173 // Nodes in cycles (or in equivalence classes) are united together using a
174 // standard union-find representation with path compression. NodeRep
175 // gives the index into GraphNodes for the representative Node.
176 unsigned NodeRep;
177 public:
178
179 Node(bool direct = true) :
180 Val(0), Edges(0), PointsTo(0), OldPointsTo(0), Changed(false),
181 PointerEquivLabel(0), LocationEquivLabel(0), PredEdges(0),
182 ImplicitPredEdges(0), PointedToBy(0), NumInEdges(0),
183 StoredInHash(false), Direct(direct), AddressTaken(false),
184 NodeRep(SelfRep) { }
130185
131186 Node *setValue(Value *V) {
132187 assert(Val == 0 && "Value already set for this node!");
162217
163218 /// ValueNodes - This map indicates the Node that a particular Value* is
164219 /// represented by. This contains entries for all pointers.
165 std::map ValueNodes;
220 DenseMap ValueNodes;
166221
167222 /// ObjectNodes - This map contains entries for each memory object in the
168223 /// program: globals, alloca's and mallocs.
169 std::map ObjectNodes;
224 DenseMap ObjectNodes;
170225
171226 /// ReturnNodes - This map contains an entry for each function in the
172227 /// program that returns a value.
173 std::map ReturnNodes;
228 DenseMap ReturnNodes;
174229
175230 /// VarargNodes - This map contains the entry used to represent all pointers
176231 /// passed through the varargs portion of a function call for a particular
177232 /// function. An entry is not present in this map for functions that do not
178233 /// take variable arguments.
179 std::map VarargNodes;
234 DenseMap VarargNodes;
180235
181236
182237 /// Constraints - This vector contains a list of all of the constraints
183238 /// identified by the program.
184239 std::vector Constraints;
185240
186 // Map from graph node to maximum K value that is allowed (For functions,
241 // Map from graph node to maximum K value that is allowed (for functions,
187242 // this is equivalent to the number of arguments + CallFirstArgPos)
188243 std::map MaxK;
189244
192247 enum {
193248 UniversalSet = 0,
194249 NullPtr = 1,
195 NullObject = 2
250 NullObject = 2,
251 NumberSpecialNodes
196252 };
197 // Stack for Tarjans
253 // Stack for Tarjan's
198254 std::stack SCCStack;
199255 // Topological Index -> Graph node
200256 std::vector Topo2Node;
208264 unsigned DFSNumber;
209265 unsigned RPONumber;
210266
267 // Offline variable substitution related things
268
269 // Temporary rep storage, used because we can't collapse SCC's in the
270 // predecessor graph by uniting the variables permanently, we can only do so
271 // for the successor graph.
272 std::vector VSSCCRep;
273 // Mapping from node to whether we have visited it during SCC finding yet.
274 std::vector Node2Visited;
275 // During variable substitution, we create unknowns to represent the unknown
276 // value that is a dereference of a variable. These nodes are known as
277 // "ref" nodes (since they represent the value of dereferences).
278 unsigned FirstRefNode;
279 // During HVN, we create represent address taken nodes as if they were
280 // unknown (since HVN, unlike HU, does not evaluate unions).
281 unsigned FirstAdrNode;
282 // Current pointer equivalence class number
283 unsigned PEClass;
284 // Mapping from points-to sets to equivalence classes
285 typedef DenseMap *, unsigned, BitmapKeyInfo> BitVectorMap;
286 BitVectorMap Set2PEClass;
287 // Mapping from pointer equivalences to the representative node. -1 if we
288 // have no representative node for this pointer equivalence class yet.
289 std::vector PEClass2Node;
290 // Mapping from pointer equivalences to representative node. This includes
291 // pointer equivalent but not location equivalent variables. -1 if we have
292 // no representative node for this pointer equivalence class yet.
293 std::vector PENLEClass2Node;
294
211295 public:
212296 static char ID;
213297 Andersens() : ModulePass((intptr_t)&ID) {}
216300 InitializeAliasAnalysis(this);
217301 IdentifyObjects(M);
218302 CollectConstraints(M);
303 #undef DEBUG_TYPE
304 #define DEBUG_TYPE "anders-aa-constraints"
219305 DEBUG(PrintConstraints());
306 #undef DEBUG_TYPE
307 #define DEBUG_TYPE "anders-aa"
220308 SolveConstraints();
221309 DEBUG(PrintPointsToGraph());
222310
274362 if (!isa(C))
275363 return getNodeForConstantPointer(C);
276364
277 std::map::iterator I = ValueNodes.find(V);
365 DenseMap::iterator I = ValueNodes.find(V);
278366 if (I == ValueNodes.end()) {
279367 #ifndef NDEBUG
280368 V->dump();
287375 /// getObject - Return the node corresponding to the memory object for the
288376 /// specified global or allocation instruction.
289377 unsigned getObject(Value *V) {
290 std::map::iterator I = ObjectNodes.find(V);
378 DenseMap::iterator I = ObjectNodes.find(V);
291379 assert(I != ObjectNodes.end() &&
292380 "Value does not have an object in the points-to graph!");
293381 return I->second;
296384 /// getReturnNode - Return the node representing the return value for the
297385 /// specified function.
298386 unsigned getReturnNode(Function *F) {
299 std::map::iterator I = ReturnNodes.find(F);
387 DenseMap::iterator I = ReturnNodes.find(F);
300388 assert(I != ReturnNodes.end() && "Function does not return a value!");
301389 return I->second;
302390 }
304392 /// getVarargNode - Return the node representing the variable arguments
305393 /// formal for the specified function.
306394 unsigned getVarargNode(Function *F) {
307 std::map::iterator I = VarargNodes.find(F);
395 DenseMap::iterator I = VarargNodes.find(F);
308396 assert(I != VarargNodes.end() && "Function does not take var args!");
309397 return I->second;
310398 }
324412 void CollectConstraints(Module &M);
325413 bool AnalyzeUsesOfFunction(Value *);
326414 void CreateConstraintGraph();
415 void OptimizeConstraints();
416 unsigned FindEquivalentNode(unsigned, unsigned);
417 void ClumpAddressTaken();
418 void RewriteConstraints();
419 void HU();
420 void HVN();
421 void UnitePointerEquivalences();
327422 void SolveConstraints();
328423 void QueryNode(unsigned Node);
329
424 void Condense(unsigned Node);
425 void HUValNum(unsigned Node);
426 void HVNValNum(unsigned Node);
330427 unsigned getNodeForConstantPointer(Constant *C);
331428 unsigned getNodeForConstantPointerTarget(Constant *C);
332429 void AddGlobalInitializerConstraints(unsigned, Constant *C);
338435
339436 void PrintNode(Node *N);
340437 void PrintConstraints();
438 void PrintConstraint(const Constraint &);
439 void PrintLabels();
341440 void PrintPointsToGraph();
342441
343442 //===------------------------------------------------------------------===//
505604 // The function itself is a memory object.
506605 unsigned First = NumObjects;
507606 ValueNodes[F] = NumObjects++;
508 ObjectNodes[F] = NumObjects++;
509607 if (isa(F->getFunctionType()->getReturnType()))
510608 ReturnNodes[F] = NumObjects++;
511609 if (F->getFunctionType()->isVarArg())
515613 // Add nodes for all of the incoming pointer arguments.
516614 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
517615 I != E; ++I)
518 if (isa(I->getType()))
519 ValueNodes[I] = NumObjects++;
616 {
617 if (isa(I->getType()))
618 ValueNodes[I] = NumObjects++;
619 }
520620 MaxK[First] = NumObjects - First;
521 MaxK[First + 1] = NumObjects - First - 1;
522621
523622 // Scan the function body, creating a memory object for each heap/stack
524623 // allocation in the body of the function and a node to represent all
795894 }
796895
797896 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
798 // Make the function address point to the function object.
799 unsigned ObjectIndex = getObject(F);
800 GraphNodes[ObjectIndex].setValue(F);
801 Constraints.push_back(Constraint(Constraint::AddressOf, getNodeValue(*F),
802 ObjectIndex));
803897 // Set up the return value node.
804898 if (isa(F->getFunctionType()->getReturnType()))
805899 GraphNodes[getReturnNode(F)].setValue(F);
10901184 return Result;
10911185 }
10921186
1093 // Create the constraint graph used for solving points-to analysis.
1094 //
1187 void dumpToDOUT(SparseBitVector<> *bitmap) {
1188 dump(*bitmap, DOUT);
1189 }
1190
1191
1192 /// Clump together address taken variables so that the points-to sets use up
1193 /// less space and can be operated on faster.
1194
1195 void Andersens::ClumpAddressTaken() {
1196 #undef DEBUG_TYPE
1197 #define DEBUG_TYPE "anders-aa-renumber"
1198 std::vector Translate;
1199 std::vector NewGraphNodes;
1200
1201 Translate.resize(GraphNodes.size());
1202 unsigned NewPos = 0;
1203
1204 for (unsigned i = 0; i < Constraints.size(); ++i) {
1205 Constraint &C = Constraints[i];
1206 if (C.Type == Constraint::AddressOf) {
1207 GraphNodes[C.Src].AddressTaken = true;
1208 }
1209 }
1210 for (unsigned i = 0; i < NumberSpecialNodes; ++i) {
1211 unsigned Pos = NewPos++;
1212 Translate[i] = Pos;
1213 NewGraphNodes.push_back(GraphNodes[i]);
1214 DOUT << "Renumbering node " << i << " to node " << Pos << "\n";
1215 }
1216
1217 // I believe this ends up being faster than making two vectors and splicing
1218 // them.
1219 for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) {
1220 if (GraphNodes[i].AddressTaken) {
1221 unsigned Pos = NewPos++;
1222 Translate[i] = Pos;
1223 NewGraphNodes.push_back(GraphNodes[i]);
1224 DOUT << "Renumbering node " << i << " to node " << Pos << "\n";
1225 }
1226 }
1227
1228 for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) {
1229 if (!GraphNodes[i].AddressTaken) {
1230 unsigned Pos = NewPos++;
1231 Translate[i] = Pos;
1232 NewGraphNodes.push_back(GraphNodes[i]);
1233 DOUT << "Renumbering node " << i << " to node " << Pos << "\n";
1234 }
1235 }
1236
1237 for (DenseMap::iterator Iter = ValueNodes.begin();
1238 Iter != ValueNodes.end();
1239 ++Iter)
1240 Iter->second = Translate[Iter->second];
1241
1242 for (DenseMap::iterator Iter = ObjectNodes.begin();
1243 Iter != ObjectNodes.end();
1244 ++Iter)
1245 Iter->second = Translate[Iter->second];
1246
1247 for (DenseMap::iterator Iter = ReturnNodes.begin();
1248 Iter != ReturnNodes.end();
1249 ++Iter)
1250 Iter->second = Translate[Iter->second];
1251
1252 for (DenseMap::iterator Iter = VarargNodes.begin();
1253 Iter != VarargNodes.end();
1254 ++Iter)
1255 Iter->second = Translate[Iter->second];
1256
1257 for (unsigned i = 0; i < Constraints.size(); ++i) {
1258 Constraint &C = Constraints[i];
1259 C.Src = Translate[C.Src];
1260 C.Dest = Translate[C.Dest];
1261 }
1262
1263 GraphNodes.swap(NewGraphNodes);
1264 #undef DEBUG_TYPE
1265 #define DEBUG_TYPE "anders-aa"
1266 }
1267
1268 /// The technique used here is described in "Exploiting Pointer and Location
1269 /// Equivalence to Optimize Pointer Analysis. In the 14th International Static
1270 /// Analysis Symposium (SAS), August 2007." It is known as the "HVN" algorithm,
1271 /// and is equivalent to value numbering the collapsed constraint graph without
1272 /// evaluating unions. This is used as a pre-pass to HU in order to resolve
1273 /// first order pointer dereferences and speed up/reduce memory usage of HU.
1274 /// Running both is equivalent to HRU without the iteration
1275 /// HVN in more detail:
1276 /// Imagine the set of constraints was simply straight line code with no loops
1277 /// (we eliminate cycles, so there are no loops), such as:
1278 /// E = &D
1279 /// E = &C
1280 /// E = F
1281 /// F = G
1282 /// G = F
1283 /// Applying value numbering to this code tells us:
1284 /// G == F == E
1285 ///
1286 /// For HVN, this is as far as it goes. We assign new value numbers to every
1287 /// "address node", and every "reference node".
1288 /// To get the optimal result for this, we use a DFS + SCC (since all nodes in a
1289 /// cycle must have the same value number since the = operation is really
1290 /// inclusion, not overwrite), and value number nodes we receive points-to sets
1291 /// before we value our own node.
1292 /// The advantage of HU over HVN is that HU considers the inclusion property, so
1293 /// that if you have
1294 /// E = &D
1295 /// E = &C
1296 /// E = F
1297 /// F = G
1298 /// F = &D
1299 /// G = F
1300 /// HU will determine that G == F == E. HVN will not, because it cannot prove
1301 /// that the points to information ends up being the same because they all
1302 /// receive &D from E anyway.
1303
1304 void Andersens::HVN() {
1305 DOUT << "Beginning HVN\n";
1306 // Build a predecessor graph. This is like our constraint graph with the
1307 // edges going in the opposite direction, and there are edges for all the
1308 // constraints, instead of just copy constraints. We also build implicit
1309 // edges for constraints are implied but not explicit. I.E for the constraint
1310 // a = &b, we add implicit edges *a = b. This helps us capture more cycles
1311 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
1312 Constraint &C = Constraints[i];
1313 if (C.Type == Constraint::AddressOf) {
1314 GraphNodes[C.Src].AddressTaken = true;
1315 GraphNodes[C.Src].Direct = false;
1316
1317 // Dest = &src edge
1318 unsigned AdrNode = C.Src + FirstAdrNode;
1319 if (!GraphNodes[C.Dest].PredEdges)
1320 GraphNodes[C.Dest].PredEdges = new SparseBitVector<>;
1321 GraphNodes[C.Dest].PredEdges->set(AdrNode);
1322
1323 // *Dest = src edge
1324 unsigned RefNode = C.Dest + FirstRefNode;
1325 if (!GraphNodes[RefNode].ImplicitPredEdges)
1326 GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>;
1327 GraphNodes[RefNode].ImplicitPredEdges->set(C.Src);
1328 } else if (C.Type == Constraint::Load) {
1329 if (C.Offset == 0) {
1330 // dest = *src edge
1331 if (!GraphNodes[C.Dest].PredEdges)
1332 GraphNodes[C.Dest].PredEdges = new SparseBitVector<>;
1333 GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode);
1334 } else {
1335 GraphNodes[C.Dest].Direct = false;
1336 }
1337 } else if (C.Type == Constraint::Store) {
1338 if (C.Offset == 0) {
1339 // *dest = src edge
1340 unsigned RefNode = C.Dest + FirstRefNode;
1341 if (!GraphNodes[RefNode].PredEdges)
1342 GraphNodes[RefNode].PredEdges = new SparseBitVector<>;
1343 GraphNodes[RefNode].PredEdges->set(C.Src);
1344 }
1345 } else {
1346 // Dest = Src edge and *Dest = *Src edge
1347 if (!GraphNodes[C.Dest].PredEdges)
1348 GraphNodes[C.Dest].PredEdges = new SparseBitVector<>;
1349 GraphNodes[C.Dest].PredEdges->set(C.Src);
1350 unsigned RefNode = C.Dest + FirstRefNode;
1351 if (!GraphNodes[RefNode].ImplicitPredEdges)
1352 GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>;
1353 GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode);
1354 }
1355 }
1356 PEClass = 1;
1357 // Do SCC finding first to condense our predecessor graph
1358 DFSNumber = 0;
1359 Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0);
1360 Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false);
1361 Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false);
1362
1363 for (unsigned i = 0; i < FirstRefNode; ++i) {
1364 unsigned Node = VSSCCRep[i];
1365 if (!Node2Visited[Node])
1366 HVNValNum(Node);
1367 }
1368 for (BitVectorMap::iterator Iter = Set2PEClass.begin();
1369 Iter != Set2PEClass.end();
1370 ++Iter)
1371 delete Iter->first;
1372 Set2PEClass.clear();
1373 Node2DFS.clear();
1374 Node2Deleted.clear();
1375 Node2Visited.clear();
1376 DOUT << "Finished HVN\n";
1377
1378 }
1379
1380 /// This is the workhorse of HVN value numbering. We combine SCC finding at the
1381 /// same time because it's easy.
1382 void Andersens::HVNValNum(unsigned NodeIndex) {
1383 unsigned MyDFS = DFSNumber++;
1384 Node *N = &GraphNodes[NodeIndex];
1385 Node2Visited[NodeIndex] = true;
1386 Node2DFS[NodeIndex] = MyDFS;
1387
1388 // First process all our explicit edges
1389 if (N->PredEdges)
1390 for (SparseBitVector<>::iterator Iter = N->PredEdges->begin();
1391 Iter != N->PredEdges->end();
1392 ++Iter) {
1393 unsigned j = VSSCCRep[*Iter];
1394 if (!Node2Deleted[j]) {
1395 if (!Node2Visited[j])
1396 HVNValNum(j);
1397 if (Node2DFS[NodeIndex] > Node2DFS[j])
1398 Node2DFS[NodeIndex] = Node2DFS[j];
1399 }
1400 }
1401
1402 // Now process all the implicit edges
1403 if (N->ImplicitPredEdges)
1404 for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin();
1405 Iter != N->ImplicitPredEdges->end();
1406 ++Iter) {
1407 unsigned j = VSSCCRep[*Iter];
1408 if (!Node2Deleted[j]) {
1409 if (!Node2Visited[j])
1410 HVNValNum(j);
1411 if (Node2DFS[NodeIndex] > Node2DFS[j])
1412 Node2DFS[NodeIndex] = Node2DFS[j];
1413 }
1414 }
1415
1416 // See if we found any cycles
1417 if (MyDFS == Node2DFS[NodeIndex]) {
1418 while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) {
1419 unsigned CycleNodeIndex = SCCStack.top();
1420 Node *CycleNode = &GraphNodes[CycleNodeIndex];
1421 VSSCCRep[CycleNodeIndex] = NodeIndex;
1422 // Unify the nodes
1423 N->Direct &= CycleNode->Direct;
1424
1425 if (CycleNode->PredEdges) {
1426 if (!N->PredEdges)
1427 N->PredEdges = new SparseBitVector<>;
1428 *(N->PredEdges) |= CycleNode->PredEdges;
1429 delete CycleNode->PredEdges;
1430 CycleNode->PredEdges = NULL;
1431 }
1432 if (CycleNode->ImplicitPredEdges) {
1433 if (!N->ImplicitPredEdges)
1434 N->ImplicitPredEdges = new SparseBitVector<>;
1435 *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges;
1436 delete CycleNode->ImplicitPredEdges;
1437 CycleNode->ImplicitPredEdges = NULL;
1438 }
1439
1440 SCCStack.pop();
1441 }
1442
1443 Node2Deleted[NodeIndex] = true;
1444
1445 if (!N->Direct) {
1446 GraphNodes[NodeIndex].PointerEquivLabel = PEClass++;
1447 return;
1448 }
1449
1450 // Collect labels of successor nodes
1451 bool AllSame = true;
1452 unsigned First = ~0;
1453 SparseBitVector<> *Labels = new SparseBitVector<>;
1454 bool Used = false;
1455
1456 if (N->PredEdges)
1457 for (SparseBitVector<>::iterator Iter = N->PredEdges->begin();
1458 Iter != N->PredEdges->end();
1459 ++Iter) {
1460 unsigned j = VSSCCRep[*Iter];
1461 unsigned Label = GraphNodes[j].PointerEquivLabel;
1462 // Ignore labels that are equal to us or non-pointers
1463 if (j == NodeIndex || Label == 0)
1464 continue;
1465 if (First == (unsigned)~0)
1466 First = Label;
1467 else if (First != Label)
1468 AllSame = false;
1469 Labels->set(Label);
1470 }
1471
1472 // We either have a non-pointer, a copy of an existing node, or a new node.
1473 // Assign the appropriate pointer equivalence label.
1474 if (Labels->empty()) {
1475 GraphNodes[NodeIndex].PointerEquivLabel = 0;
1476 } else if (AllSame) {
1477 GraphNodes[NodeIndex].PointerEquivLabel = First;
1478 } else {
1479 GraphNodes[NodeIndex].PointerEquivLabel = Set2PEClass[Labels];
1480 if (GraphNodes[NodeIndex].PointerEquivLabel == 0) {
1481 unsigned EquivClass = PEClass++;
1482 Set2PEClass[Labels] = EquivClass;
1483 GraphNodes[NodeIndex].PointerEquivLabel = EquivClass;
1484 Used = true;
1485 }
1486 }
1487 if (!Used)
1488 delete Labels;
1489 } else {
1490 SCCStack.push(NodeIndex);
1491 }
1492 }
1493
1494 /// The technique used here is described in "Exploiting Pointer and Location
1495 /// Equivalence to Optimize Pointer Analysis. In the 14th International Static
1496 /// Analysis Symposium (SAS), August 2007." It is known as the "HU" algorithm,
1497 /// and is equivalent to value numbering the collapsed constraint graph
1498 /// including evaluating unions.
1499 void Andersens::HU() {
1500 DOUT << "Beginning HU\n";
1501 // Build a predecessor graph. This is like our constraint graph with the
1502 // edges going in the opposite direction, and there are edges for all the
1503 // constraints, instead of just copy constraints. We also build implicit
1504 // edges for constraints are implied but not explicit. I.E for the constraint
1505 // a = &b, we add implicit edges *a = b. This helps us capture more cycles
1506 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
1507 Constraint &C = Constraints[i];
1508 if (C.Type == Constraint::AddressOf) {
1509 GraphNodes[C.Src].AddressTaken = true;
1510 GraphNodes[C.Src].Direct = false;
1511
1512 GraphNodes[C.Dest].PointsTo->set(C.Src);
1513 // *Dest = src edge
1514 unsigned RefNode = C.Dest + FirstRefNode;
1515 if (!GraphNodes[RefNode].ImplicitPredEdges)
1516 GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>;
1517 GraphNodes[RefNode].ImplicitPredEdges->set(C.Src);
1518 GraphNodes[C.Src].PointedToBy->set(C.Dest);
1519 } else if (C.Type == Constraint::Load) {
1520 if (C.Offset == 0) {
1521 // dest = *src edge
1522 if (!GraphNodes[C.Dest].PredEdges)
1523 GraphNodes[C.Dest].PredEdges = new SparseBitVector<>;
1524 GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode);
1525 } else {
1526 GraphNodes[C.Dest].Direct = false;
1527 }
1528 } else if (C.Type == Constraint::Store) {
1529 if (C.Offset == 0) {
1530 // *dest = src edge
1531 unsigned RefNode = C.Dest + FirstRefNode;
1532 if (!GraphNodes[RefNode].PredEdges)
1533 GraphNodes[RefNode].PredEdges = new SparseBitVector<>;
1534 GraphNodes[RefNode].PredEdges->set(C.Src);
1535 }
1536 } else {
1537 // Dest = Src edge and *Dest = *Src edg
1538 if (!GraphNodes[C.Dest].PredEdges)
1539 GraphNodes[C.Dest].PredEdges = new SparseBitVector<>;
1540 GraphNodes[C.Dest].PredEdges->set(C.Src);
1541 unsigned RefNode = C.Dest + FirstRefNode;
1542 if (!GraphNodes[RefNode].ImplicitPredEdges)
1543 GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>;
1544 GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode);
1545 }
1546 }
1547 PEClass = 1;
1548 // Do SCC finding first to condense our predecessor graph
1549 DFSNumber = 0;
1550 Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0);
1551 Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false);
1552 Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false);
1553
1554 for (unsigned i = 0; i < FirstRefNode; ++i) {
1555 if (FindNode(i) == i) {
1556 unsigned Node = VSSCCRep[i];
1557 if (!Node2Visited[Node])
1558 Condense(Node);
1559 }
1560 }
1561
1562 // Reset tables for actual labeling
1563 Node2DFS.clear();
1564 Node2Visited.clear();
1565 Node2Deleted.clear();
1566 // Pre-grow our densemap so that we don't get really bad behavior
1567 Set2PEClass.resize(GraphNodes.size());
1568
1569 // Visit the condensed graph and generate pointer equivalence labels.
1570 Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false);
1571 for (unsigned i = 0; i < FirstRefNode; ++i) {
1572 if (FindNode(i) == i) {
1573 unsigned Node = VSSCCRep[i];
1574 if (!Node2Visited[Node])
1575 HUValNum(Node);
1576 }
1577 }
1578 // PEClass nodes will be deleted by the deleting of N->PointsTo in our caller.
1579 Set2PEClass.clear();
1580 DOUT << "Finished HU\n";
1581 }
1582
1583
1584 /// Implementation of standard Tarjan SCC algorithm as modified by Nuutilla.
1585 void Andersens::Condense(unsigned NodeIndex) {
1586 unsigned MyDFS = DFSNumber++;
1587 Node *N = &GraphNodes[NodeIndex];
1588 Node2Visited[NodeIndex] = true;
1589 Node2DFS[NodeIndex] = MyDFS;
1590
1591 // First process all our explicit edges
1592 if (N->PredEdges)
1593 for (SparseBitVector<>::iterator Iter = N->PredEdges->begin();
1594 Iter != N->PredEdges->end();
1595 ++Iter) {
1596 unsigned j = VSSCCRep[*Iter];
1597 if (!Node2Deleted[j]) {
1598 if (!Node2Visited[j])
1599 Condense(j);
1600 if (Node2DFS[NodeIndex] > Node2DFS[j])
1601 Node2DFS[NodeIndex] = Node2DFS[j];
1602 }
1603 }
1604
1605 // Now process all the implicit edges
1606 if (N->ImplicitPredEdges)
1607 for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin();
1608 Iter != N->ImplicitPredEdges->end();
1609 ++Iter) {
1610 unsigned j = VSSCCRep[*Iter];
1611 if (!Node2Deleted[j]) {
1612 if (!Node2Visited[j])
1613 Condense(j);
1614 if (Node2DFS[NodeIndex] > Node2DFS[j])
1615 Node2DFS[NodeIndex] = Node2DFS[j];
1616 }
1617 }
1618
1619 // See if we found any cycles
1620 if (MyDFS == Node2DFS[NodeIndex]) {
1621 while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) {
1622 unsigned CycleNodeIndex = SCCStack.top();
1623 Node *CycleNode = &GraphNodes[CycleNodeIndex];
1624 VSSCCRep[CycleNodeIndex] = NodeIndex;
1625 // Unify the nodes
1626 N->Direct &= CycleNode->Direct;
1627
1628 *(N->PointsTo) |= CycleNode->PointsTo;
1629 delete CycleNode->PointsTo;
1630 CycleNode->PointsTo = NULL;
1631 if (CycleNode->PredEdges) {
1632 if (!N->PredEdges)
1633 N->PredEdges = new SparseBitVector<>;
1634 *(N->PredEdges) |= CycleNode->PredEdges;
1635 delete CycleNode->PredEdges;
1636 CycleNode->PredEdges = NULL;
1637 }
1638 if (CycleNode->ImplicitPredEdges) {
1639 if (!N->ImplicitPredEdges)
1640 N->ImplicitPredEdges = new SparseBitVector<>;
1641 *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges;
1642 delete CycleNode->ImplicitPredEdges;
1643 CycleNode->ImplicitPredEdges = NULL;
1644 }
1645 SCCStack.pop();
1646 }
1647
1648 Node2Deleted[NodeIndex] = true;
1649
1650 // Set up number of incoming edges for other nodes
1651 if (N->PredEdges)
1652 for (SparseBitVector<>::iterator Iter = N->PredEdges->begin();
1653 Iter != N->PredEdges->end();
1654 ++Iter)
1655 ++GraphNodes[VSSCCRep[*Iter]].NumInEdges;
1656 } else {
1657 SCCStack.push(NodeIndex);
1658 }
1659 }
1660
1661 void Andersens::HUValNum(unsigned NodeIndex) {
1662 Node *N = &GraphNodes[NodeIndex];
1663 Node2Visited[NodeIndex] = true;
1664
1665 // Eliminate dereferences of non-pointers for those non-pointers we have
1666 // already identified. These are ref nodes whose non-ref node:
1667 // 1. Has already been visited determined to point to nothing (and thus, a
1668 // dereference of it must point to nothing)
1669 // 2. Any direct node with no predecessor edges in our graph and with no
1670 // points-to set (since it can't point to anything either, being that it
1671 // receives no points-to sets and has none).
1672 if (NodeIndex >= FirstRefNode) {
1673 unsigned j = VSSCCRep[FindNode(NodeIndex - FirstRefNode)];
1674 if ((Node2Visited[j] && !GraphNodes[j].PointerEquivLabel)
1675 || (GraphNodes[j].Direct && !GraphNodes[j].PredEdges
1676 && GraphNodes[j].PointsTo->empty())){
1677 return;
1678 }
1679 }
1680 // Process all our explicit edges
1681 if (N->PredEdges)
1682 for (SparseBitVector<>::iterator Iter = N->PredEdges->begin();
1683 Iter != N->PredEdges->end();
1684 ++Iter) {
1685 unsigned j = VSSCCRep[*Iter];
1686 if (!Node2Visited[j])
1687 HUValNum(j);
1688
1689 // If this edge turned out to be the same as us, or got no pointer
1690 // equivalence label (and thus points to nothing) , just decrement our
1691 // incoming edges and continue.
1692 if (j == NodeIndex || GraphNodes[j].PointerEquivLabel == 0) {
1693 --GraphNodes[j].NumInEdges;
1694 continue;
1695 }
1696
1697 *(N->PointsTo) |= GraphNodes[j].PointsTo;
1698
1699 // If we didn't end up storing this in the hash, and we're done with all
1700 // the edges, we don't need the points-to set anymore.
1701 --GraphNodes[j].NumInEdges;
1702 if (!GraphNodes[j].NumInEdges && !GraphNodes[j].StoredInHash) {
1703 delete GraphNodes[j].PointsTo;
1704 GraphNodes[j].PointsTo = NULL;
1705 }
1706 }
1707 // If this isn't a direct node, generate a fresh variable.
1708 if (!N->Direct) {
1709 N->PointsTo->set(FirstRefNode + NodeIndex);
1710 }
1711
1712 // See If we have something equivalent to us, if not, generate a new
1713 // equivalence class.
1714 if (N->PointsTo->empty()) {
1715 delete N->PointsTo;
1716 N->PointsTo = NULL;
1717 } else {
1718 if (N->Direct) {
1719 N->PointerEquivLabel = Set2PEClass[N->PointsTo];
1720 if (N->PointerEquivLabel == 0) {
1721 unsigned EquivClass = PEClass++;
1722 N->StoredInHash = true;
1723 Set2PEClass[N->PointsTo] = EquivClass;
1724 N->PointerEquivLabel = EquivClass;
1725 }
1726 } else {
1727 N->PointerEquivLabel = PEClass++;
1728 }
1729 }
1730 }
1731
1732 /// Rewrite our list of constraints so that pointer equivalent nodes are
1733 /// replaced by their the pointer equivalence class representative.
1734 void Andersens::RewriteConstraints() {
1735 std::vector NewConstraints;
1736
1737 PEClass2Node.clear();
1738 PENLEClass2Node.clear();
1739
1740 // We may have from 1 to Graphnodes + 1 equivalence classes.
1741 PEClass2Node.insert(PEClass2Node.begin(), GraphNodes.size() + 1, -1);
1742 PENLEClass2Node.insert(PENLEClass2Node.begin(), GraphNodes.size() + 1, -1);
1743
1744 // Rewrite constraints, ignoring non-pointer constraints, uniting equivalent
1745 // nodes, and rewriting constraints to use the representative nodes.
1746 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
1747 Constraint &C = Constraints[i];
1748 unsigned RHSNode = FindNode(C.Src);
1749 unsigned LHSNode = FindNode(C.Dest);
1750 unsigned RHSLabel = GraphNodes[VSSCCRep[RHSNode]].PointerEquivLabel;
1751 unsigned LHSLabel = GraphNodes[VSSCCRep[LHSNode]].PointerEquivLabel;
1752
1753 // First we try to eliminate constraints for things we can prove don't point
1754 // to anything.
1755 if (LHSLabel == 0) {
1756 DEBUG(PrintNode(&GraphNodes[LHSNode]));
1757 DOUT << " is a non-pointer, ignoring constraint.\n";
1758 continue;
1759 }
1760 if (RHSLabel == 0) {
1761 DEBUG(PrintNode(&GraphNodes[RHSNode]));
1762 DOUT << " is a non-pointer, ignoring constraint.\n";
1763 continue;
1764 }
1765 // This constraint may be useless, and it may become useless as we translate
1766 // it.
1767 if (C.Src == C.Dest && C.Type == Constraint::Copy)
1768 continue;
1769
1770 C.Src = FindEquivalentNode(RHSNode, RHSLabel);
1771 C.Dest = FindEquivalentNode(FindNode(LHSNode), LHSLabel);
1772 if (C.Src == C.Dest && C.Type == Constraint::Copy)
1773 continue;
1774
1775 NewConstraints.push_back(C);
1776 }
1777 Constraints.swap(NewConstraints);
1778 PEClass2Node.clear();
1779 }
1780
1781 /// See if we have a node that is pointer equivalent to the one being asked
1782 /// about, and if so, unite them and return the equivalent node. Otherwise,
1783 /// return the original node.
1784 unsigned Andersens::FindEquivalentNode(unsigned NodeIndex,
1785 unsigned NodeLabel) {
1786 if (!GraphNodes[NodeIndex].AddressTaken) {
1787 if (PEClass2Node[NodeLabel] != -1) {
1788 // We found an existing node with the same pointer label, so unify them.
1789 return UniteNodes(PEClass2Node[NodeLabel], NodeIndex);
1790 } else {
1791 PEClass2Node[NodeLabel] = NodeIndex;
1792 PENLEClass2Node[NodeLabel] = NodeIndex;
1793 }
1794 } else if (PENLEClass2Node[NodeLabel] == -1) {
1795 PENLEClass2Node[NodeLabel] = NodeIndex;
1796 }
1797
1798 return NodeIndex;
1799 }
1800
1801 void Andersens::PrintLabels() {
1802 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1803 if (i < FirstRefNode) {
1804 PrintNode(&GraphNodes[i]);
1805 } else if (i < FirstAdrNode) {
1806 DOUT << "REF(";
1807 PrintNode(&GraphNodes[i-FirstRefNode]);
1808 DOUT <<")";
1809 } else {
1810 DOUT << "ADR(";
1811 PrintNode(&GraphNodes[i-FirstAdrNode]);
1812 DOUT <<")";
1813 }
1814
1815 DOUT << " has pointer label " << GraphNodes[i].PointerEquivLabel
1816 << " and SCC rep " << VSSCCRep[i]
1817 << " and is " << (GraphNodes[i].Direct ? "Direct" : "Not direct")
1818 << "\n";
1819 }
1820 }
1821
1822 /// Optimize the constraints by performing offline variable substitution and
1823 /// other optimizations.
1824 void Andersens::OptimizeConstraints() {
1825 DOUT << "Beginning constraint optimization\n";
1826
1827 // Function related nodes need to stay in the same relative position and can't
1828 // be location equivalent.
1829 for (std::map::iterator Iter = MaxK.begin();
1830 Iter != MaxK.end();
1831 ++Iter) {
1832 for (unsigned i = Iter->first;
1833 i != Iter->first + Iter->second;
1834 ++i) {
1835 GraphNodes[i].AddressTaken = true;
1836 GraphNodes[i].Direct = false;
1837 }
1838 }
1839
1840 ClumpAddressTaken();
1841 FirstRefNode = GraphNodes.size();
1842 FirstAdrNode = FirstRefNode + GraphNodes.size();
1843 GraphNodes.insert(GraphNodes.end(), 2 * GraphNodes.size(),
1844 Node(false));
1845 VSSCCRep.resize(GraphNodes.size());
1846 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1847 VSSCCRep[i] = i;
1848 }
1849 HVN();
1850 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1851 Node *N = &GraphNodes[i];
1852 delete N->PredEdges;
1853 N->PredEdges = NULL;
1854 delete N->ImplicitPredEdges;
1855 N->ImplicitPredEdges = NULL;
1856 }
1857 #undef DEBUG_TYPE
1858 #define DEBUG_TYPE "anders-aa-labels"
1859 DEBUG(PrintLabels());
1860 #undef DEBUG_TYPE
1861 #define DEBUG_TYPE "anders-aa"
1862 RewriteConstraints();
1863 // Delete the adr nodes.
1864 GraphNodes.resize(FirstRefNode * 2);
1865
1866 // Now perform HU
1867 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1868 Node *N = &GraphNodes[i];
1869 if (FindNode(i) == i) {
1870 N->PointsTo = new SparseBitVector<>;
1871 N->PointedToBy = new SparseBitVector<>;
1872 // Reset our labels
1873 }
1874 VSSCCRep[i] = i;
1875 N->PointerEquivLabel = 0;
1876 }
1877 HU();
1878 #undef DEBUG_TYPE
1879 #define DEBUG_TYPE "anders-aa-labels"
1880 DEBUG(PrintLabels());
1881 #undef DEBUG_TYPE
1882 #define DEBUG_TYPE "anders-aa"
1883 RewriteConstraints();
1884 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1885 if (FindNode(i) == i) {
1886 Node *N = &GraphNodes[i];
1887 delete N->PointsTo;
1888 delete N->PredEdges;
1889 delete N->ImplicitPredEdges;
1890 delete N->PointedToBy;
1891 }
1892 }
1893 GraphNodes.erase(GraphNodes.begin() + FirstRefNode, GraphNodes.end());
1894 DOUT << "Finished constraint optimization\n";
1895 FirstRefNode = 0;
1896 FirstAdrNode = 0;
1897 }
1898
1899 /// Unite pointer but not location equivalent variables, now that the constraint
1900 /// graph is built.
1901 void Andersens::UnitePointerEquivalences() {
1902 DOUT << "Uniting remaining pointer equivalences\n";
1903 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
1904 if (GraphNodes[i].AddressTaken && GraphNodes[i].NodeRep == SelfRep) {
1905 unsigned Label = GraphNodes[i].PointerEquivLabel;
1906
1907 if (Label && PENLEClass2Node[Label] != -1)
1908 UniteNodes(i, PENLEClass2Node[Label]);
1909 }
1910 }
1911 DOUT << "Finished remaining pointer equivalences\n";
1912 PENLEClass2Node.clear();
1913 }
1914
1915 /// Create the constraint graph used for solving points-to analysis.
1916 ///
10951917 void Andersens::CreateConstraintGraph() {
10961918 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
10971919 Constraint &C = Constraints[i];
11802002 bool Changed = true;
11812003 unsigned Iteration = 0;
11822004
1183 // We create the bitmaps here to avoid getting jerked around by the compiler
1184 // creating objects behind our back and wasting lots of memory.
2005 OptimizeConstraints();
2006 #undef DEBUG_TYPE
2007 #define DEBUG_TYPE "anders-aa-constraints"
2008 DEBUG(PrintConstraints());
2009 #undef DEBUG_TYPE
2010 #define DEBUG_TYPE "anders-aa"
2011
11852012 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
11862013 Node *N = &GraphNodes[i];
11872014 N->PointsTo = new SparseBitVector<>;
11892016 N->Edges = new SparseBitVector<>;
11902017 }
11912018 CreateConstraintGraph();
1192
2019 UnitePointerEquivalences();
2020 assert(SCCStack.empty() && "SCC Stack should be empty by now!");
11932021 Topo2Node.insert(Topo2Node.begin(), GraphNodes.size(), Unvisited);
11942022 Node2Topo.insert(Node2Topo.begin(), GraphNodes.size(), Unvisited);
2023 Node2DFS.clear();
2024 Node2Deleted.clear();
11952025 Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0);
11962026 Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false);
11972027 DFSNumber = 0;
12132043 do {
12142044 Changed = false;
12152045 ++NumIters;
1216 DOUT << "Starting iteration #" << Iteration++;
2046 DOUT << "Starting iteration #" << Iteration++ << "\n";
12172047 // TODO: In the microoptimization category, we could just make Topo2Node
12182048 // a fast map and thus only contain the visited nodes.
12192049 for (unsigned i = 0; i < GraphNodes.size(); ++i) {
12472077 // TODO: We could delete redundant constraints here.
12482078 // Src and Dest will be the vars we are going to process.
12492079 // This may look a bit ugly, but what it does is allow us to process
1250 // both store and load constraints with the same function.
2080 // both store and load constraints with the same code.
12512081 // Load constraints say that every member of our RHS solution has K
12522082 // added to it, and that variable gets an edge to LHS. We also union
12532083 // RHS+K's solution into the LHS solution.
12812111 CurrMember = *bi;
12822112
12832113 // Need to increment the member by K since that is where we are
1284 // supposed to copy to/from
1285 // Node that in positive weight cycles, which occur in address taking
1286 // of fields, K can go past
1287 // MaxK[CurrMember] elements, even though that is all it could
1288 // point to.
2114 // supposed to copy to/from. Note that in positive weight cycles,
2115 // which occur in address taking of fields, K can go past
2116 // MaxK[CurrMember] elements, even though that is all it could point
2117 // to.
12892118 if (K > 0 && K > MaxK[CurrMember])
12902119 continue;
12912120 else
13922221
13932222 SecondNode->NodeRep = First;
13942223 FirstNode->Changed |= SecondNode->Changed;
1395 FirstNode->PointsTo |= *(SecondNode->PointsTo);
1396 FirstNode->Edges |= *(SecondNode->Edges);
1397 FirstNode->Constraints.splice(FirstNode->Constraints.begin(),
1398 SecondNode->Constraints);
1399 delete FirstNode->OldPointsTo;
1400 FirstNode->OldPointsTo = new SparseBitVector<>;
2224 if (FirstNode->PointsTo && SecondNode->PointsTo)
2225 FirstNode->PointsTo |= *(SecondNode->PointsTo);
2226 if (FirstNode->Edges && SecondNode->Edges)
2227 FirstNode->Edges |= *(SecondNode->Edges);
2228 if (!FirstNode->Constraints.empty() && !SecondNode->Constraints.empty())
2229 FirstNode->Constraints.splice(FirstNode->Constraints.begin(),
2230 SecondNode->Constraints);
2231 if (FirstNode->OldPointsTo) {
2232 delete FirstNode->OldPointsTo;
2233 FirstNode->OldPointsTo = new SparseBitVector<>;
2234 }
14012235
14022236 // Destroy interesting parts of the merged-from node.
14032237 delete SecondNode->OldPointsTo;
14782312 if (N == &GraphNodes[getObject(V)])
14792313 cerr << "";
14802314 }
2315 void Andersens::PrintConstraint(const Constraint &C) {
2316 if (C.Type == Constraint::Store) {
2317 cerr << "*";
2318 if (C.Offset != 0)
2319 cerr << "(";
2320 }
2321 PrintNode(&GraphNodes[C.Dest]);
2322 if (C.Type == Constraint::Store && C.Offset != 0)
2323 cerr << " + " << C.Offset << ")";
2324 cerr << " = ";
2325 if (C.Type == Constraint::Load) {
2326 cerr << "*";
2327 if (C.Offset != 0)
2328 cerr << "(";
2329 }
2330 else if (C.Type == Constraint::AddressOf)
2331 cerr << "&";
2332 PrintNode(&GraphNodes[C.Src]);
2333 if (C.Offset != 0 && C.Type != Constraint::Store)
2334 cerr << " + " << C.Offset;
2335 if (C.Type == Constraint::Load && C.Offset != 0)
2336 cerr << ")";
2337 cerr << "\n";
2338 }
14812339
14822340 void Andersens::PrintConstraints() {
14832341 cerr << "Constraints:\n";
14842342
1485 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
1486 const Constraint &C = Constraints[i];
1487 if (C.Type == Constraint::Store) {
1488 cerr << "*";
1489 if (C.Offset != 0)
1490 cerr << "(";
1491 }
1492 PrintNode(&GraphNodes[C.Dest]);
1493 if (C.Type == Constraint::Store && C.Offset != 0)
1494 cerr << " + " << C.Offset << ")";
1495 cerr << " = ";
1496 if (C.Type == Constraint::Load) {
1497 cerr << "*";
1498 if (C.Offset != 0)
1499 cerr << "(";
1500 }
1501 else if (C.Type == Constraint::AddressOf)
1502 cerr << "&";
1503 PrintNode(&GraphNodes[C.Src]);
1504 if (C.Offset != 0 && C.Type != Constraint::Store)
1505 cerr << " + " << C.Offset;
1506 if (C.Type == Constraint::Load && C.Offset != 0)
1507 cerr << ")";
1508 cerr << "\n";
1509 }
2343 for (unsigned i = 0, e = Constraints.size(); i != e; ++i)
2344 PrintConstraint(Constraints[i]);
15102345 }
15112346
15122347 void Andersens::PrintPointsToGraph() {