<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=http://email.email.llvm.org/c/eJylVU2P2jAQ_TXhMmoENinLIQfYVT8kttpD1fbqJANx69hZ2wF2f33HTgIsRe2hyCRx_Pzmeb5SmOolv1dC7xL2YbP59ghbIZUDb6DCvbS-E0q-Ihxq1CDKEp2TegcCdsoUQsFeWCkKhSl8raUDV5tOVVAgtIaQtACELxF8jScs1MIRwy9tDhr8SxtWhYdSaG182FvWpAerFB6llg1ZwaNoWoUJXyXTh2Q6Xt9PhxGnztuu9PADksW6fwMwnACk9rA1JmF3CVtCabTzAQYWfWc1zFnC1_TiYdwX8IWwA_4CeSJ5syE88MEoHj0S8AccT6-i9TPXaIQ8TgOe0G6NbRw5QCk4SF9DGQPCR6uOBPYLu7Icdw-CjulJ58nelYEvxg8u9iFGMQyk6Jo7GqU960srPcXJ1uXxz0e_FY2erbWm6ihpzpF7i9qObGTqX7-EcUjm03HLILD_NWb_HO7HuJhZ2QYIu4cwEcc_wKonnB8HDFbyLeZn0z73mNVASSwUvr-J-7r6vLlfbTY3T_qZEnysjRgGohWxYKgIipfo8-iIm7uvZFO-Drqvz0aRuknQXx-wCalvhZdGA43SNK1UaKnCWmUs2hCJ2vs2RizGfmeqwiifGhtaxCv9-VN2_Mg_Pn2_pD4nWR_5yqCDtk_tWP0X7aQ3H1tKWLlqJUObAfKRbBqKjPCoXqiUYz9J4ZM54J4kS2pIemwNoOSvwbGHWpY1bKV1IcefO2lJidSKegnp0uZPJbVoW9QBFPXENmhaL5sR0MoWaT-mkyrn1ZIvxUR0vjY2fxT-FdeTzqr8ym1UUl2RkoNpotR-vL2jkviJpaepdK6j0mAfMp4tZ5M6rzjPxIKVi6rItgUT2_mMnqv3s1nJURR3EyUKVC5PsnXCWCTlq0uhRMaS7GHy_2JkzqaMxnQ-u8sWjKfiblFtGV9ixWczli2oErGhT0UaeEJyTGweKYtu52hRSefdeVHQ12CnEaN2UuilV5h_uREMSpjrjJhEcXlU9hsDfQPB>53591</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            No devirtualization for global variable
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:optimizations
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          MatzeB
      </td>
    </tr>
</table>

<pre>
    Clang/LLVM fails to devirtualize when accessing a global variable. This should be possible since the variable has a known type that cannot be changed. Minimal example:

```
struct X {
  virtual int foo() const { return 42; }
  int bar() { return foo(); }
};
extern X x;
int f() {
  // Performs call with clang; returns 42 with gcc
  return x.bar();

  // Note that this variant returns 42 with clang + gcc
  //return x.foo();
}
```
clang produces:
```
f():                                  # @f()
        movq    x(%rip), %rax
        movl    $x, %edi
        jmpq    *(%rax)                         # TAILCALL
```
It could be this (as shown by gcc):
```
    movl    $42, %eax
        ret
```

Demonstration on compiler explorer: https://godbolt.org/z/3P5xG3GPW

Note that clang does perform the devirtualization when the global variable access is immediately visible. However in an example like this which first requires inlining no devirtualization happens in the LLVM optimization pipeline.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyFVU1z2jAQ_TXmslMPkXCAgw-QTD9mSCeHTturbC9YrSw5kgwkv74r2QZCmdYjDLbevn27q10KU73mD0roXcI-bjbfn2ArpHLgDVS4l9Z3Qsk3hEONGkRZonNS70DATplCKNgLK0WhMIVvtXTgatOpCgqE1hCSNoDwJYKv8YSFWjhi-K3NQYN_bcOu8FAKrY0PtmVNerBK4Ulq2ZAXPIqmVZjwVTJ9TKbj_X46rPjovO1KDz8hma_7NwBDBCC1h60xCVskbAml0c4HGFj0ndUwYwlf04vH0S7gC2EH_AXyRPLOIPzgg1M8eiTgTzieXkXvZ67RCWWcFjyj3RrbOEqAUnCQvoYyFoSPXh0J7Dd2ZTlaD4KO6Unnyd-Vg6_GDyn2oUaxDKTomjs6JZv1pZee4uTrMvxz6Leq0bO11lQdHZpz5d6jtiMbufrflTAOyWw6mgwC-6sx-5fwfYybmZVtgLAHCA_i-BdY9YSz44DBSr7H_Gralx6zGiiJhcr3L3HfVl82D6vN5makX-iAj70Ry0C0IjYMNUHxGnMeE3HT-ko2nddB93VsVKmbBP39EZtw9K3w0migVZqmlQotdVirjEUbKlF738aKxdrvTFUY5VNjw4h4ow9_zo6f-KfnH5fU50PWV74y6KDtj3bs_otx0ruPIyXsXI2SYcwA5Ug2DVVGeFSv1MpxnqTw2RxwT5IlDSQ9jgZQ8veQ2EMtyxq20rpwxl86aUmJ1IpmCenS5m8ltWhb1AEU9cQxaFovmxHQyhbJHtNJlfNqyZdi4qVXmH-9wUYRX4c06azKr9JKLdcVKRWAHpTaj18fqGV-YenpUTrXUeuwjxnPlneTOi_mdE23_J4ksGLJ2Iyz2fKeL-YZ394vZhMlClQuT7J1wlgk5avLQIiMJdnjROZsymhNZ3eLbM54Khbzasv4Eit-d8eyOfUZNvRHkAaSUPqJzaO6ots52lTSeXfeFDTrdxoxeiZ-0fna2PxJ-DdcT2IceQziD-vx7FQ">