<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 - InstCombine combines mul->shift into two multiplies."
   href="https://bugs.llvm.org/show_bug.cgi?id=42874">42874</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>InstCombine combines mul->shift into two multiplies.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </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>Scalar Optimizations
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>husseydevin@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>InstCombine is often too willing to turn a multiply followed by a shift/rotate
to two multiplies. 

<a href="https://godbolt.org/z/W44mjh">https://godbolt.org/z/W44mjh</a>

C:

#include <stdint.h>

uint32_t mulrot(uint32_t a)
{
    a *= 0x90000007;
    a = (a << 4) | (a >> 28);
    return a;
}

LLVM IR:

define i32 @mulrot(i32) {
  %2 = mul i32 %0, -1879048185 ; 0x90000007
  %3 = shl i32 %2, 4
  %4 = lshr i32 %2, 28
  %5 = or i32 %3, %4
  ret i32 %5
}


After running instcombine on this code, it converts it to this:

define i32 @mulrot(i32) {
  %2 = mul i32 %0, -1879048185 ; 0x90000007
  %3 = mul i32 %0, 112         ; 0x70
  %4 = lshr i32 %2, 28
  %5 = or i32 %3, %4
  ret i32 %5
}

So for example, on x86_64, the code I want is

mulrot:
    imul eax, edx, 0x90000007
    rol eax, 4
    ret

but I get this instead.

mulrot:
    imul eax, edi, 0x90000007
    imul ecx, edi, 0x70
    shr eax, 28
    or eax, ecx
    ret

This is incredibly inefficient and screws some stuff up.

instcombine is trying to use the associative property to make it so the
multiplies don't depend on each other.

    x *= 5;
    int y = x * 9;

is the same as 

    int y = x * 9 * 5;
    x *= 9;

In a normal scenario, this would probably be faster, as it can now use ILP.
However, a rotate/shift is usually much faster in this case and should be
prioritized.

While it is easiest to reproduce with a rotate, a simple left shift works as
well, as long as you use both results.

Using the funnel shift intrinsic doesn't cause this behavior.</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>