Home | History | Annotate | Download | only in Analysis
      1 //===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Analysis/LazyCallGraph.h"
     11 #include "llvm/AsmParser/Parser.h"
     12 #include "llvm/IR/Function.h"
     13 #include "llvm/IR/LLVMContext.h"
     14 #include "llvm/IR/Module.h"
     15 #include "llvm/Support/ErrorHandling.h"
     16 #include "llvm/Support/SourceMgr.h"
     17 #include "gtest/gtest.h"
     18 #include <memory>
     19 
     20 using namespace llvm;
     21 
     22 namespace {
     23 
     24 std::unique_ptr<Module> parseAssembly(const char *Assembly) {
     25   SMDiagnostic Error;
     26   std::unique_ptr<Module> M =
     27       parseAssemblyString(Assembly, Error, getGlobalContext());
     28 
     29   std::string ErrMsg;
     30   raw_string_ostream OS(ErrMsg);
     31   Error.print("", OS);
     32 
     33   // A failure here means that the test itself is buggy.
     34   if (!M)
     35     report_fatal_error(OS.str().c_str());
     36 
     37   return M;
     38 }
     39 
     40 /*
     41    IR forming a call graph with a diamond of triangle-shaped SCCs:
     42 
     43            d1
     44           /  \
     45          d3--d2
     46         /     \
     47        b1     c1
     48      /  \    /  \
     49     b3--b2  c3--c2
     50          \  /
     51           a1
     52          /  \
     53         a3--a2
     54 
     55    All call edges go up between SCCs, and clockwise around the SCC.
     56  */
     57 static const char DiamondOfTriangles[] =
     58      "define void @a1() {\n"
     59      "entry:\n"
     60      "  call void @a2()\n"
     61      "  call void @b2()\n"
     62      "  call void @c3()\n"
     63      "  ret void\n"
     64      "}\n"
     65      "define void @a2() {\n"
     66      "entry:\n"
     67      "  call void @a3()\n"
     68      "  ret void\n"
     69      "}\n"
     70      "define void @a3() {\n"
     71      "entry:\n"
     72      "  call void @a1()\n"
     73      "  ret void\n"
     74      "}\n"
     75      "define void @b1() {\n"
     76      "entry:\n"
     77      "  call void @b2()\n"
     78      "  call void @d3()\n"
     79      "  ret void\n"
     80      "}\n"
     81      "define void @b2() {\n"
     82      "entry:\n"
     83      "  call void @b3()\n"
     84      "  ret void\n"
     85      "}\n"
     86      "define void @b3() {\n"
     87      "entry:\n"
     88      "  call void @b1()\n"
     89      "  ret void\n"
     90      "}\n"
     91      "define void @c1() {\n"
     92      "entry:\n"
     93      "  call void @c2()\n"
     94      "  call void @d2()\n"
     95      "  ret void\n"
     96      "}\n"
     97      "define void @c2() {\n"
     98      "entry:\n"
     99      "  call void @c3()\n"
    100      "  ret void\n"
    101      "}\n"
    102      "define void @c3() {\n"
    103      "entry:\n"
    104      "  call void @c1()\n"
    105      "  ret void\n"
    106      "}\n"
    107      "define void @d1() {\n"
    108      "entry:\n"
    109      "  call void @d2()\n"
    110      "  ret void\n"
    111      "}\n"
    112      "define void @d2() {\n"
    113      "entry:\n"
    114      "  call void @d3()\n"
    115      "  ret void\n"
    116      "}\n"
    117      "define void @d3() {\n"
    118      "entry:\n"
    119      "  call void @d1()\n"
    120      "  ret void\n"
    121      "}\n";
    122 
    123 TEST(LazyCallGraphTest, BasicGraphFormation) {
    124   std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
    125   LazyCallGraph CG(*M);
    126 
    127   // The order of the entry nodes should be stable w.r.t. the source order of
    128   // the IR, and everything in our module is an entry node, so just directly
    129   // build variables for each node.
    130   auto I = CG.begin();
    131   LazyCallGraph::Node &A1 = *I++;
    132   EXPECT_EQ("a1", A1.getFunction().getName());
    133   LazyCallGraph::Node &A2 = *I++;
    134   EXPECT_EQ("a2", A2.getFunction().getName());
    135   LazyCallGraph::Node &A3 = *I++;
    136   EXPECT_EQ("a3", A3.getFunction().getName());
    137   LazyCallGraph::Node &B1 = *I++;
    138   EXPECT_EQ("b1", B1.getFunction().getName());
    139   LazyCallGraph::Node &B2 = *I++;
    140   EXPECT_EQ("b2", B2.getFunction().getName());
    141   LazyCallGraph::Node &B3 = *I++;
    142   EXPECT_EQ("b3", B3.getFunction().getName());
    143   LazyCallGraph::Node &C1 = *I++;
    144   EXPECT_EQ("c1", C1.getFunction().getName());
    145   LazyCallGraph::Node &C2 = *I++;
    146   EXPECT_EQ("c2", C2.getFunction().getName());
    147   LazyCallGraph::Node &C3 = *I++;
    148   EXPECT_EQ("c3", C3.getFunction().getName());
    149   LazyCallGraph::Node &D1 = *I++;
    150   EXPECT_EQ("d1", D1.getFunction().getName());
    151   LazyCallGraph::Node &D2 = *I++;
    152   EXPECT_EQ("d2", D2.getFunction().getName());
    153   LazyCallGraph::Node &D3 = *I++;
    154   EXPECT_EQ("d3", D3.getFunction().getName());
    155   EXPECT_EQ(CG.end(), I);
    156 
    157   // Build vectors and sort them for the rest of the assertions to make them
    158   // independent of order.
    159   std::vector<std::string> Nodes;
    160 
    161   for (LazyCallGraph::Node &N : A1)
    162     Nodes.push_back(N.getFunction().getName());
    163   std::sort(Nodes.begin(), Nodes.end());
    164   EXPECT_EQ("a2", Nodes[0]);
    165   EXPECT_EQ("b2", Nodes[1]);
    166   EXPECT_EQ("c3", Nodes[2]);
    167   Nodes.clear();
    168 
    169   EXPECT_EQ(A2.end(), std::next(A2.begin()));
    170   EXPECT_EQ("a3", A2.begin()->getFunction().getName());
    171   EXPECT_EQ(A3.end(), std::next(A3.begin()));
    172   EXPECT_EQ("a1", A3.begin()->getFunction().getName());
    173 
    174   for (LazyCallGraph::Node &N : B1)
    175     Nodes.push_back(N.getFunction().getName());
    176   std::sort(Nodes.begin(), Nodes.end());
    177   EXPECT_EQ("b2", Nodes[0]);
    178   EXPECT_EQ("d3", Nodes[1]);
    179   Nodes.clear();
    180 
    181   EXPECT_EQ(B2.end(), std::next(B2.begin()));
    182   EXPECT_EQ("b3", B2.begin()->getFunction().getName());
    183   EXPECT_EQ(B3.end(), std::next(B3.begin()));
    184   EXPECT_EQ("b1", B3.begin()->getFunction().getName());
    185 
    186   for (LazyCallGraph::Node &N : C1)
    187     Nodes.push_back(N.getFunction().getName());
    188   std::sort(Nodes.begin(), Nodes.end());
    189   EXPECT_EQ("c2", Nodes[0]);
    190   EXPECT_EQ("d2", Nodes[1]);
    191   Nodes.clear();
    192 
    193   EXPECT_EQ(C2.end(), std::next(C2.begin()));
    194   EXPECT_EQ("c3", C2.begin()->getFunction().getName());
    195   EXPECT_EQ(C3.end(), std::next(C3.begin()));
    196   EXPECT_EQ("c1", C3.begin()->getFunction().getName());
    197 
    198   EXPECT_EQ(D1.end(), std::next(D1.begin()));
    199   EXPECT_EQ("d2", D1.begin()->getFunction().getName());
    200   EXPECT_EQ(D2.end(), std::next(D2.begin()));
    201   EXPECT_EQ("d3", D2.begin()->getFunction().getName());
    202   EXPECT_EQ(D3.end(), std::next(D3.begin()));
    203   EXPECT_EQ("d1", D3.begin()->getFunction().getName());
    204 
    205   // Now lets look at the SCCs.
    206   auto SCCI = CG.postorder_scc_begin();
    207 
    208   LazyCallGraph::SCC &D = *SCCI++;
    209   for (LazyCallGraph::Node *N : D)
    210     Nodes.push_back(N->getFunction().getName());
    211   std::sort(Nodes.begin(), Nodes.end());
    212   EXPECT_EQ(3u, Nodes.size());
    213   EXPECT_EQ("d1", Nodes[0]);
    214   EXPECT_EQ("d2", Nodes[1]);
    215   EXPECT_EQ("d3", Nodes[2]);
    216   Nodes.clear();
    217   EXPECT_FALSE(D.isParentOf(D));
    218   EXPECT_FALSE(D.isChildOf(D));
    219   EXPECT_FALSE(D.isAncestorOf(D));
    220   EXPECT_FALSE(D.isDescendantOf(D));
    221 
    222   LazyCallGraph::SCC &C = *SCCI++;
    223   for (LazyCallGraph::Node *N : C)
    224     Nodes.push_back(N->getFunction().getName());
    225   std::sort(Nodes.begin(), Nodes.end());
    226   EXPECT_EQ(3u, Nodes.size());
    227   EXPECT_EQ("c1", Nodes[0]);
    228   EXPECT_EQ("c2", Nodes[1]);
    229   EXPECT_EQ("c3", Nodes[2]);
    230   Nodes.clear();
    231   EXPECT_TRUE(C.isParentOf(D));
    232   EXPECT_FALSE(C.isChildOf(D));
    233   EXPECT_TRUE(C.isAncestorOf(D));
    234   EXPECT_FALSE(C.isDescendantOf(D));
    235 
    236   LazyCallGraph::SCC &B = *SCCI++;
    237   for (LazyCallGraph::Node *N : B)
    238     Nodes.push_back(N->getFunction().getName());
    239   std::sort(Nodes.begin(), Nodes.end());
    240   EXPECT_EQ(3u, Nodes.size());
    241   EXPECT_EQ("b1", Nodes[0]);
    242   EXPECT_EQ("b2", Nodes[1]);
    243   EXPECT_EQ("b3", Nodes[2]);
    244   Nodes.clear();
    245   EXPECT_TRUE(B.isParentOf(D));
    246   EXPECT_FALSE(B.isChildOf(D));
    247   EXPECT_TRUE(B.isAncestorOf(D));
    248   EXPECT_FALSE(B.isDescendantOf(D));
    249   EXPECT_FALSE(B.isAncestorOf(C));
    250   EXPECT_FALSE(C.isAncestorOf(B));
    251 
    252   LazyCallGraph::SCC &A = *SCCI++;
    253   for (LazyCallGraph::Node *N : A)
    254     Nodes.push_back(N->getFunction().getName());
    255   std::sort(Nodes.begin(), Nodes.end());
    256   EXPECT_EQ(3u, Nodes.size());
    257   EXPECT_EQ("a1", Nodes[0]);
    258   EXPECT_EQ("a2", Nodes[1]);
    259   EXPECT_EQ("a3", Nodes[2]);
    260   Nodes.clear();
    261   EXPECT_TRUE(A.isParentOf(B));
    262   EXPECT_TRUE(A.isParentOf(C));
    263   EXPECT_FALSE(A.isParentOf(D));
    264   EXPECT_TRUE(A.isAncestorOf(B));
    265   EXPECT_TRUE(A.isAncestorOf(C));
    266   EXPECT_TRUE(A.isAncestorOf(D));
    267 
    268   EXPECT_EQ(CG.postorder_scc_end(), SCCI);
    269 }
    270 
    271 static Function &lookupFunction(Module &M, StringRef Name) {
    272   for (Function &F : M)
    273     if (F.getName() == Name)
    274       return F;
    275   report_fatal_error("Couldn't find function!");
    276 }
    277 
    278 TEST(LazyCallGraphTest, BasicGraphMutation) {
    279   std::unique_ptr<Module> M = parseAssembly(
    280       "define void @a() {\n"
    281       "entry:\n"
    282       "  call void @b()\n"
    283       "  call void @c()\n"
    284       "  ret void\n"
    285       "}\n"
    286       "define void @b() {\n"
    287       "entry:\n"
    288       "  ret void\n"
    289       "}\n"
    290       "define void @c() {\n"
    291       "entry:\n"
    292       "  ret void\n"
    293       "}\n");
    294   LazyCallGraph CG(*M);
    295 
    296   LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
    297   LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
    298   EXPECT_EQ(2, std::distance(A.begin(), A.end()));
    299   EXPECT_EQ(0, std::distance(B.begin(), B.end()));
    300 
    301   CG.insertEdge(B, lookupFunction(*M, "c"));
    302   EXPECT_EQ(1, std::distance(B.begin(), B.end()));
    303   LazyCallGraph::Node &C = *B.begin();
    304   EXPECT_EQ(0, std::distance(C.begin(), C.end()));
    305 
    306   CG.insertEdge(C, B.getFunction());
    307   EXPECT_EQ(1, std::distance(C.begin(), C.end()));
    308   EXPECT_EQ(&B, &*C.begin());
    309 
    310   CG.insertEdge(C, C.getFunction());
    311   EXPECT_EQ(2, std::distance(C.begin(), C.end()));
    312   EXPECT_EQ(&B, &*C.begin());
    313   EXPECT_EQ(&C, &*std::next(C.begin()));
    314 
    315   CG.removeEdge(C, B.getFunction());
    316   EXPECT_EQ(1, std::distance(C.begin(), C.end()));
    317   EXPECT_EQ(&C, &*C.begin());
    318 
    319   CG.removeEdge(C, C.getFunction());
    320   EXPECT_EQ(0, std::distance(C.begin(), C.end()));
    321 
    322   CG.removeEdge(B, C.getFunction());
    323   EXPECT_EQ(0, std::distance(B.begin(), B.end()));
    324 }
    325 
    326 TEST(LazyCallGraphTest, MultiArmSCC) {
    327   // Two interlocking cycles. The really useful thing about this SCC is that it
    328   // will require Tarjan's DFS to backtrack and finish processing all of the
    329   // children of each node in the SCC.
    330   std::unique_ptr<Module> M = parseAssembly(
    331       "define void @a() {\n"
    332       "entry:\n"
    333       "  call void @b()\n"
    334       "  call void @d()\n"
    335       "  ret void\n"
    336       "}\n"
    337       "define void @b() {\n"
    338       "entry:\n"
    339       "  call void @c()\n"
    340       "  ret void\n"
    341       "}\n"
    342       "define void @c() {\n"
    343       "entry:\n"
    344       "  call void @a()\n"
    345       "  ret void\n"
    346       "}\n"
    347       "define void @d() {\n"
    348       "entry:\n"
    349       "  call void @e()\n"
    350       "  ret void\n"
    351       "}\n"
    352       "define void @e() {\n"
    353       "entry:\n"
    354       "  call void @a()\n"
    355       "  ret void\n"
    356       "}\n");
    357   LazyCallGraph CG(*M);
    358 
    359   // Force the graph to be fully expanded.
    360   auto SCCI = CG.postorder_scc_begin();
    361   LazyCallGraph::SCC &SCC = *SCCI++;
    362   EXPECT_EQ(CG.postorder_scc_end(), SCCI);
    363 
    364   LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
    365   LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
    366   LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
    367   LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
    368   LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
    369   EXPECT_EQ(&SCC, CG.lookupSCC(A));
    370   EXPECT_EQ(&SCC, CG.lookupSCC(B));
    371   EXPECT_EQ(&SCC, CG.lookupSCC(C));
    372   EXPECT_EQ(&SCC, CG.lookupSCC(D));
    373   EXPECT_EQ(&SCC, CG.lookupSCC(E));
    374 }
    375 
    376 TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) {
    377   std::unique_ptr<Module> M = parseAssembly(
    378       "define void @a() {\n"
    379       "entry:\n"
    380       "  call void @b()\n"
    381       "  call void @c()\n"
    382       "  ret void\n"
    383       "}\n"
    384       "define void @b() {\n"
    385       "entry:\n"
    386       "  call void @d()\n"
    387       "  ret void\n"
    388       "}\n"
    389       "define void @c() {\n"
    390       "entry:\n"
    391       "  call void @d()\n"
    392       "  ret void\n"
    393       "}\n"
    394       "define void @d() {\n"
    395       "entry:\n"
    396       "  ret void\n"
    397       "}\n");
    398   LazyCallGraph CG(*M);
    399 
    400   // Force the graph to be fully expanded.
    401   for (LazyCallGraph::SCC &C : CG.postorder_sccs())
    402     (void)C;
    403 
    404   LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
    405   LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
    406   LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
    407   LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
    408   LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
    409   LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
    410   LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
    411   LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
    412   EXPECT_TRUE(AC.isAncestorOf(BC));
    413   EXPECT_TRUE(AC.isAncestorOf(CC));
    414   EXPECT_TRUE(AC.isAncestorOf(DC));
    415   EXPECT_TRUE(DC.isDescendantOf(AC));
    416   EXPECT_TRUE(DC.isDescendantOf(BC));
    417   EXPECT_TRUE(DC.isDescendantOf(CC));
    418 
    419   EXPECT_EQ(2, std::distance(A.begin(), A.end()));
    420   AC.insertOutgoingEdge(A, D);
    421   EXPECT_EQ(3, std::distance(A.begin(), A.end()));
    422   EXPECT_TRUE(AC.isParentOf(DC));
    423   EXPECT_EQ(&AC, CG.lookupSCC(A));
    424   EXPECT_EQ(&BC, CG.lookupSCC(B));
    425   EXPECT_EQ(&CC, CG.lookupSCC(C));
    426   EXPECT_EQ(&DC, CG.lookupSCC(D));
    427 }
    428 
    429 TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) {
    430   // We want to ensure we can add edges even across complex diamond graphs, so
    431   // we use the diamond of triangles graph defined above. The ascii diagram is
    432   // repeated here for easy reference.
    433   //
    434   //         d1       |
    435   //        /  \      |
    436   //       d3--d2     |
    437   //      /     \     |
    438   //     b1     c1    |
    439   //   /  \    /  \   |
    440   //  b3--b2  c3--c2  |
    441   //       \  /       |
    442   //        a1        |
    443   //       /  \       |
    444   //      a3--a2      |
    445   //
    446   std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
    447   LazyCallGraph CG(*M);
    448 
    449   // Force the graph to be fully expanded.
    450   for (LazyCallGraph::SCC &C : CG.postorder_sccs())
    451     (void)C;
    452 
    453   LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
    454   LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
    455   LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
    456   LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
    457   LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
    458   LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
    459   LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
    460   LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
    461   LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
    462   LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
    463   LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
    464   LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
    465   LazyCallGraph::SCC &AC = *CG.lookupSCC(A1);
    466   LazyCallGraph::SCC &BC = *CG.lookupSCC(B1);
    467   LazyCallGraph::SCC &CC = *CG.lookupSCC(C1);
    468   LazyCallGraph::SCC &DC = *CG.lookupSCC(D1);
    469   ASSERT_EQ(&AC, CG.lookupSCC(A2));
    470   ASSERT_EQ(&AC, CG.lookupSCC(A3));
    471   ASSERT_EQ(&BC, CG.lookupSCC(B2));
    472   ASSERT_EQ(&BC, CG.lookupSCC(B3));
    473   ASSERT_EQ(&CC, CG.lookupSCC(C2));
    474   ASSERT_EQ(&CC, CG.lookupSCC(C3));
    475   ASSERT_EQ(&DC, CG.lookupSCC(D2));
    476   ASSERT_EQ(&DC, CG.lookupSCC(D3));
    477   ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
    478 
    479   // Add an edge to make the graph:
    480   //
    481   //         d1         |
    482   //        /  \        |
    483   //       d3--d2---.   |
    484   //      /     \    |  |
    485   //     b1     c1   |  |
    486   //   /  \    /  \ /   |
    487   //  b3--b2  c3--c2    |
    488   //       \  /         |
    489   //        a1          |
    490   //       /  \         |
    491   //      a3--a2        |
    492   CC.insertIncomingEdge(D2, C2);
    493   // Make sure we connected the nodes.
    494   EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
    495 
    496   // Make sure we have the correct nodes in the SCC sets.
    497   EXPECT_EQ(&AC, CG.lookupSCC(A1));
    498   EXPECT_EQ(&AC, CG.lookupSCC(A2));
    499   EXPECT_EQ(&AC, CG.lookupSCC(A3));
    500   EXPECT_EQ(&BC, CG.lookupSCC(B1));
    501   EXPECT_EQ(&BC, CG.lookupSCC(B2));
    502   EXPECT_EQ(&BC, CG.lookupSCC(B3));
    503   EXPECT_EQ(&CC, CG.lookupSCC(C1));
    504   EXPECT_EQ(&CC, CG.lookupSCC(C2));
    505   EXPECT_EQ(&CC, CG.lookupSCC(C3));
    506   EXPECT_EQ(&CC, CG.lookupSCC(D1));
    507   EXPECT_EQ(&CC, CG.lookupSCC(D2));
    508   EXPECT_EQ(&CC, CG.lookupSCC(D3));
    509 
    510   // And that ancestry tests have been updated.
    511   EXPECT_TRUE(AC.isParentOf(BC));
    512   EXPECT_TRUE(AC.isParentOf(CC));
    513   EXPECT_FALSE(AC.isAncestorOf(DC));
    514   EXPECT_FALSE(BC.isAncestorOf(DC));
    515   EXPECT_FALSE(CC.isAncestorOf(DC));
    516 }
    517 
    518 TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) {
    519   // This is the same fundamental test as the previous, but we perform it
    520   // having only partially walked the SCCs of the graph.
    521   std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
    522   LazyCallGraph CG(*M);
    523 
    524   // Walk the SCCs until we find the one containing 'c1'.
    525   auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end();
    526   ASSERT_NE(SCCI, SCCE);
    527   LazyCallGraph::SCC &DC = *SCCI;
    528   ASSERT_NE(&DC, nullptr);
    529   ++SCCI;
    530   ASSERT_NE(SCCI, SCCE);
    531   LazyCallGraph::SCC &CC = *SCCI;
    532   ASSERT_NE(&CC, nullptr);
    533 
    534   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
    535   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
    536   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
    537   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
    538   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
    539   ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
    540   LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
    541   LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
    542   LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
    543   LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
    544   LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
    545   LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
    546   ASSERT_EQ(&CC, CG.lookupSCC(C1));
    547   ASSERT_EQ(&CC, CG.lookupSCC(C2));
    548   ASSERT_EQ(&CC, CG.lookupSCC(C3));
    549   ASSERT_EQ(&DC, CG.lookupSCC(D1));
    550   ASSERT_EQ(&DC, CG.lookupSCC(D2));
    551   ASSERT_EQ(&DC, CG.lookupSCC(D3));
    552   ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
    553 
    554   CC.insertIncomingEdge(D2, C2);
    555   EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
    556 
    557   // Make sure we have the correct nodes in the SCC sets.
    558   EXPECT_EQ(&CC, CG.lookupSCC(C1));
    559   EXPECT_EQ(&CC, CG.lookupSCC(C2));
    560   EXPECT_EQ(&CC, CG.lookupSCC(C3));
    561   EXPECT_EQ(&CC, CG.lookupSCC(D1));
    562   EXPECT_EQ(&CC, CG.lookupSCC(D2));
    563   EXPECT_EQ(&CC, CG.lookupSCC(D3));
    564 
    565   // Check that we can form the last two SCCs now in a coherent way.
    566   ++SCCI;
    567   EXPECT_NE(SCCI, SCCE);
    568   LazyCallGraph::SCC &BC = *SCCI;
    569   EXPECT_NE(&BC, nullptr);
    570   EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1"))));
    571   EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2"))));
    572   EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3"))));
    573   ++SCCI;
    574   EXPECT_NE(SCCI, SCCE);
    575   LazyCallGraph::SCC &AC = *SCCI;
    576   EXPECT_NE(&AC, nullptr);
    577   EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1"))));
    578   EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2"))));
    579   EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3"))));
    580   ++SCCI;
    581   EXPECT_EQ(SCCI, SCCE);
    582 }
    583 
    584 TEST(LazyCallGraphTest, InterSCCEdgeRemoval) {
    585   std::unique_ptr<Module> M = parseAssembly(
    586       "define void @a() {\n"
    587       "entry:\n"
    588       "  call void @b()\n"
    589       "  ret void\n"
    590       "}\n"
    591       "define void @b() {\n"
    592       "entry:\n"
    593       "  ret void\n"
    594       "}\n");
    595   LazyCallGraph CG(*M);
    596 
    597   // Force the graph to be fully expanded.
    598   for (LazyCallGraph::SCC &C : CG.postorder_sccs())
    599     (void)C;
    600 
    601   LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
    602   LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
    603   LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
    604   LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
    605 
    606   EXPECT_EQ("b", A.begin()->getFunction().getName());
    607   EXPECT_EQ(B.end(), B.begin());
    608   EXPECT_EQ(&AC, &*BC.parent_begin());
    609 
    610   AC.removeInterSCCEdge(A, B);
    611 
    612   EXPECT_EQ(A.end(), A.begin());
    613   EXPECT_EQ(B.end(), B.begin());
    614   EXPECT_EQ(BC.parent_end(), BC.parent_begin());
    615 }
    616 
    617 TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) {
    618   std::unique_ptr<Module> M1 = parseAssembly(
    619       "define void @a() {\n"
    620       "entry:\n"
    621       "  call void @b()\n"
    622       "  ret void\n"
    623       "}\n"
    624       "define void @b() {\n"
    625       "entry:\n"
    626       "  call void @c()\n"
    627       "  ret void\n"
    628       "}\n"
    629       "define void @c() {\n"
    630       "entry:\n"
    631       "  call void @a()\n"
    632       "  ret void\n"
    633       "}\n");
    634   LazyCallGraph CG1(*M1);
    635 
    636   // Force the graph to be fully expanded.
    637   auto SCCI = CG1.postorder_scc_begin();
    638   LazyCallGraph::SCC &SCC = *SCCI++;
    639   EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
    640 
    641   LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
    642   LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
    643   LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
    644   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    645   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
    646   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
    647 
    648   // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs.
    649   SCC.insertIntraSCCEdge(A, C);
    650   EXPECT_EQ(2, std::distance(A.begin(), A.end()));
    651   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    652   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
    653   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
    654 
    655   // Insert a self edge from 'a' back to 'a'.
    656   SCC.insertIntraSCCEdge(A, A);
    657   EXPECT_EQ(3, std::distance(A.begin(), A.end()));
    658   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    659   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
    660   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
    661 }
    662 
    663 TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) {
    664   // A nice fully connected (including self-edges) SCC.
    665   std::unique_ptr<Module> M1 = parseAssembly(
    666       "define void @a() {\n"
    667       "entry:\n"
    668       "  call void @a()\n"
    669       "  call void @b()\n"
    670       "  call void @c()\n"
    671       "  ret void\n"
    672       "}\n"
    673       "define void @b() {\n"
    674       "entry:\n"
    675       "  call void @a()\n"
    676       "  call void @b()\n"
    677       "  call void @c()\n"
    678       "  ret void\n"
    679       "}\n"
    680       "define void @c() {\n"
    681       "entry:\n"
    682       "  call void @a()\n"
    683       "  call void @b()\n"
    684       "  call void @c()\n"
    685       "  ret void\n"
    686       "}\n");
    687   LazyCallGraph CG1(*M1);
    688 
    689   // Force the graph to be fully expanded.
    690   auto SCCI = CG1.postorder_scc_begin();
    691   LazyCallGraph::SCC &SCC = *SCCI++;
    692   EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
    693 
    694   LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
    695   LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
    696   LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
    697   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    698   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
    699   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
    700 
    701   // Remove the edge from b -> a, which should leave the 3 functions still in
    702   // a single connected component because of a -> b -> c -> a.
    703   SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A);
    704   EXPECT_EQ(0u, NewSCCs.size());
    705   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    706   EXPECT_EQ(&SCC, CG1.lookupSCC(B));
    707   EXPECT_EQ(&SCC, CG1.lookupSCC(C));
    708 
    709   // Remove the edge from c -> a, which should leave 'a' in the original SCC
    710   // and form a new SCC for 'b' and 'c'.
    711   NewSCCs = SCC.removeIntraSCCEdge(C, A);
    712   EXPECT_EQ(1u, NewSCCs.size());
    713   EXPECT_EQ(&SCC, CG1.lookupSCC(A));
    714   EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end()));
    715   LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B);
    716   EXPECT_EQ(SCC2, CG1.lookupSCC(C));
    717   EXPECT_EQ(SCC2, NewSCCs[0]);
    718 }
    719 
    720 }
    721