<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 - clang generates incorrect X86-64 code optimization for integer assignment-comparison"
   href="https://bugs.llvm.org/show_bug.cgi?id=45191">45191</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>clang generates incorrect X86-64 code optimization for integer assignment-comparison
          </td>
        </tr>

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

        <tr>
          <th>Version</th>
          <td>9.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>release blocker
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

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

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

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>We've found the following issue in clang 6 through 9, in x86_64 Linux as well
as MacOS. And might have spanned more releases. This happens consistently for
certain source code arrangement when optimization is enabled (-O1 ~ -O3).
Unoptimized code seems to be fine. Since this bug is a contradiction to
C-language's definition and the C source code is a very common way of writing,
I'd consider it a severe bug that has existed for a few years and many programs
may have been impacted without noticing the issue, if the tests haven't covered
the case.

For the short C program below ('volatile' is to prevent optimizer from directly
short-circuiting the while-loop. In real cases the assignment in the loop can
be function calls.):

#include <stdio.h>
#include <stdint.h>

int32_t volatile g_a = 0x7fffffff;
int32_t volatile g_b = 16;

int main()
{
    int32_t overflown = g_a;
    int32_t m;

    while ((m = overflown - g_a) <= 0)
    {
        overflown = g_a + g_b;
        putchar('.');
    }

    printf("m = %d\n", m);
    return 0;
}

If compiled without optimization, e.g., clang-9 -Wall source.c, the resultant
executable runs fine, printing ".m = 16" and exit. But if it is compiled with
optimization, e.g., clang-9 -Wall -O3 source.c, the generated code will loop
forever printing '.'. Disassembly the main function of the optimized code
shows:

(gdb) disass main
Dump of assembler code for function main:
   0x0000000000401140 <+0>:     push   %rbx
   0x0000000000401141 <+1>:     mov    0x2ef1(%rip),%ebx        # 0x404038
<g_a>
   0x0000000000401147 <+7>:     sub    0x2eeb(%rip),%ebx        # 0x404038
<g_a>
   0x000000000040114d <+13>:    jg     0x401175 <main+53>
   0x000000000040114f <+15>:    nop
   0x0000000000401150 <+16>:    mov    0x2ee2(%rip),%ebx        # 0x404038
<g_a>
   0x0000000000401156 <+22>:    add    0x2ee0(%rip),%ebx        # 0x40403c
<g_b>
   0x000000000040115c <+28>:    mov    0x2edd(%rip),%rsi        # 0x404040
<stdout@@GLIBC_2.2.5>
   0x0000000000401163 <+35>:    mov    $0x2e,%edi
   0x0000000000401168 <+40>:    callq  0x401040 <putc@plt>
   0x000000000040116d <+45>:    sub    0x2ec5(%rip),%ebx        # 0x404038
<g_a>
   0x0000000000401173 <+51>:    jle    0x401150 <main+16>
   0x0000000000401175 <+53>:    mov    $0x402004,%edi
   0x000000000040117a <+58>:    mov    %ebx,%esi
   0x000000000040117c <+60>:    xor    %eax,%eax
   0x000000000040117e <+62>:    callq  0x401030 <printf@plt>
   0x0000000000401183 <+67>:    xor    %eax,%eax
   0x0000000000401185 <+69>:    pop    %rbx
   0x0000000000401186 <+70>:    retq
End of assembler dump.
(gdb) q

Apparently after 'sub' (main+7, +45), a 'test %ebx,%ebx' or 'cmp #0,%ebx' is
missing. Therefore the branch instructions uses the result of 'sub' operation
instead of the result of 'sub'.

Code like this is commonly used for integer comparison on the integer-ring,
e.g., timer timeout, TCP Sequence numbers, etc. The impact of this bug is big.</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>