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

    <tr>
        <th>Summary</th>
        <td>
            Hardening checks in a std::copy-like loop aren't hoisted out of the loop
        </td>
    </tr>

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

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

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

<pre>
    For some context, see https://github.com/llvm/llvm-project/pull/78876.

Playing around with a bounds-checked iterator, and `std::copy`, I found another missed optimization. `std::copy` is interesting because it iterates over both a source and destination range in parallel. It uses the source range to bound the loop, which means we have a precondition on the destination range.

Ideally this would be checked once, a la `dst.size() >= src.size()` and then the loop itself be check-free. But if we add safety checks to the individual iterator accesses, there will initially be checks inside the loop.

I tried several variations, but I could not get Clang to determine that the inner check is redundant with some outer one.
https://godbolt.org/z/aen9vYjzz

This is less bad than it sounds because `std::copy` is often specialized to `memmove`. (Though there we have a different problem, #78829.) But sometimes it is just the loop, and ideally patterns like this could be optimized, so that code using LLVM can add more safety checks with less worry about the impact on tight loops.

(CC @danakj)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVEFv40YP_TXjCxFDGie2dPBhN_sZX4At0MOiQI-UhraYjGaEIWXX_vXFjGM32baHXmzYEsnHx_ceivAhEG3N01fz9G2Bsw4xbR0e2XUUFl105-0uJpA4EvQxKP2hxj6DEMGgOolZfTF2Z-zuwDrM3bKPo7E774-3r4cpxVfq1djdNHtv7G7TNJv10lTfTPXl-vmrxzOHA2CKc3BwYh0Aocs_5KEfqH8jB6yUUGPK4zE4MOtK1OX5qy99nM5mXeVHL7AvTTBEHSjByCLkIE7KI19QOYblP9UCC3BQSiSasXTU4ywErO-TSSAeKUEXCzqJc-qpIHGlpLSGhOFAwAEmTOg9-SW8KMxCAjrQrer6lsbrjuWJj3HK-E8D9wOMhEHgRDDgkQBhStTH4LjMiKFU_G3sJ05fHKH3Z9CBBU5x9g46ghuZMfRUiASPmQ0nuhS-kLGNsS2Y1f_M6htI6j_8m0nCK9pwhwysQn5_7_2wT0RL-Dor8D4vgM6B4J70fH1B8tq5moPjI7sZ_f20gH1PIiQZWr4ewYm9Bw6sXLa5jcm3EnZ0x_F5d9DE5EDoSAk9HDFx4ak07maFF-gLJSEqHEjh2WM4ZGSOlNLIIXdGfQcaKF3HZpEkcnNwGPSq0-KMOCsliOF2gp-sEV0XvS5jOhi7uxi7Qwrt8ffXy-Uj6h_5UizgSQQ6zERjyPqTYoS7Iv9FvHGvFEAm6hk9X8jldcy6Gmkc45HMulqCsc2PIc6H4cbuXWCO93tKFBSmFDtPY2bK2NWmaWy7zJrIJ83LKo8kxRYCr7PoJ_VmffC78iZUpRQEPL_RVYf9TYfvdiRXwiReye6jI5glu-_7999-gR5Dkc8YE_2koUJ9IeoUUzoDdnF-v9Y4Ya_FI3wYtCCTT-owtnl-BvNYOQz49mpsu3DblWtXLS5oW2-qp2bTVq1dDFvbNk1v63bztNrssaamXtdPdl1VVecqV68WvLWVfaxqW9tV3dR2WfVV13ZobbXqm4aceaxoRPbLnIVZAQsWmWm7adp6s_DYkZeSvtYGOkF5aKzNYZy2JT-7-SDmsfIsKn91UVZP2_9jchQyYXdX5Gj6qI6Hwn6xKiYKxm4UhsiiOQVmhbi_H3AxJ7_9z6leIEvJ9bbe_BkAAP__raQfwg">