Skip to content

Commit 61325c4

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents 630d7e3 + 76fec49 commit 61325c4

File tree

3 files changed

+289
-49
lines changed

3 files changed

+289
-49
lines changed

lib/Sema/ConstraintGraph.cpp

Lines changed: 242 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,74 @@ void ConstraintGraphNode::removeConstraint(Constraint *constraint) {
128128
Constraints.pop_back();
129129
}
130130

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+
131199
void ConstraintGraphNode::addToEquivalenceClass(
132200
ArrayRef<TypeVariableType *> typeVars) {
133201
assert(TypeVar == TypeVar->getImpl().getRepresentative(nullptr) &&
@@ -258,52 +326,80 @@ void ConstraintGraph::removeNode(TypeVariableType *typeVar) {
258326
TypeVariables.pop_back();
259327
}
260328

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.
263338
auto referencedTypeVars = constraint->getTypeVariables();
264339
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+
}
267348

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));
270353
}
271354

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.
275358
OrphanedConstraints.push_back(constraint);
359+
return;
276360
}
277361

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+
});
281373
}
282374

283375
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));
293379

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.
296383
auto known = std::find(OrphanedConstraints.begin(),
297384
OrphanedConstraints.end(),
298385
constraint);
299386
assert(known != OrphanedConstraints.end() && "missing orphaned constraint");
300387
*known = OrphanedConstraints.back();
301388
OrphanedConstraints.pop_back();
389+
return;
302390
}
303391

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+
});
307403
}
308404

