Skip to content

Commit 71d666f

Browse files
authored
Merge pull request swiftlang#76962 from slavapestov/connected-components-graph
Sema: Optimize computeConnectedComponents()
2 parents 3d40a8c + 3a4de0b commit 71d666f

File tree

1 file changed

+42
-32
lines changed

1 file changed

+42
-32
lines changed

lib/Sema/ConstraintGraph.cpp

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,10 @@ namespace {
722722
mutable llvm::SmallDenseMap<TypeVariableType *, TypeVariableType *>
723723
representatives;
724724

725+
// Figure out which components have unbound type variables and/or
726+
// constraints. These are the only components we want to report.
727+
llvm::SmallDenseSet<TypeVariableType *> validComponents;
728+
725729
/// The complete set of constraints that were visited while computing
726730
/// connected components.
727731
llvm::SmallPtrSet<Constraint *, 8> visitedConstraints;
@@ -764,47 +768,34 @@ namespace {
764768

765769
/// Retrieve the set of components.
766770
SmallVector<Component, 1> getComponents() const {
767-
// Figure out which components have unbound type variables and/or
768-
// constraints. These are the only components we want to report.
769-
llvm::SmallDenseSet<TypeVariableType *> validComponents;
770-
auto &cs = cg.getConstraintSystem();
771-
for (auto typeVar : typeVars) {
772-
// If this type variable has a fixed type, skip it.
773-
if (cs.getFixedType(typeVar))
774-
continue;
771+
// The final return value.
772+
SmallVector<Component, 1> flatComponents;
775773

776-
auto rep = findRepresentative(typeVar);
777-
validComponents.insert(rep);
778-
}
779774

780-
for (auto &constraint : cs.getConstraints()) {
781-
for (auto typeVar : constraint.getTypeVariables()) {
782-
auto rep = findRepresentative(typeVar);
783-
validComponents.insert(rep);
784-
}
785-
}
775+
// We don't actually need to partition the graph into components if
776+
// there are fewer than 2.
777+
if (validComponents.size() < 2 && cg.getOrphanedConstraints().empty())
778+
return flatComponents;
786779

787-
// Capture the type variables of each component.
780+
// Mapping from representatives to components.
788781
llvm::SmallDenseMap<TypeVariableType *, Component> components;
789782
SmallVector<TypeVariableType *, 4> representativeTypeVars;
783+
784+
// Capture the type variables of each component.
790785
for (auto typeVar : typeVars) {
791786
// Find the representative. If we aren't creating a type variable
792787
// for this component, skip it.
793788
auto rep = findRepresentative(typeVar);
794789
if (validComponents.count(rep) == 0)
795790
continue;
796791

797-
// If this type variable is the representative, add it to the list of
798-
// representatives.
799-
if (rep == typeVar) {
792+
auto pair = components.insert({rep, Component(components.size())});
793+
if (pair.second)
800794
representativeTypeVars.push_back(rep);
801-
}
802795

803796
// Record this type variable in the set of type variables for its
804797
// component.
805-
auto &component = components.insert(
806-
{rep, Component(components.size())}).first->second;
807-
component.typeVars.push_back(typeVar);
798+
pair.first->second.typeVars.push_back(typeVar);
808799
}
809800

810801
// Retrieve the component for the given representative type variable.
@@ -814,6 +805,8 @@ namespace {
814805
return component->second;
815806
};
816807

808+
auto &cs = cg.getConstraintSystem();
809+
817810
// Assign each constraint to its appropriate component.
818811
// Note: we use the inactive constraints so that we maintain the
819812
// order of constraints when we re-introduce them.
@@ -848,8 +841,7 @@ namespace {
848841
});
849842

850843
representativeTypeVars =
851-
computeOneWayComponentOrdering(representativeTypeVars,
852-
validComponents);
844+
computeOneWayComponentOrdering(representativeTypeVars);
853845

854846
// Fill in one-way dependency information for all of the components.
855847
for (auto typeVar : representativeTypeVars) {
@@ -869,7 +861,6 @@ namespace {
869861
}
870862

871863
// Flatten the set of components.
872-
SmallVector<Component, 1> flatComponents;
873864
flatComponents.reserve(
874865
representativeTypeVars.size() + cg.getOrphanedConstraints().size());
875866
for (auto rep: representativeTypeVars) {
@@ -934,10 +925,13 @@ namespace {
934925

935926
// Reparent the type variable with the higher ID. The actual choice doesn't
936927
// matter, but this makes debugging easier.
937-
if (rep1->getID() < rep2->getID())
928+
if (rep1->getID() < rep2->getID()) {
929+
validComponents.erase(rep2);
938930
representatives[rep2] = rep1;
939-
else
931+
} else {
932+
validComponents.erase(rep1);
940933
representatives[rep1] = rep2;
934+
}
941935
return true;
942936
}
943937

@@ -948,6 +942,8 @@ namespace {
948942
TinyPtrVector<Constraint *> connectedComponents() {
949943
TinyPtrVector<Constraint *> oneWayConstraints;
950944

945+
auto &cs = cg.getConstraintSystem();
946+
951947
// Perform a depth-first search from each type variable to identify
952948
// what component it is in.
953949
for (auto typeVar : typeVars) {
@@ -966,6 +962,10 @@ namespace {
966962
assert((inserted.second || inserted.first->second == typeVar) &&
967963
"Wrong component?");
968964

965+
if (inserted.second)
966+
if (!cs.getFixedType(found))
967+
validComponents.insert(typeVar);
968+
969969
return inserted.second;
970970
},
971971
[&](Constraint *constraint) {
@@ -980,6 +980,17 @@ namespace {
980980
visitedConstraints);
981981
}
982982

983+
for (auto &constraint : cs.getConstraints()) {
984+
if (constraint.getKind() == ConstraintKind::Disjunction ||
985+
constraint.getKind() == ConstraintKind::Conjunction) {
986+
for (auto typeVar : constraint.getTypeVariables()) {
987+
auto rep = findRepresentative(typeVar);
988+
if (validComponents.insert(rep).second)
989+
ASSERT(cs.getFixedType(typeVar));
990+
}
991+
}
992+
}
993+
983994
return oneWayConstraints;
984995
}
985996

@@ -1196,8 +1207,7 @@ namespace {
11961207
/// solved after the components for type variables on the right-hand
11971208
/// side of that constraint.
11981209
SmallVector<TypeVariableType *, 4> computeOneWayComponentOrdering(
1199-
ArrayRef<TypeVariableType *> representativeTypeVars,
1200-
llvm::SmallDenseSet<TypeVariableType *> &validComponents) const {
1210+
ArrayRef<TypeVariableType *> representativeTypeVars) const {
12011211
SmallVector<TypeVariableType *, 4> orderedReps;
12021212
orderedReps.reserve(representativeTypeVars.size());
12031213
SmallPtrSet<TypeVariableType *, 4> visited;

0 commit comments

Comments
 (0)