<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 - Inline assembly allocated register clash with multi-register constraints"
href="https://bugs.llvm.org/show_bug.cgi?id=48862">48862</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Inline assembly allocated register clash with multi-register constraints
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</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>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Register Allocator
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>nva280@nn.kiev.ua
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, quentin.colombet@gmail.com
</td>
</tr></table>
<p>
<div>
<pre>Consider the following sample program (targeting Linux/x86-64):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned arg1 = strtoul(argv[1], NULL, 0);
unsigned arg2 = strtoul(argv[2], NULL, 0);
asm(
"mov %[arg1], %%ecx\n\t"
"add %[arg2], %[arg1]\n\t"
"add %[arg2], %%ecx\n\t"
"xchg %%ecx, %[arg2]"
: [arg1] "+&abdSD" (arg1), [arg2] "+&abdSD" (arg2)
:
: "cc", "ecx");
printf("%u %u\n", arg1, arg2);
}
(xchg is used just for easy grepping of compiled instructions in listing. This
is just an example crafted to reproduce the issue, far from real code, but
clear enough.)
With GCC, it works as expected - different registers are assigned to arg1 and
arg2, for example:
11bf: e8 cc fe ff ff callq 1090 <strtoul@plt>
11c4: 89 da mov %ebx,%edx
11c6: 89 d1 mov %edx,%ecx
11c8: 01 c2 add %eax,%edx
11ca: 01 c1 add %eax,%ecx
11cc: 91 xchg %eax,%ecx
(so, arg1 in edx, arg2 in eax)
But, compiling with Clang (confirmed on all from 6.0 to trunk) results in
assigning the same register for arg1 and arg2:
401174: e8 d7 fe ff ff callq 401050 <strtoul@plt>
401179: 44 89 f0 mov %r14d,%eax ; <--
40117c: 89 c1 mov %eax,%ecx
40117e: 01 c0 add %eax,%eax ; <-- so, arg1 and
arg2 both in eax
401180: 01 c1 add %eax,%ecx
401182: 91 xchg %eax,%ecx
The issue remains with multiple variations as e.g.: + instead of +& in
constraint strings; numeric forms like %0 to address operands; replacing xchg
with another rare instruction; and so on.
The issue is of importance on x86 because a lots of its instructions are
allowing only fixed registers, but a desire to alleviate allocation causes
constraint suggestion as explicit list except 1-2 reserved ones.
A workaround is accessible to use generic constraints like 'r' while marking
all disallowed registers as clobbered, but Iʼm uncertain whether it wonʼt
explode with "rm" or analogs.
Discussed also at <a href="https://stackoverflow.com/q/65644864">https://stackoverflow.com/q/65644864</a> (with an explicit
suggestion this is really a bug).</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>