[arm64] Negative immediates
Torbjörn Granlund
tg at gmplib.org
Tue Sep 23 21:58:09 UTC 2014
Marc Glisse <marc.glisse at inria.fr> writes:
long f(long l){return __builtin_clzl(l);}
compiles to:
clz x0, x0
ret
with clang-3.4, clang-3.5, gcc-4.8 and gcc-4.9 at -O or higher (-O0
also calls clz, with some loads and stores around it).
Good!
> On aarch64, with "r"(var), gcc and clang always name the register x0
> (never w0), whether var is an int or a long long. On amd64, I get %al
> / %ax / %eax / %rax depending on the type of var.
>
> You're right! That seem quite odd, I'd say wrong, and is why things
> happens to work with gcc.
>
> (One can override it with 'w' after the % in the register constraint.
> See aarch64_print_operand in gcc-4.8.2/gcc/config/aarch64/aarch64.c.)
Nice find, but clang doesn't accept it. I'll ask the gcc devs.
One could argue that defaulting to 64-bit register names for narrower
types is incorrect by using an example like this:
#include <stdlib.h>
#include <stdio.h>
void
foo (unsigned int a, unsigned int b)
{
unsigned int r;
asm ("lsl %0, %1, %2\n\tlsr %0, %0, %2" : "=&r" (r) : "%r" (a), "r"
(b));
if (r != (a << b) >> b)
abort ();
}
main ()
{
unsigned int r;
foo (0xcafebabe, 31);
return 0;
}
The problem is that the lsl result isn't truncated as it should be.
Using %w is a workaround, but an ugly one.
Torbjörn
Please encrypt, key id 0xC8601622
More information about the gmp-bugs
mailing list