<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 - Inefficient codegen for remainder loop when vectorizing by factor of 2 (possibly more)"
   href="https://bugs.llvm.org/show_bug.cgi?id=44547">44547</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Inefficient codegen for remainder loop when vectorizing by factor of 2 (possibly more)
          </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>All
          </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>Loop Optimizer
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>d.maljutin@yandex.ru
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>See motivating example: <a href="https://godbolt.org/z/vSfTT9">https://godbolt.org/z/vSfTT9</a>

void test(const int16_t* __restrict a, const int16_t* __restrict b, int16_t*
__restrict c, uint32_t n) {
#pragma nounroll
#pragma clang loop vectorize_width(2) interleave_count(1)
    for (int32_t i = 0; i < n; i++) {
        *c++ = *a++ + *b++;
    }
}

One would imagine that the compiler would essentially turn this into
{
    if (n & 1) *c++ = *a++ + *b++;
    for (int32_t i = 0; i < n<<1; i++) {
        ...
    }
}
But it generates something like this instead:
{
    for (int32_t i = 0; i < n<<1; i++) {
        ...
    }
    if (n & 1) for (int32_t i = 0; i < phi(1, (n & 1)); i++) *c++ = *a++ +
*b++;
}
Loop vectorizer seems to always generate remainder "block", as a loop even if
it has known constant tripcount (in this case it's 1!).
However, since this tripcount is hidden behind an "if" (or switch condition
after some opts), this "remainder loop with tripcount == 1" is never really
unrolled (because SCEV fails to compute it's tripcount). Sometimes running
additional GVN and IPSCCP passes helps, but this is not optimal.

I don't see why remainder has to be a loop in the first place (when trip count
is known).</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>