<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 - Function pointers not inlined and suboptimal assembly is generated"
   href="https://bugs.llvm.org/show_bug.cgi?id=34801">34801</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Function pointers not inlined and suboptimal assembly is generated
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </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>enhancement
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

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

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

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The following code 

enum class eShape { eSquare, eCircle, eShpere, eTetraeder };

static inline double eval_square(double r) { return 4 * r*r; }
static inline double eval_circle(double r) { return 3.1415 * r * r; }
static inline double eval_sphere(double r) { return 4 * 3.1415 * r * r; }
static inline double eval_tetraeder(double r) { return 24 * 1.73205 * r*r; }

double test_switch_table(eShape shape, double r) {
    using eval_t = double(*)(double);
    constexpr eval_t table[] = { 
        eval_square,
        eval_circle,
        eval_sphere,
        eval_tetraeder,
    };
    return table[static_cast<unsigned>(shape)](r);
}

Produces very long suboptimal assembly, that does not inline the eval_*
functions. 


generated code could be made much better by just rewriting the code in the
following way

double test_switch_native(eShape shape, double r) {
    switch(shape) {
    case eShape::eSquare:    return eval_square(r);
    case eShape::eCircle:    return eval_circle(r);
    case eShape::eShpere:    return eval_sphere(r);
    case eShape::eTetraeder: return eval_tetraeder(r);
    }
}

At -O2 such code produces a nice assembly with merged common `r*r` part:

test_switch_native(eShape, double):         # @test_switch_native(eShape,
double)
        movsxd  rax, edi
        movsd   xmm1, qword ptr [8*rax +
.Lswitch.table._Z18test_switch_native6eShaped] # xmm1 = mem[0],zero
        mulsd   xmm1, xmm0
        mulsd   xmm0, xmm1
        ret
.Lswitch.table._Z18test_switch_native6eShaped:
        .quad   4616189618054758400     # double 4
        .quad   4614256447914709615     # double 3.1415000000000002
        .quad   4623263647169450607     # double 12.566000000000001
        .quad   4631047162110439693     # double 41.569200000000002</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>