1 //===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/SCCIterator.h"
10 #include "TestGraph.h"
11 #include "gtest/gtest.h"
18 TEST(SCCIteratorTest
, AllSmallGraphs
) {
19 // Test SCC computation against every graph with NUM_NODES nodes or less.
20 // Since SCC considers every node to have an implicit self-edge, we only
21 // create graphs for which every node has a self-edge.
23 #define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))
24 typedef Graph
<NUM_NODES
> GT
;
26 /// Enumerate all graphs using NUM_GRAPHS bits.
27 static_assert(NUM_GRAPHS
< sizeof(unsigned) * CHAR_BIT
, "Too many graphs!");
28 for (unsigned GraphDescriptor
= 0; GraphDescriptor
< (1U << NUM_GRAPHS
);
32 // Add edges as specified by the descriptor.
33 unsigned DescriptorCopy
= GraphDescriptor
;
34 for (unsigned i
= 0; i
!= NUM_NODES
; ++i
)
35 for (unsigned j
= 0; j
!= NUM_NODES
; ++j
) {
36 // Always add a self-edge.
41 if (DescriptorCopy
& 1)
46 // Test the SCC logic on this graph.
48 /// NodesInSomeSCC - Those nodes which are in some SCC.
49 GT::NodeSubset NodesInSomeSCC
;
51 for (scc_iterator
<GT
> I
= scc_begin(G
), E
= scc_end(G
); I
!= E
; ++I
) {
52 const std::vector
<GT::NodeType
*> &SCC
= *I
;
54 // Get the nodes in this SCC as a NodeSubset rather than a vector.
55 GT::NodeSubset NodesInThisSCC
;
56 for (unsigned i
= 0, e
= SCC
.size(); i
!= e
; ++i
)
57 NodesInThisSCC
.AddNode(SCC
[i
]->first
);
59 // There should be at least one node in every SCC.
60 EXPECT_FALSE(NodesInThisSCC
.isEmpty());
62 // Check that every node in the SCC is reachable from every other node in
64 for (unsigned i
= 0; i
!= NUM_NODES
; ++i
)
65 if (NodesInThisSCC
.count(i
)) {
66 EXPECT_TRUE(NodesInThisSCC
.isSubsetOf(G
.NodesReachableFrom(i
)));
69 // OK, now that we now that every node in the SCC is reachable from every
70 // other, this means that the set of nodes reachable from any node in the
71 // SCC is the same as the set of nodes reachable from every node in the
72 // SCC. Check that for every node N not in the SCC but reachable from the
73 // SCC, no element of the SCC is reachable from N.
74 for (unsigned i
= 0; i
!= NUM_NODES
; ++i
)
75 if (NodesInThisSCC
.count(i
)) {
76 GT::NodeSubset NodesReachableFromSCC
= G
.NodesReachableFrom(i
);
77 GT::NodeSubset ReachableButNotInSCC
=
78 NodesReachableFromSCC
.Meet(NodesInThisSCC
.Complement());
80 for (unsigned j
= 0; j
!= NUM_NODES
; ++j
)
81 if (ReachableButNotInSCC
.count(j
)) {
82 EXPECT_TRUE(G
.NodesReachableFrom(j
).Meet(NodesInThisSCC
).isEmpty());
85 // The result must be the same for all other nodes in this SCC, so
86 // there is no point in checking them.
90 // This is indeed a SCC: a maximal set of nodes for which each node is
91 // reachable from every other.
93 // Check that we didn't already see this SCC.
94 EXPECT_TRUE(NodesInSomeSCC
.Meet(NodesInThisSCC
).isEmpty());
96 NodesInSomeSCC
= NodesInSomeSCC
.Join(NodesInThisSCC
);
98 // Check a property that is specific to the LLVM SCC iterator and
99 // guaranteed by it: if a node in SCC S1 has an edge to a node in
100 // SCC S2, then S1 is visited *after* S2. This means that the set
101 // of nodes reachable from this SCC must be contained either in the
102 // union of this SCC and all previously visited SCC's.
104 for (unsigned i
= 0; i
!= NUM_NODES
; ++i
)
105 if (NodesInThisSCC
.count(i
)) {
106 GT::NodeSubset NodesReachableFromSCC
= G
.NodesReachableFrom(i
);
107 EXPECT_TRUE(NodesReachableFromSCC
.isSubsetOf(NodesInSomeSCC
));
108 // The result must be the same for all other nodes in this SCC, so
109 // there is no point in checking them.
114 // Finally, check that the nodes in some SCC are exactly those that are
115 // reachable from the initial node.
116 EXPECT_EQ(NodesInSomeSCC
, G
.NodesReachableFrom(0));