<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 - [X86] [CodeGen] Compiler not using SHLD/SHRD instructions when doing double shift pattern combine for 16bit or 8bit arguments"
   href="https://bugs.llvm.org/show_bug.cgi?id=35155">35155</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[X86] [CodeGen] Compiler not using SHLD/SHRD instructions when doing double shift pattern combine for 16bit or 8bit arguments
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </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>LLVM Codegen
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>konstantin.belochapka@sony.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Consider the following code which implements double shift left:

uint64_t shld64(uint64_t a, uint64_t b, uint64_t shift)
{
  return (a << shift) | (b >> (64 - shift));
}

uint32_t shld32(uint32_t a, uint32_t b, uint32_t shift)
{
  return (a << shift) | (b >> (32 - shift));
}

uint16_t shld16(uint16_t a, uint16_t b, uint16_t shift)
{
  return (a << shift) | (b >> (16 - shift));
}

uint8_t shld8(uint8_t a, uint8_t b, uint8_t shift)
{
  return (a << shift) | (b >> (8 - shift));
}


With optimization enabled, clang produces the following assembler code:

shld64:
        movl    %edx, %ecx
        shldq   %cl, %rsi, %rdi
        movq    %rdi, %rax
        retq

shld32:
        movl    %edx, %ecx
        shldl   %cl, %esi, %edi
        movl    %edi, %eax
        retq

shld16:
        movl    %edx, %ecx
        shll    %cl, %edi
        movl    $16, %ecx
        subl    %edx, %ecx
        shrl    %cl, %esi
        orl     %edi, %esi
        movl    %esi, %eax
        retq

shld8:
        movl    %edx, %ecx
        shll    %cl, %edi
        movl    $8, %ecx
        subl    %edx, %ecx
        shrl    %cl, %esi
        orl     %edi, %esi
        movl    %esi, %eax
        retq


Obviously uint16_t type gets promoted to 32 bit and the backend code no longer
can recognize the double shift pattern.


Even with the integer promotion the generated code can be shorter, four
instruction against seven:
shld16:
        shll    $16, %esi
        movl    %edx, %ecx
        shldl   %cl, %esi, %edi
        movl    %edi, %eax
        retq

shld8:
        shll    $24, %esi
        movl    %edx, %ecx
        shldl   %cl, %esi, %edi
        movl    %edi, %eax
        retq</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>