<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>