|
@@ -1496,7 +1496,7 @@ TEST(LazyCallGraphTest, InternalEdgeMutation) {
|
|
|
// Switch the call edge from 'b' to 'c' to a ref edge. This will break the
|
|
|
// call cycle and cause us to form more SCCs. The RefSCC will remain the same
|
|
|
// though.
|
|
|
- RC.switchInternalEdgeToRef(B, C);
|
|
|
+ auto NewCs = RC.switchInternalEdgeToRef(B, C);
|
|
|
EXPECT_EQ(&RC, CG.lookupRefSCC(A));
|
|
|
EXPECT_EQ(&RC, CG.lookupRefSCC(B));
|
|
|
EXPECT_EQ(&RC, CG.lookupRefSCC(C));
|
|
@@ -1508,6 +1508,10 @@ TEST(LazyCallGraphTest, InternalEdgeMutation) {
|
|
|
EXPECT_EQ(&*J++, CG.lookupSCC(A));
|
|
|
EXPECT_EQ(&*J++, CG.lookupSCC(C));
|
|
|
EXPECT_EQ(RC.end(), J);
|
|
|
+ // And the returned range must be the slice of this sequence containing new
|
|
|
+ // SCCs.
|
|
|
+ EXPECT_EQ(RC.begin(), NewCs.begin());
|
|
|
+ EXPECT_EQ(std::prev(RC.end()), NewCs.end());
|
|
|
|
|
|
// Test turning the ref edge from A to C into a call edge. This will form an
|
|
|
// SCC out of A and C. Since we previously had a call edge from C to A, the
|
|
@@ -1710,54 +1714,59 @@ TEST(LazyCallGraphTest, InternalCallEdgeToRef) {
|
|
|
EXPECT_EQ(CG.postorder_ref_scc_end(), I);
|
|
|
|
|
|
EXPECT_EQ(1, RC.size());
|
|
|
- LazyCallGraph::SCC &CallC = *RC.begin();
|
|
|
+ LazyCallGraph::SCC &AC = *RC.begin();
|
|
|
|
|
|
- LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
|
|
|
- LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
|
|
|
- LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(A));
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(B));
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(C));
|
|
|
+ LazyCallGraph::Node &AN = *CG.lookup(lookupFunction(*M, "a"));
|
|
|
+ LazyCallGraph::Node &BN = *CG.lookup(lookupFunction(*M, "b"));
|
|
|
+ LazyCallGraph::Node &CN = *CG.lookup(lookupFunction(*M, "c"));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(AN));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(BN));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(CN));
|
|
|
|
|
|
// Remove the call edge from b -> a to a ref edge, which should leave the
|
|
|
// 3 functions still in a single connected component because of a -> b ->
|
|
|
// c -> a.
|
|
|
- RC.switchInternalEdgeToRef(B, A);
|
|
|
+ auto NewCs = RC.switchInternalEdgeToRef(BN, AN);
|
|
|
+ EXPECT_EQ(NewCs.begin(), NewCs.end());
|
|
|
EXPECT_EQ(1, RC.size());
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(A));
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(B));
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(C));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(AN));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(BN));
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(CN));
|
|
|
|
|
|
// Remove the edge from c -> a, which should leave 'a' in the original SCC
|
|
|
// and form a new SCC for 'b' and 'c'.
|
|
|
- RC.switchInternalEdgeToRef(C, A);
|
|
|
+ NewCs = RC.switchInternalEdgeToRef(CN, AN);
|
|
|
+ EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
|
|
|
EXPECT_EQ(2, RC.size());
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(A));
|
|
|
- LazyCallGraph::SCC &BCallC = *CG.lookupSCC(B);
|
|
|
- EXPECT_NE(&BCallC, &CallC);
|
|
|
- EXPECT_EQ(&BCallC, CG.lookupSCC(C));
|
|
|
- auto J = RC.find(CallC);
|
|
|
- EXPECT_EQ(&CallC, &*J);
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(AN));
|
|
|
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(BN);
|
|
|
+ EXPECT_NE(&BC, &AC);
|
|
|
+ EXPECT_EQ(&BC, CG.lookupSCC(CN));
|
|
|
+ auto J = RC.find(AC);
|
|
|
+ EXPECT_EQ(&AC, &*J);
|
|
|
--J;
|
|
|
- EXPECT_EQ(&BCallC, &*J);
|
|
|
+ EXPECT_EQ(&BC, &*J);
|
|
|
EXPECT_EQ(RC.begin(), J);
|
|
|
+ EXPECT_EQ(J, NewCs.begin());
|
|
|
|
|
|
// Remove the edge from c -> b, which should leave 'b' in the original SCC
|
|
|
// and form a new SCC for 'c'. It shouldn't change 'a's SCC.
|
|
|
- RC.switchInternalEdgeToRef(C, B);
|
|
|
+ NewCs = RC.switchInternalEdgeToRef(CN, BN);
|
|
|
+ EXPECT_EQ(1, std::distance(NewCs.begin(), NewCs.end()));
|
|
|
EXPECT_EQ(3, RC.size());
|
|
|
- EXPECT_EQ(&CallC, CG.lookupSCC(A));
|
|
|
- EXPECT_EQ(&BCallC, CG.lookupSCC(B));
|
|
|
- LazyCallGraph::SCC &CCallC = *CG.lookupSCC(C);
|
|
|
- EXPECT_NE(&CCallC, &CallC);
|
|
|
- EXPECT_NE(&CCallC, &BCallC);
|
|
|
- J = RC.find(CallC);
|
|
|
- EXPECT_EQ(&CallC, &*J);
|
|
|
+ EXPECT_EQ(&AC, CG.lookupSCC(AN));
|
|
|
+ EXPECT_EQ(&BC, CG.lookupSCC(BN));
|
|
|
+ LazyCallGraph::SCC &CC = *CG.lookupSCC(CN);
|
|
|
+ EXPECT_NE(&CC, &AC);
|
|
|
+ EXPECT_NE(&CC, &BC);
|
|
|
+ J = RC.find(AC);
|
|
|
+ EXPECT_EQ(&AC, &*J);
|
|
|
--J;
|
|
|
- EXPECT_EQ(&BCallC, &*J);
|
|
|
+ EXPECT_EQ(&BC, &*J);
|
|
|
--J;
|
|
|
- EXPECT_EQ(&CCallC, &*J);
|
|
|
+ EXPECT_EQ(&CC, &*J);
|
|
|
EXPECT_EQ(RC.begin(), J);
|
|
|
+ EXPECT_EQ(J, NewCs.begin());
|
|
|
}
|
|
|
|
|
|
TEST(LazyCallGraphTest, InternalRefEdgeToCall) {
|
|
@@ -1927,11 +1936,11 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallNoCycleInterleaved) {
|
|
|
|
|
|
// Several call edges are initially present to force a particual post-order.
|
|
|
// Remove them now, leaving an interleaved post-order pattern.
|
|
|
- RC.switchInternalEdgeToRef(B3, C3);
|
|
|
- RC.switchInternalEdgeToRef(C2, B3);
|
|
|
- RC.switchInternalEdgeToRef(B2, C2);
|
|
|
- RC.switchInternalEdgeToRef(C1, B2);
|
|
|
- RC.switchInternalEdgeToRef(B1, C1);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(B3, C3);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(C2, B3);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(B2, C2);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(C1, B2);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(B1, C1);
|
|
|
|
|
|
// Check the initial post-order. We ensure this order with the extra edges
|
|
|
// that are nuked above.
|
|
@@ -2054,8 +2063,8 @@ TEST(LazyCallGraphTest, InternalRefEdgeToCallBothPartitionAndMerge) {
|
|
|
LazyCallGraph::SCC &GC = *CG.lookupSCC(G);
|
|
|
|
|
|
// Remove the extra edges that were used to force a particular post-order.
|
|
|
- RC.switchInternalEdgeToRef(C, D);
|
|
|
- RC.switchInternalEdgeToRef(D, E);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(C, D);
|
|
|
+ RC.switchTrivialInternalEdgeToRef(D, E);
|
|
|
|
|
|
// Check the initial post-order. We ensure this order with the extra edges
|
|
|
// that are nuked above.
|