[llvm-bugs] [Bug 28701] New: Thumb code generation incorrectly uses smmls

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jul 25 13:46:43 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=28701

            Bug ID: 28701
           Summary: Thumb code generation incorrectly uses smmls
           Product: new-bugs
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: martin at martin.st
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

Created attachment 16804
  --> https://llvm.org/bugs/attachment.cgi?id=16804&action=edit
Sample code illustrating how the smmls instruction causes differing results

The optimizer can choose to use the smmul instruction for functions like this,
which is correct:

int MULH(int a, int b)
{
    return ((int64_t)a * (int64_t)b) >> 32;
}

With optimization, this ends up compiled as this:

00000000 <MULH>:
   0:   fb51 f000       smmul   r0, r1, r0
   4:   4770            bx      lr

(And similarly in ARM mode.)

When combined with a subtraction, this can end up as the smmls instruction, in
cases like this:

int test_MULH(int a, int b, int c)
{
    return c - MULH_inline(a, b);
}

In ARM mode, this ends up compiled like this:

00000008 <test_inline>:
   8:   e750f011        smmul   r0, r1, r0
   c:   e0420000        sub     r0, r2, r0
  10:   e12fff1e        bx      lr

This is correct, but in thumb mode, this gets optimized further, to use the
smmls instruction:

00000006 <test_inline>:
   6:   fb61 2000       smmls   r0, r1, r0, r2
   a:   4770            bx      lr

This is wrong, since smmls doesn't truncate the result of the multiplication
before accumulating. The description of smmls is:

"Signed Most Significant Word Multiply Subtract multiplies two signed 32-bit
values, subtracts the result from a 32-bit accumulate value that is shifted
left by 32 bits, and extracts the most significant 32 bits of the result of
that subtraction."

Thus, in practice, as long as the lower 32 bit of the result of the
multiplication isn't zero, the result will end up one less than the actual.

The attached code sample, built with optimization in thumb mode, illustrates
the issue. To reproduce:

$ clang -target armv7-linux-gnueabihf test-smmls.c -o test-smmls -O -mthumb
$ ./test-smmls
differing: 6324 vs 6323

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160725/a7e54f36/attachment-0001.html>


More information about the llvm-bugs mailing list