<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </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 --- - comdats cause uncalled linkonce_odr functions to be retained at -O0/-O1"
   href="http://llvm.org/bugs/show_bug.cgi?id=22285">22285</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>comdats cause uncalled linkonce_odr functions to be retained at -O0/-O1
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

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

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

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

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>Interprocedural Optimizations
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>david.majnemer@gmail.com
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>dblaikie@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu, rafael.espindola@gmail.com
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>$ cat inl.ll
  $f1 = comdat any
  define void @f2() {
  entry:
    call void @f1()
    ret void
  }

  define linkonce_odr void @f1() comdat {
  entry:
    ret void
  }
  $ opt -S -inline inl.ll -o - | grep define
  define void @f2() {
  define linkonce_odr void @f1() comdat {
  $ cat inl2.ll
  define void @f2() {
  entry:
    call void @f1()
    ret void
  }
  define linkonce_odr void @f1() {
  entry:
    ret void
  }
  $ opt inl2.ll -S -inline -o - | grep define
  define void @f2() {
  $

The problem seems to be at lib/Transforms/IPO/Inliner.cpp:678:
    // It is unsafe to drop a function with discardable linkage from a COMDAT
    // without also dropping the other members of the COMDAT.
    // The inliner doesn't visit non-function entities which are in COMDAT
    // groups so it is unsafe to do so *unless* the linkage is local.
    if (!F->hasLocalLinkage() && F->hasComdat())
      continue;

Which is correct, but very conservative. At higher optimization levels some
other pass (I'll check which one in a moment) must kick in and still manage to
cleanup these dead comdats.

Since a comdat doesn't refer to its members, it's not trivial to just ask "is
this a comdat with only one element" and then drop the function (& comdat)
anyway. Maybe it needs a separate pass specifically looking for comdats whos
elements are all unused linkonce_odr elements?</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>