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
On Aug 31, 2011, at 12:28 AM, Florian Schirmer wrote:> 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 EndThis has been fixed in SVN trunk. /jakob
Possibly Parallel Threads
- More BeOS woe
- [LLVMdev] Feature request for include llvm-mc in llvm.org/builds
- [LLVMdev] Feature request for include llvm-mc in llvm.org/builds
- [LLVMdev] LLVM-GCC generating too much code from inline assembly
- [LLVMdev] LLVM-GCC generating too much code from inline assembly