Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

Strange handling of asm constraints #17958

Open Quuxplusone opened 10 years ago

Quuxplusone commented 10 years ago
Bugzilla Link PR17959
Status NEW
Importance P normal
Reported by Marc Glisse (marc.glisse@normalesup.org)
Reported on 2013-11-16 12:17:36 -0800
Last modified on 2018-03-20 08:53:51 -0700
Version trunk
Hardware PC Linux
CC echristo@gmail.com, llvm-bugs@lists.llvm.org, llvm-dev@ndave.org
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
double f(double x){
  asm volatile ("" : "+x"(x) );
  asm volatile ("" : "+m"(x) );
  asm volatile ("" : "+f"(x) );
  asm volatile ("" : "+mx"(x) );
  asm volatile ("" : "+mf"(x) );
  asm volatile ("" : "+xm"(x) );
  asm volatile ("" : "+xf"(x) );
  asm volatile ("" : "+fx"(x) );
  asm volatile ("" : "+fm"(x) );
  asm volatile ("" : "+mxf"(x) );
  asm volatile ("" : "+mfx"(x) );
  asm volatile ("" : "+fmx"(x) );
  asm volatile ("" : "+fxm"(x) );
  asm volatile ("" : "+xfm"(x) );
  asm volatile ("" : "+xmf"(x) );
  return x;
}

compiled with clang complains:
error: illegal "f" output constraint
for each line where there isn't an 'x' before the 'f'. That seems inconsistent.
And the 'f' seems ignored in the cases where it isn't rejected.

Now if I compile:
  asm volatile ("" : "+x"(x) );
with -m64 -O, I get the expected empty assembler output (just 'ret').
But with "+xm", the compiler somehow adds:
    movsd   %xmm0, -8(%rsp)
before and after the asm (I would maybe understand if the second movsd was
reversed, it would just mean that llvm wrongly prefers 'm' to 'x', but the same
movsd is confusing me).

Similarly strange things happen with -m32, producing for instance:
    subl    $12, %esp
    movsd   16(%esp), %xmm0
    movsd   %xmm0, (%esp)
    #APP
    #NO_APP
    movsd   %xmm0, (%esp)
    fldl    (%esp)
    addl    $12, %esp

when with just "+x" it manages the less strange:
    subl    $12, %esp
    movsd   16(%esp), %xmm0
    #APP
    #NO_APP
    movsd   %xmm0, (%esp)
    fldl    (%esp)
    addl    $12, %esp
    ret

Note that inline asm is all the more necessary with llvm ignoring fenv floating
point support.
Quuxplusone commented 7 years ago

This currently fails with

fatal error: error in backend: Cannot pop empty stack!

while gcc rejects it with the slightly clearer

error: output constraint 0 must specify a single register

After replacing "f" by "t" as a constraint, I still see plenty of meaningless "movsd %xmm0, -32(%rsp)" generated by llvm.