FP Stack overflow with inline asm

Hi LLVM hackers,

when switching one of our projects to LLVM we discovered some strange behavior. We tracked the issue down to the following test case:

int main()
{
  double v = 0.84711;
  int r;

  __asm__("fistl %0": "=m"(r) : "t"(v));

  return r;
}

The (relevant) clang generated asm looks like this:

fldt 0.84711
## InlineAsm Start
fistl -4(%ebp)
## InlineAsm End

The compiler is loading the constant into the top fpu stack register (as requested by "t" constraint) and then is executing the asm statement. The asm statement doesn't pop the value from the fp stack. Running this statement in a loop will quickly result in a fp stack overflow. As i'm not a real inline asm expert i'm wondering who is supposed to clean up the mess.

There is a section in the gcc manual dealing with situations like this:

http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Extended-Asm.html#Extended-Asm (Section 6.41.2 i386 floating point asm operands)

According to that page i would assume that it is the job of the compiler to handle the stack usage since the asm doesn't modify the fpu stack and we also didn't mark it as clobbered.

Same code compiled with gcc-4.2:

fldl 0.84711
fistl -4(%ebp)
fstp %st(0)

This seems fine and works as expected. Changing the inline asm to

__asm__("fistl %0": "=m"(r) : "t"(v) : "st"); // Marking fpu top stack as clobbered

Will result in the same output for gcc-4.2 and clang:

fldt 0.84711
## InlineAsm Start
fistl -4(%ebp)
## InlineAsm End

This code seems fine, of course it doesn't work but is exactly what was requested.

The issue can we worked around by using the following asm statement:

__asm__("fistpl %0": "=m"(r) : "t"(v) : "st");

which actively pops the value from the stack but i really would like to understand (and fix) the root of the problem and not tamper some band aid over it.

I'm happy to file a bug if someone can confirm that my inline asm understanding is right and we're indeed talking about a compile issue here.

Thanks a lot for your help!

Best,
   Florian

This has been fixed in SVN trunk.

/jakob