[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