309405
void ConstraintGraph::mergeNodes(TypeVariableType *typeVar1,
@@ -377,7 +473,6 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
377473
TypeVariableType *typeVar, GatheringKind kind,
378474
llvm::function_ref<bool(Constraint *)> acceptConstraintFn) {
379475
llvm::TinyPtrVector<Constraint *> constraints;
380-
381476
// Whether we should consider this constraint at all.
382477
auto rep = CS.getRepresentative(typeVar);
383478
auto shouldConsiderConstraint = [&](Constraint *constraint) {
@@ -409,19 +504,29 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
409504

410505
// Add constraints for the given adjacent type variable.
411506
llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
507+
508+
// Local function to add constraints
412509
llvm::SmallPtrSet<Constraint *, 4> visitedConstraints;
413-
auto addAdjacentConstraints = [&](TypeVariableType *adjTypeVar) {
414-
auto adjTypeVarsToVisit =
415-
(*this)[CS.getRepresentative(adjTypeVar)].getEquivalenceClass();
510+
auto addConstraintsOfAdjacency = [&](TypeVariableType *adjTypeVar) {
511+
ArrayRef<TypeVariableType *> adjTypeVarsToVisit;
512+
switch (kind) {
513+
case GatheringKind::EquivalenceClass:
514+
adjTypeVarsToVisit = adjTypeVar;
515+
break;
516+
517+
case GatheringKind::AllMentions:
518+
adjTypeVarsToVisit
519+
= (*this)[CS.getRepresentative(adjTypeVar)].getEquivalenceClass();
520+
break;
521+
}
522+
416523
for (auto adjTypeVarEquiv : adjTypeVarsToVisit) {
417524
if (!typeVars.insert(adjTypeVarEquiv).second)
418525
continue;
419526

420527
for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints()) {
421-
if (!visitedConstraints.insert(constraint).second)
422-
continue;
423-
424-
if (acceptConstraint(constraint))
528+
if (visitedConstraints.insert(constraint).second &&
529+
acceptConstraint(constraint))
425530
constraints.push_back(constraint);
426531
}
427532
}
@@ -430,29 +535,34 @@ llvm::TinyPtrVector<Constraint *> ConstraintGraph::gatherConstraints(
430535
auto &reprNode = (*this)[CS.getRepresentative(typeVar)];
431536
auto equivClass = reprNode.getEquivalenceClass();
432537
for (auto typeVar : equivClass) {
433-
auto &node = (*this)[typeVar];
434-
for (auto constraint : node.getConstraints()) {
538+
if (!typeVars.insert(typeVar).second)
539+
continue;
540+
541+
for (auto constraint : (*this)[typeVar].getConstraints()) {
435542
if (visitedConstraints.insert(constraint).second &&
436543
acceptConstraint(constraint))
437544
constraints.push_back(constraint);
545+
}
438546

439-
// If we want all mentions, visit type variables within each of our
440-
// constraints.
441-
if (kind == GatheringKind::AllMentions) {
442-
if (!shouldConsiderConstraint(constraint))
443-
continue;
547+
auto &node = (*this)[typeVar];
444548

445-
for (auto adjTypeVar : constraint->getTypeVariables()) {
446-
addAdjacentConstraints(adjTypeVar);
447-
}
448-
}
549+
for (auto adjTypeVar : node.getFixedBindings()) {
550+
addConstraintsOfAdjacency(adjTypeVar);
449551
}
450552

451-
// For any type variable mentioned in a fixed binding, add adjacent
452-
// constraints.
453-
for (auto adjTypeVar : node.getFixedBindings()) {
454-
addAdjacentConstraints(adjTypeVar);
553+
switch (kind) {
554+
case GatheringKind::EquivalenceClass:
555+
break;
556+
557+
case GatheringKind::AllMentions:
558+
// Retrieve the constraints from adjacent bindings.
559+
for (auto adjTypeVar : node.getAdjacencies()) {
560+
addConstraintsOfAdjacency(adjTypeVar);
561+
}
562+
563+
break;
455564
}
565+
456566
}
457567

458568
return constraints;
@@ -1228,6 +1338,28 @@ void ConstraintGraphNode::print(llvm::raw_ostream &out, unsigned indent) {
12281338
}
12291339
}
12301340

1341+
if (!Adjacencies.empty()) {
1342+
out.indent(indent + 2);
1343+
out << "Adjacencies:";
1344+
SmallVector<TypeVariableType *, 4> sortedAdjacencies(Adjacencies.begin(),
1345+
Adjacencies.end());
1346+
std::sort(sortedAdjacencies.begin(), sortedAdjacencies.end(),
1347+
[](TypeVariableType *lhs, TypeVariableType *rhs) {
1348+
return lhs->getID() < rhs->getID();
1349+
});
1350+
for (auto adj : sortedAdjacencies) {
1351+
out << ' ';
1352+
adj->print(out);
1353+
1354+
auto &info = AdjacencyInfo[adj];
1355+
auto degree = info.NumConstraints;
1356+
if (degree > 1) {
1357+
out << " (" << degree << ")";
1358+
}
1359+
}
1360+
out << "\n";
1361+
}
1362+
12311363
// Print fixed bindings.
12321364
if (!FixedBindings.empty()) {
12331365
out.indent(indent + 2);
@@ -1396,6 +1528,67 @@ void ConstraintGraphNode::verify(ConstraintGraph &cg) {
13961528
requireSameValue(info.first, Constraints[info.second],
13971529
"constraint map provides wrong index into vector");
13981530
}
1531+
1532+
// Verify that the adjacency map/vector haven't gotten out of sync.
1533+
requireSameValue(Adjacencies.size(), AdjacencyInfo.size(),
1534+
"adjacency vector and map have different sizes");
1535+
for (auto info : AdjacencyInfo) {
1536+
require(info.second.Index < Adjacencies.size(),
1537+
"adjacency index out-of-range");
1538+
requireSameValue(info.first, Adjacencies[info.second.Index],
1539+
"adjacency map provides wrong index into vector");
1540+
require(!info.second.empty(),
1541+
"adjacency information should have been removed");
1542+
require(info.second.NumConstraints <= Constraints.size(),
1543+
"adjacency information has higher degree than # of constraints");
1544+
}
1545+
1546+
// Based on the constraints we have, build up a representation of what
1547+
// we expect the adjacencies to look like.
1548+
llvm::DenseMap<TypeVariableType *, unsigned> expectedAdjacencies;
1549+
for (auto constraint : Constraints) {
1550+
if (constraint->isOneWayConstraint())
1551+
continue;
1552+
1553+
for (auto adjTypeVar : constraint->getTypeVariables()) {
1554+
if (adjTypeVar == TypeVar)
1555+
continue;
1556+
1557+
++expectedAdjacencies[adjTypeVar];
1558+
}
1559+
}
1560+
1561+
// Make sure that the adjacencies we expect are the adjacencies we have.
1562+
for (auto adj : expectedAdjacencies) {
1563+
auto knownAdj = AdjacencyInfo.find(adj.first);
1564+
requireWithContext(knownAdj != AdjacencyInfo.end(),
1565+
"missing adjacency information for type variable",
1566+
[&] {
1567+
llvm::dbgs() << " type variable=" << adj.first->getString() << 'n';
1568+
});
1569+
1570+
requireWithContext(adj.second == knownAdj->second.NumConstraints,
1571+
"wrong number of adjacencies for type variable",
1572+
[&] {
1573+
llvm::dbgs() << " type variable=" << adj.first->getString()
1574+
<< " (" << adj.second << " vs. "
1575+
<< knownAdj->second.NumConstraints
1576+
<< ")\n";
1577+
});
1578+
}
1579+
1580+
if (AdjacencyInfo.size() != expectedAdjacencies.size()) {
1581+
// The adjacency information has something extra in it. Find the
1582+
// extraneous type variable.
1583+
for (auto adj : AdjacencyInfo) {
1584+
requireWithContext(AdjacencyInfo.count(adj.first) > 0,
1585+
"extraneous adjacency info for type variable",
1586+
[&] {
1587+
llvm::dbgs() << " type variable=" << adj.first->getString() << '\n';
1588+
});
1589+
}
1590+
}
1591+
13991592
#undef requireSameValue
14001593
#undef requireWithContext
14011594
#undef require

0 commit comments

Comments
 (0)