<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/56001>56001</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            SimplifyCFG with hoisting and sinking enabled in pre-link prevents link-time WholeProgramDevirt from recognizing virtual call sites
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    The 'whole program devirtualzation' (WPD, WholeProgramDevirt, `-fwhole-program-vtables`) family of link-time optimizations recognizes virtual call sites to optimize by looking for specific sequences of instructions (for example, see https://github.com/llvm/llvm-project/blob/186a13f647acac623898bcffa4b966624d2358ba/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp#L1891 and https://github.com/llvm/llvm-project/blob/09c2b7c35af8c4bad39f03e9f60df8bd07323028/llvm/lib/Analysis/TypeMetadataUtils.cpp#L74). In LLVM 13 and later, with instruction hoisting and sinking enabled early in https://github.com/llvm/llvm-project/commit/ed9df5bd2f50b2199204cc6e50910ba52dd5e93e, and the ability to sink/hoist indirect calls implemented in https://github.com/llvm/llvm-project/commit/d16d820c2e6400aa2242efcedbfa824fbfa2fc09, those sequences can be broken during pre-link SimplifyCFG, preventing the link-time WPD pass from doing its job.

Attached is a LIT test case ([do-not-break-vcall-test-assume-sequences.ll.txt](https://github.com/llvm/llvm-project/files/8886988/do-not-break-vcall-test-assume-sequences.ll.txt)) demonstrating the issue, based on the following real C++ code, where `GetClassID` is a method viable to be optimized via virtual constant propagation, one of the WPD optimizations:

```
namespace
{
    static const char* GetOperatorID(NodeOperator * op)
    {
#ifdef NODE_USE_OBJECTNAMES
        return op->GetDebugClassID(true);
#else
        return op->GetClassID();
#endif
    }
}
 
void NodeOperator::Initialize(InitType initType, InitInfo& initInfo)
{
    super::Initialize(initType, initInfo);
 
    if(NodeManager::GetInstance().GetGroupOperatorsInProfilingInfo())
    {
        m_ProfilerNameActivate = StringFormat("Activate %d", GetClassID());
        m_ProfilerNameDeactivate = StringFormat("Deactivate %d", GetClassID());
        m_ProfilerNameExecute = StringFormat("Execute %d", GetClassID());
    }
    else
    {
        m_ProfilerNameActivate = StringFormat("Activate %d", GetOperatorID(this));
        m_ProfilerNameDeactivate = StringFormat("Deactivate %d", GetOperatorID(this));
        m_ProfilerNameExecute = StringFormat("Execute %d", GetOperatorID(this));
    }
}

```

If `NODE_USE_OBJECTNAMES` is not defined, Clang generates identical code for both branches, except for the type.test/assume intrinsic function calls in one of the branches having the `nounwind` attribute. I haven't investigated why it's like that - the generated IR is nevertheless legal. The SimplifyCFG pass then sinks a part of the 3rd virtual function call in both branches, stopping at the `assume` intrinsic function call, preventing WPD from devirtualizing it.

It may be possible to either make Clang not apply `nounwind` to intrinsics (all of them, or the specific ones involved here), or make SimplifyCFG ignore it when determining where to stop hoisting/sinking, but the attached workaround (
[14.diff.txt](https://github.com/llvm/llvm-project/files/8886990/14.diff.txt)
) only disables pre-link hoisting/sinking when doing LTO, based on the possibly mistaken assumption that it - SimplifyCFG with hoisting/sinking enabled - is going to happen again during link-time.

The affected codebase is heavily reliant on WPD being able to do as much work as possible, and an investigation of performance issues after upgrade to LLVM 14 is how the issue was discovered.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1V11z2sgS_TX4ZQpKjEBIDzzYxk5xy4lTG-fuY2qkacHEkkYrjSDOr7-nRwhwzG5tsncpCiTNqPv095nU6pfl05bESC72W1uQqBu7aVQpNO1M4zpVfFfO2Arr2BP__nE1krfid976sd-58hv56SgKxrmXMj5IGe-cSgtqsTKSichVaYoXYXNRmOp57ExJwtb4M72SVjSU2U1lvlMrDupFpopCtMbhkbPDdhLpiyisfTbVRuS2EW1NmclNJlr6o6Mqw26oMVXrmi7rZQM-76RvqqwLYsAtkdg6V7ej8Hok7_HdGLft0klmS9wUxW74Y4O-UgYz79PCpvibxpGahnk0W6hMZZEM4yROszxXszSJokjOtAzncarO5Bh-76lRVQscZYub9cdH_L715iSr65EMH6ZxMhWq0r-MMkgymS6ycK7yOJulSodJHoSU5FGg8zjVwSKUYSDjH1FeV6p4aQ1jfHqp6T05pZVTn50p2gHcYoaYTsS6Eg8P_30vpqFHWihHDTt3D5DnARBba1rH8eJtLRKAr6niBNGCVIPMMNXPW4q10vAF6UTn81TLfB6kcpokMphlWUTzIJkGqZpLreeUhD7yDMEh7VVqCuNeOLMYEaR4lACiDXLR-exrheGMKalyQPqPMOpppGMZZJKiWRAoJeVMUp6RTnMVy1mOP5lnQcIY3da2dJbPmapEisRv7DNVQncN-69uaMzFJD4xRpO_3N6_45fxfAe8vIXtPNUbKljUqm1F3lhUueUdxrXiq00no2A1Cq7732vnVLZle1uhxMP6SaAC2R8tN4t4NL_RdlxZN04bUs_jHTtqzFvGEN6VND4CnxTFxH1zozlaR_zTrssN9w95H8dxlMScqD-rVybcezSVlpNRHX1isN8nQwqbtECG8tPcFoXd8x7IL8TtSN7gKzKr_d79lhriTveO3G0BlesVbnonlYSQaTQuTmlOqfTY3sg_PvU0hqIqx922VptDh70FBuK2xTg4Tq96IzvtLD7cUvuvv61USW2tMjqsLm76C4EPVDl0Rq9UZFuF8rwWwP9YE9xhmzUH5gMMHB4I3mBr9txRyFEiSt_kmnLx4XF19-Xzp7svjzf_ubt9-nD9_u7TaT9_GnJdU0HSeBTeQeGK0m4zeE3G6AzEOsKTZCpa-msZp9d_fBUlm5_jXQ2uOFyI_m9njRbn1rJjw-t1ZZxRBUIF0XzDfQ_F3l9wcPjhusrtSEb-eX-dXHJ4B9EXxJ5LO5cwWCFOImBKH5P3qlKbQRrsX_vMyah3wARP3jW2qwdj2nWFSYKiQQb34uO-AC5EcnBx-aV_hZoPyKJrdOsdmrgYhSvxyXGXuce4Us6LkqdlOde4Z1vehOXcpotKVqT-Ws35hn-i6O4bZd2fajmu_n0Vp3TC53W6_iuOfVWkbssj-V_176_p-xU3_x1Nb6v4Yvfrf9c5N-aLbalv0RgbmAO5qUgzBsQZbX5DFePAgDWaJ2bm-7MmTytTCxKTgrJhFLb8Dn3LqHZ-jbu0QzVPePpgLvXzB4XN9rdouHlX9cznQCKq8_4-CBVbtRsmEmBWtqswfTQjVg6SUjgOJIu3EbNw5iY7KDSYGpgq-y1YE7QvWsz4ZwDaKifGXtpgmBbr37z1YAQNFjBPsZk2qpgIpv5nzKFnBthTeTrEQ61WjRswh40-jrBXxrFtb1zVOlvXnu-5wbreRT4al730A3XhIdjzlOE0Yr73hOUVV1k7UaoXHre1bVtzmL4EckENVuCWPtQcf1XXIJo_eBq7j4D8QYFt6o0u_Vzuo308ZCCOHM-dLXZwL1MCn7t-o9d37lOzqSw4g3FMHkDcCAS5RPsHoJ5NMPmEr44EGbl0oMeenXS9-9RAyPa2eVbo-aCwXF69H-Y309kEAzD_f1GtJOBDzpnM46QDmbIVfKhN6w93Jw761oCDyZ5lPjw9vmFbh3i9iBJvKua1PkVqnxA-lw2n87k7_bnigqbhJDHmXN94jXDsFvFmqRtljpz5SIZfJRGXgspzuAJCuAEwUJa1JVQoIDZUGOZsQMZ5mZLP7UOyaQvkouyyrY8P3wy5OJw3QN9Ppcv2IcHQAvksyAO956MouRz5Iboap0HtRfenq5mHYvcn6ir2UIIgZBZ1TXpypZehTsJEXTnjClr-qdMuHsDgnmMcDxXYnh8b3pxR-8IcDuws6u2J_apriuVP52HvCFzMoyCYXm2XMpqHC1pQMk0XKtZaRbOIomwepVkYRQu6KlSKUbxEFWC8VLQfuL1EJVyZpQykDKKplGEog3iiFjj9BlGS6lDG-TwazQIqlSkmjGNim81Vs_SQwFZbLBZwW3taRIaipIm8OshXHWh_s_yqqq79Xl151UsP_X_0favV">