@@ -616,6 +616,11 @@ class GenericSignatureBuilder::ExplicitRequirement {
616616
617617 return true ;
618618 }
619+
620+ friend bool operator !=(const ExplicitRequirement &lhs,
621+ const ExplicitRequirement &rhs) {
622+ return !(lhs == rhs);
623+ }
619624};
620625
621626namespace llvm {
@@ -690,8 +695,13 @@ struct GenericSignatureBuilder::Implementation {
690695 // / Whether there were any errors.
691696 bool HadAnyError = false ;
692697
693- // / The set of computed redundant explicit requirements.
694- llvm::DenseSet<ExplicitRequirement> RedundantRequirements;
698+ // / A mapping of redundant explicit requirements to the best root requirement
699+ // / that implies them.
700+ using RedundantRequirementMap =
701+ llvm::DenseMap<ExplicitRequirement,
702+ llvm::SmallDenseSet<ExplicitRequirement, 2 >>;
703+
704+ RedundantRequirementMap RedundantRequirements;
695705
696706#ifndef NDEBUG
697707 // / Whether we've already computed redundant requiremnts.
@@ -5624,8 +5634,8 @@ class RedundantRequirementGraph {
56245634
56255635 SmallVector<Vertex, 2 > vertices;
56265636
5627- ComponentID nextComponent = 0 ;
5628- VertexID nextIndex = 0 ;
5637+ ComponentID componentCount = 0 ;
5638+ VertexID vertexCount = 0 ;
56295639
56305640 SmallVector<VertexID, 2 > stack;
56315641
@@ -5784,11 +5794,11 @@ class RedundantRequirementGraph {
57845794 void strongConnect (VertexID v) {
57855795 // Set the depth index for v to the smallest unused index.
57865796 assert (vertices[v].index == Vertex::UndefinedIndex);
5787- vertices[v].index = nextIndex ;
5797+ vertices[v].index = vertexCount ;
57885798 assert (vertices[v].lowLink == Vertex::UndefinedIndex);
5789- vertices[v].lowLink = nextIndex ;
5799+ vertices[v].lowLink = vertexCount ;
57905800
5791- nextIndex ++;
5801+ vertexCount ++;
57925802
57935803 stack.push_back (v);
57945804 assert (!vertices[v].onStack );
@@ -5826,40 +5836,60 @@ class RedundantRequirementGraph {
58265836 vertices[w].onStack = false ;
58275837 assert (vertices[w].component == Vertex::UndefinedComponent);
58285838
5829- vertices[w].component = nextComponent ;
5839+ vertices[w].component = componentCount ;
58305840 } while (v != w);
58315841
5832- nextComponent ++;
5842+ componentCount ++;
58335843 }
58345844 }
58355845
58365846public:
5847+ using RedundantRequirementMap =
5848+ llvm::DenseMap<ExplicitRequirement,
5849+ llvm::SmallDenseSet<ExplicitRequirement, 2 >>;
5850+
58375851 void computeRedundantRequirements (SourceManager &SM,
5838- llvm::DenseSet<ExplicitRequirement> &redundant) {
5852+ RedundantRequirementMap &redundant) {
58395853 // First, compute SCCs.
58405854 computeSCCs ();
58415855
5842- // The number of edges from other connected components to this one.
5843- SmallVector<unsigned , 2 > inboundComponentEdges;
5844- inboundComponentEdges.resize (nextComponent);
5856+ // The set of edges pointing to each connected component.
5857+ SmallVector<SmallVector<ComponentID, 2 >, 2 > inboundComponentEdges;
5858+ inboundComponentEdges.resize (componentCount);
5859+
5860+ // The set of edges originating from this connected component.
5861+ SmallVector<SmallVector<ComponentID, 2 >, 2 > outboundComponentEdges;
5862+ outboundComponentEdges.resize (componentCount);
58455863
5846- // Visit all vertices and count inter-component edges.
5864+ // Visit all vertices and build the adjacency sets for the connected
5865+ // component graph.
58475866 for (const auto &vertex : vertices) {
58485867 assert (vertex.component != Vertex::UndefinedComponent);
58495868 for (auto successor : vertex.successors ) {
58505869 ComponentID otherComponent = vertices[successor].component ;
5851- if (vertex.component != otherComponent)
5852- ++inboundComponentEdges[otherComponent];
5870+ if (vertex.component != otherComponent) {
5871+ inboundComponentEdges[otherComponent].push_back (vertex.component );
5872+ outboundComponentEdges[vertex.component ].push_back (otherComponent);
5873+ }
58535874 }
58545875 }
58555876
5856- // The best explicit requirement for each root SCC.
5877+ auto isRootComponent = [&](ComponentID component) -> bool {
5878+ return inboundComponentEdges[component].empty ();
5879+ };
5880+
5881+ // The set of root components.
5882+ llvm::SmallDenseSet<ComponentID, 2 > rootComponents;
5883+
5884+ // The best explicit requirement for each root component.
58575885 SmallVector<Optional<ExplicitRequirement>, 2 > bestExplicitReq;
5858- bestExplicitReq.resize (nextComponent );
5886+ bestExplicitReq.resize (componentCount );
58595887
5860- // Visit all vertices and find the best requirement for each root SCC .
5888+ // Visit all vertices and find the best requirement for each root component .
58615889 for (const auto &vertex : vertices) {
5862- if (inboundComponentEdges[vertex.component ] == 0 ) {
5890+ if (isRootComponent (vertex.component )) {
5891+ rootComponents.insert (vertex.component );
5892+
58635893 // If this vertex is part of a root SCC, see if the requirement is
58645894 // better than the one we have so far.
58655895 auto &best = bestExplicitReq[vertex.component ];
@@ -5868,26 +5898,61 @@ class RedundantRequirementGraph {
58685898 }
58695899 }
58705900
5871- // Compute the set of redundant requirements.
5872- for (const auto &vertex : vertices) {
5873- if (inboundComponentEdges[vertex.component ] == 0 ) {
5874- // We have a root SCC. This requirement is redundant unless
5875- // it is the best requirement for this SCC.
5876- auto best = bestExplicitReq[vertex.component ];
5877- assert (best.hasValue () &&
5878- " Did not record best requirement for root SCC?" );
5901+ // The set of root components that each component is reachable from.
5902+ SmallVector<llvm::SmallDenseSet<ComponentID, 2 >, 2 > reachableFromRoot;
5903+ reachableFromRoot.resize (componentCount);
58795904
5880- if (vertex.req == *best)
5881- continue ;
5905+ // Traverse the graph of connected components starting from the roots.
5906+ for (auto rootComponent : rootComponents) {
5907+ SmallVector<ComponentID, 2 > worklist;
5908+
5909+ auto addToWorklist = [&](ComponentID nextComponent) {
5910+ if (!reachableFromRoot[nextComponent].count (rootComponent))
5911+ worklist.push_back (nextComponent);
5912+ };
5913+
5914+ addToWorklist (rootComponent);
5915+
5916+ while (!worklist.empty ()) {
5917+ auto component = worklist.back ();
5918+ worklist.pop_back ();
5919+
5920+ reachableFromRoot[component].insert (rootComponent);
5921+
5922+ for (auto nextComponent : outboundComponentEdges[component])
5923+ addToWorklist (nextComponent);
5924+ }
5925+ }
5926+
5927+ // Compute the mapping of redundant requirements to the best root
5928+ // requirement that implies them.
5929+ for (const auto &vertex : vertices) {
5930+ if (isRootComponent (vertex.component )) {
5931+ // A root component is reachable from itself, and itself only.
5932+ assert (reachableFromRoot[vertex.component ].size () == 1 );
5933+ assert (reachableFromRoot[vertex.component ].count (vertex.component ) == 1 );
58825934 } else {
5883- // We have a non-root SCC. This requirement is always
5884- // redundant.
58855935 assert (!bestExplicitReq[vertex.component ].hasValue () &&
58865936 " Recorded best requirement for non-root SCC?" );
58875937 }
58885938
5889- auto inserted = redundant.insert (vertex.req );
5890- assert (inserted.second && " Saw the same vertex twice?" );
5939+ // We have a non-root component. This requirement is always
5940+ // redundant.
5941+ auto reachableFromRootSet = reachableFromRoot[vertex.component ];
5942+ assert (reachableFromRootSet.size () > 0 );
5943+
5944+ for (auto rootComponent : reachableFromRootSet) {
5945+ assert (isRootComponent (rootComponent));
5946+
5947+ auto best = bestExplicitReq[rootComponent];
5948+ assert (best.hasValue () &&
5949+ " Did not record best requirement for root SCC?" );
5950+
5951+ assert (vertex.req != *best || vertex.component == rootComponent);
5952+ if (vertex.req != *best) {
5953+ redundant[vertex.req ].insert (*best);
5954+ }
5955+ }
58915956 }
58925957 }
58935958
0 commit comments