<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 - Incorrect code generation for ARM with inline assembly"
href="https://bugs.llvm.org/show_bug.cgi?id=50647">50647</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Incorrect code generation for ARM with inline assembly
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</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>jacob.abraham@intel.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>I came across a code generation issue related to register allocation.
Essentially, if you have two C variables, one being uninitialized, and you use
one of them in regular C code (in the example a shift right), then use both of
them as inputs to an inline asm block, the two variables collide on a register.
This issue does not appear in similar X86 code or in the ARM gcc compiler.
However, if you initialize the variable this bug goes away, but introduces an
extra mov that is unnecessary for the correctness of the code.
You can see the below example on compiler explorer here
(<a href="https://godbolt.org/z/7nKhfj9E9">https://godbolt.org/z/7nKhfj9E9</a>)
The following is code that reproduces the issue
void func(unsigned long long n)
{
#ifndef FIX
unsigned long long b;
#else
//this fixes the bug but introduces an extra, extraneous mov
//the ideal code would not include this extra mov
//this is what gcc does with or without initializing the variable
unsigned long long b = 0;
#endif
//if this is not here, bug does not occur
//one of the C variables must be used to trigger the bug
n = n >> 7;
//_n should be a loop counter
//_b should be the jump address
//but _n and _b map to the same register in arm clang
//they should map to different registers, as seen in arm gcc
__asm__ volatile (
"top%=: \n\t"
"adrp %[_b], lbl%=@PAGE \n\t"
"add %[_b], %[_b], lbl%=@PAGEOFF \n\t"
"br %[_b] \n\t"
"lbl%=: \n\t"
"sub %[_n], %[_n], #0x1 \n\t"
"cmp %[_n], #0x0 \n\t"
"b.ne top%= \n\t"
:
: [_n] "r" (n), [_b] "r" (b)
);
}
The generated assembly is as follows
func:
lsr x8, x0, #7
top0:
adrp x8, lbl0@PAGE
add x8, x8, lbl0@PAGEOFF
br x8
lbl0:
sub x8, x8, #1
cmp x8, #0
b.ne top0
ret
Note that x0 is 'n', which after being shifted is stored in x8. But then x8 is
used for both 'n' and 'b'.
I would expect the generated assembly to be
func:
lsr x9, x0, #7
top0:
adrp x8, lbl0@PAGE
add x8, x8, lbl0@PAGEOFF
br x8
lbl0:
sub x9, x9, #1
cmp x9, #0
b.ne top0
ret</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>