@@ -128,6 +128,74 @@ void ConstraintGraphNode::removeConstraint(Constraint *constraint) {
128
128
Constraints.pop_back ();
129
129
}
130
130
131
+ ConstraintGraphNode::Adjacency &
132
+ ConstraintGraphNode::getAdjacency (TypeVariableType *typeVar) {
133
+ assert (typeVar != TypeVar && " Cannot be adjacent to oneself" );
134
+
135
+ // Look for existing adjacency information.
136
+ auto pos = AdjacencyInfo.find (typeVar);
137
+
138
+ if (pos != AdjacencyInfo.end ())
139
+ return pos->second ;
140
+
141
+ // If we weren't already adjacent to this type variable, add it to the
142
+ // list of adjacencies.
143
+ pos = AdjacencyInfo.insert (
144
+ { typeVar, { static_cast <unsigned >(Adjacencies.size ()), 0 } })
145
+ .first ;
146
+ Adjacencies.push_back (typeVar);
147
+ return pos->second ;
148
+ }
149
+
150
+ void ConstraintGraphNode::modifyAdjacency (
151
+ TypeVariableType *typeVar,
152
+ llvm::function_ref<void (Adjacency& adj)> modify) {
153
+ // Find the adjacency information.
154
+ auto pos = AdjacencyInfo.find (typeVar);
155
+ assert (pos != AdjacencyInfo.end () && " Type variables not adjacent" );
156
+ assert (Adjacencies[pos->second .Index ] == typeVar && " Mismatched adjacency" );
157
+
158
+ // Perform the modification .
159
+ modify (pos->second );
160
+
161
+ // If the adjacency is not empty, leave the information in there.
162
+ if (!pos->second .empty ())
163
+ return ;
164
+
165
+ // Remove this adjacency from the mapping.
166
+ unsigned index = pos->second .Index ;
167
+ AdjacencyInfo.erase (pos);
168
+
169
+ // If this adjacency is last in the vector, just pop it off.
170
+ unsigned lastIndex = Adjacencies.size ()-1 ;
171
+ if (index == lastIndex) {
172
+ Adjacencies.pop_back ();
173
+ return ;
174
+ }
175
+
176
+ // This adjacency is somewhere in the middle; swap it with the last
177
+ // adjacency so we can remove the adjacency from the vector in O(1) time
178
+ // rather than O(n) time.
179
+ auto lastTypeVar = Adjacencies[lastIndex];
180
+ Adjacencies[index] = lastTypeVar;
181
+ AdjacencyInfo[lastTypeVar].Index = index;
182
+ Adjacencies.pop_back ();
183
+ }
184
+
185
+ void ConstraintGraphNode::addAdjacency (TypeVariableType *typeVar) {
186
+ auto &adjacency = getAdjacency (typeVar);
187
+
188
+ // Bump the degree of the adjacency.
189
+ ++adjacency.NumConstraints ;
190
+ }
191
+
192
+ void ConstraintGraphNode::removeAdjacency (TypeVariableType *typeVar) {
193
+ modifyAdjacency (typeVar, [](Adjacency &adj) {
194
+ assert (adj.NumConstraints > 0 && " No adjacency to remove?" );
195
+ --adj.NumConstraints ;
196
+ });
197
+ }
198
+
131
199
void ConstraintGraphNode::addToEquivalenceClass (
132
200
ArrayRef<TypeVariableType *> typeVars) {
133
201
assert (TypeVar == TypeVar->getImpl ().getRepresentative (nullptr ) &&
@@ -258,52 +326,80 @@ void ConstraintGraph::removeNode(TypeVariableType *typeVar) {
258
326
TypeVariables.pop_back ();
259
327
}
260
328
261
- void ConstraintGraph::addConstraint (Constraint *constraint) {
262
- // For the nodes corresponding to each type variable...
329
+ // / Enumerate the adjacency edges for the given constraint.
330
+ static void enumerateAdjacencies (
331
+ Constraint *constraint,
332
+ llvm::function_ref<void (TypeVariableType *, TypeVariableType *)> visitor) {
333
+ // Don't record adjacencies for one-way constraints.
334
+ if (constraint->isOneWayConstraint ())
335
+ return ;
336
+
337
+ // O(N^2) update for all of the adjacent type variables.
263
338
auto referencedTypeVars = constraint->getTypeVariables ();
264
339
for (auto typeVar : referencedTypeVars) {
265
- // Find the node for this type variable.
266
- auto &node = (*this )[typeVar];
340
+ for (auto otherTypeVar : referencedTypeVars) {
341
+ if (typeVar == otherTypeVar)
342
+ continue ;
343
+
344
+ visitor (typeVar, otherTypeVar);
345
+ }
346
+ }
347
+ }
267
348
268
- // Note the constraint within the node for that type variable.
269
- node.addConstraint (constraint);
349
+ void ConstraintGraph::addConstraint (Constraint *constraint) {
350
+ // Record the change, if there are active scopes.
351
+ if (ActiveScope) {
352
+ Changes.push_back (Change::addedConstraint (constraint));
270
353
}
271
354
272
- // If the constraint doesn't reference any type variables, it's orphaned;
273
- // track it as such.
274
- if (referencedTypeVars. empty ()) {
355
+ if ( constraint-> getTypeVariables (). empty ()) {
356
+ // A constraint that doesn't reference any type variables is orphaned;
357
+ // track it as such.
275
358
OrphanedConstraints.push_back (constraint);
359
+ return ;
276
360
}
277
361
278
- // Record the change, if there are active scopes.
279
- if (ActiveScope)
280
- Changes.push_back (Change::addedConstraint (constraint));
362
+ // Record this constraint in each type variable.
363
+ for (auto typeVar : constraint->getTypeVariables ()) {
364
+ (*this )[typeVar].addConstraint (constraint);
365
+ }
366
+
367
+ // Record adjacencies.
368
+ enumerateAdjacencies (constraint,
369
+ [&](TypeVariableType *lhs, TypeVariableType *rhs) {
370
+ assert (lhs != rhs);
371
+ (*this )[lhs].addAdjacency (rhs);
372
+ });
281
373
}
282
374
283
375
void ConstraintGraph::removeConstraint (Constraint *constraint) {
284
- // For the nodes corresponding to each type variable...
285
- auto referencedTypeVars = constraint->getTypeVariables ();
286
- for (auto typeVar : referencedTypeVars) {
287
- // Find the node for this type variable.
288
- auto &node = (*this )[typeVar];
289
-
290
- // Remove the constraint.
291
- node.removeConstraint (constraint);
292
- }
376
+ // Record the change, if there are active scopes.
377
+ if (ActiveScope)
378
+ Changes.push_back (Change::removedConstraint (constraint));
293
379
294
- // If this is an orphaned constraint, remove it from the list.
295
- if (referencedTypeVars.empty ()) {
380
+ if (constraint->getTypeVariables ().empty ()) {
381
+ // A constraint that doesn't reference any type variables is orphaned;
382
+ // remove it from the list of orphaned constraints.
296
383
auto known = std::find (OrphanedConstraints.begin (),
297
384
OrphanedConstraints.end (),
298
385
constraint);
299
386
assert (known != OrphanedConstraints.end () && " missing orphaned constraint" );
300
387
*known = OrphanedConstraints.back ();
301
388
OrphanedConstraints.pop_back ();
389
+ return ;
302
390
}
303
391
304
- // Record the change, if there are active scopes.
305
- if (ActiveScope)
306
- Changes.push_back (Change::removedConstraint (constraint));
392
+ // Remove the constraint from each type variable.
393
+ for (auto typeVar : constraint->getTypeVariables ()) {
394
+ (*this )[typeVar].removeConstraint (constraint);
395
+ }
396
+
397
+ // Remove all adjacencies for all type variables.
398
+ enumerateAdjacencies (constraint,
399
+ [&](TypeVariableType *lhs, TypeVariableType *rhs) {
400
+ assert (lhs != rhs);
401
+ (*this )[lhs].removeAdjacency (rhs);
402
+ });
307
403
}
308
404
309
405
void ConstraintGraph::mergeNodes (TypeVariableType *typeVar1,
@@ -1228,6 +1324,28 @@ void ConstraintGraphNode::print(llvm::raw_ostream &out, unsigned indent) {
1228
1324
}
1229
1325
}
1230
1326
1327
+ if (!Adjacencies.empty ()) {
1328
+ out.indent (indent + 2 );
1329
+ out << " Adjacencies:" ;
1330
+ SmallVector<TypeVariableType *, 4 > sortedAdjacencies (Adjacencies.begin (),
1331
+ Adjacencies.end ());
1332
+ std::sort (sortedAdjacencies.begin (), sortedAdjacencies.end (),
1333
+ [](TypeVariableType *lhs, TypeVariableType *rhs) {
1334
+ return lhs->getID () < rhs->getID ();
1335
+ });
1336
+ for (auto adj : sortedAdjacencies) {
1337
+ out << ' ' ;
1338
+ adj->print (out);
1339
+
1340
+ auto &info = AdjacencyInfo[adj];
1341
+ auto degree = info.NumConstraints ;
1342
+ if (degree > 1 ) {
1343
+ out << " (" << degree << " )" ;
1344
+ }
1345
+ }
1346
+ out << " \n " ;
1347
+ }
1348
+
1231
1349
// Print fixed bindings.
1232
1350
if (!FixedBindings.empty ()) {
1233
1351
out.indent (indent + 2 );
@@ -1396,6 +1514,67 @@ void ConstraintGraphNode::verify(ConstraintGraph &cg) {
1396
1514
requireSameValue (info.first , Constraints[info.second ],
1397
1515
" constraint map provides wrong index into vector" );
1398
1516
}
1517
+
1518
+ // Verify that the adjacency map/vector haven't gotten out of sync.
1519
+ requireSameValue (Adjacencies.size (), AdjacencyInfo.size (),
1520
+ " adjacency vector and map have different sizes" );
1521
+ for (auto info : AdjacencyInfo) {
1522
+ require (info.second .Index < Adjacencies.size (),
1523
+ " adjacency index out-of-range" );
1524
+ requireSameValue (info.first , Adjacencies[info.second .Index ],
1525
+ " adjacency map provides wrong index into vector" );
1526
+ require (!info.second .empty (),
1527
+ " adjacency information should have been removed" );
1528
+ require (info.second .NumConstraints <= Constraints.size (),
1529
+ " adjacency information has higher degree than # of constraints" );
1530
+ }
1531
+
1532
+ // Based on the constraints we have, build up a representation of what
1533
+ // we expect the adjacencies to look like.
1534
+ llvm::DenseMap<TypeVariableType *, unsigned > expectedAdjacencies;
1535
+ for (auto constraint : Constraints) {
1536
+ if (constraint->isOneWayConstraint ())
1537
+ continue ;
1538
+
1539
+ for (auto adjTypeVar : constraint->getTypeVariables ()) {
1540
+ if (adjTypeVar == TypeVar)
1541
+ continue ;
1542
+
1543
+ ++expectedAdjacencies[adjTypeVar];
1544
+ }
1545
+ }
1546
+
1547
+ // Make sure that the adjacencies we expect are the adjacencies we have.
1548
+ for (auto adj : expectedAdjacencies) {
1549
+ auto knownAdj = AdjacencyInfo.find (adj.first );
1550
+ requireWithContext (knownAdj != AdjacencyInfo.end (),
1551
+ " missing adjacency information for type variable" ,
1552
+ [&] {
1553
+ llvm::dbgs () << " type variable=" << adj.first ->getString () << ' n' ;
1554
+ });
1555
+
1556
+ requireWithContext (adj.second == knownAdj->second .NumConstraints ,
1557
+ " wrong number of adjacencies for type variable" ,
1558
+ [&] {
1559
+ llvm::dbgs () << " type variable=" << adj.first ->getString ()
1560
+ << " (" << adj.second << " vs. "
1561
+ << knownAdj->second .NumConstraints
1562
+ << " )\n " ;
1563
+ });
1564
+ }
1565
+
1566
+ if (AdjacencyInfo.size () != expectedAdjacencies.size ()) {
1567
+ // The adjacency information has something extra in it. Find the
1568
+ // extraneous type variable.
1569
+ for (auto adj : AdjacencyInfo) {
1570
+ requireWithContext (AdjacencyInfo.count (adj.first ) > 0 ,
1571
+ " extraneous adjacency info for type variable" ,
1572
+ [&] {
1573
+ llvm::dbgs () << " type variable=" << adj.first ->getString () << ' \n ' ;
1574
+ });
1575
+ }
1576
+ }
1577
+
1399
1578
#undef requireSameValue
1400
1579
#undef requireWithContext
1401
1580
#undef require
0 commit comments