<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Cannot add mutually recursive functions into RefSCC"
   href="https://bugs.llvm.org/show_bug.cgi?id=47502">47502</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Cannot add mutually recursive functions into RefSCC
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>aeubanks@google.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>alina.sbirlea@gmail.com, htmldeveloper@gmail.com, johannes@jdoerfert.de, llvm-bugs@lists.llvm.org, modocache@gmail.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>When adding mutually recursive (ref-wise) functions to a CGSCC via
LazyCallGraph::addNewFunctionIntoRefSCC(), the following assert triggers:
Assertion failed: !lookup(F) && "node already exists", file
../../llvm/lib/Analysis/LazyCallGraph.cpp, line 1598

This is because addNewFunctionIntoRefSCC() calls createNode(), which populates
the edges for that node and creates nodes for any functions it references by
calling get(). Let's say we want to call addNewFunctionIntoRefSCC() on two
newly created and mutually recursive functions. After the first
addNewFunctionIntoRefSCC(), it has created two nodes, one for each of the newly
added functions. Then in the second call to addNewFunctionIntoRefSCC(), it
calls createNode() on the second function, but the node was already created via
a call to get() previously, so the assert triggers.

<a href="https://reviews.llvm.org/D72025">https://reviews.llvm.org/D72025</a> and <a href="https://reviews.llvm.org/D70927">https://reviews.llvm.org/D70927</a> introduced
addNewFunctionIntoSCC() and addNewFunctionIntoRefSCC().

Reproducible via unittests with the diff in CGSCCCPassManagerTest.cpp below:
```
@@ -1753,11 +1753,29 @@ TEST_F(CGSCCPassManagerTest, TestInsertionOfNewRefSCC)
{
                                            
Type::getInt8PtrTy(F.getContext()),
                                             "f.ref", &*F.begin()->begin());

+          // Create mutually recursive functions 'h1' and 'h2'.
+          auto *H1 = Function::Create(F.getFunctionType(), F.getLinkage(),
+                                      F.getAddressSpace(), "h1",
F.getParent());
+          auto *H2 = Function::Create(F.getFunctionType(), F.getLinkage(),
+                                      F.getAddressSpace(), "h2",
F.getParent());
+          BasicBlock *H1BB =
+              BasicBlock::Create(F.getParent()->getContext(), "entry", H1);
+          BasicBlock *H2BB =
+              BasicBlock::Create(F.getParent()->getContext(), "entry", H2);
+          (void)CallInst::Create(H2, {}, "", H1BB);
+          ReturnInst::Create(H1->getContext(), H1BB);
+          (void)CallInst::Create(H1, {}, "", H2BB);
+          ReturnInst::Create(H2->getContext(), H2BB);
+
+          CG.addNewFunctionIntoRefSCC(*H1, C.getOuterRefSCC());
+          CG.addNewFunctionIntoRefSCC(*H2, C.getOuterRefSCC());
+
+          F.getParent()->dump();
           ASSERT_NO_FATAL_FAILURE(
               updateCGAndAnalysisManagerForCGSCCPass(CG, C, N, AM, UR, FAM))
               << "Updating the call graph with a demoted, self-referential "
-                 "call edge 'f -> f', and a newly inserted ref edge 'f -> g',
"
-                 "caused a fatal failure";
+                 "call edge 'f -> f', a newly inserted ref edge 'f -> g', and
"
+                 "mutually recursive h1 <-> h2 caused a fatal failure";
         }
```

$ ./build/debug/obj/llvm/unittests/Analysis/AnalysisTests.exe
--gtest_filter='*TestInsertionOfNew*' --gtest_catch_exceptions=0
Note: Google Test filter = *TestInsertionOfNew*
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from CGSCCPassManagerTest
[ RUN      ] CGSCCPassManagerTest.TestInsertionOfNewRefSCC
Starting llvm::Module pass manager run.
Starting CGSCC pass manager run.
Assertion failed: !lookup(F) && "node already exists", file
../../llvm/lib/Analysis/LazyCallGraph.cpp, line 1598</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>