llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.83k stars 11.46k forks source link

problems with soft-float #44349

Open llvmbot opened 4 years ago

llvmbot commented 4 years ago
Bugzilla Link 45004
Version 7.0
OS Linux
Reporter LLVM Bugzilla Contributor
CC @topperc,@DougGregor,@zygoloid

Extended Description

When I compile this program:

#include <stdio.h>
int main(int argc, char*argv[])
{
    double x = 2.0;
    double y = 3.0;
    printf("%f\n", x * y);
    return 0;
}

with "clang -msoft-float -mno-sse -O0 test.c", it prints 0 instead of 6.

Output of clang --version:

clang --version clang version 7.0.1-8 (tags/RELEASE_701/final) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

I'm trying to use soft-float without any FPU or XMM registers, as it is e.g. possible on ARM.

llvmbot commented 4 years ago

You are right, looks like this is the problem. The calling convention for AMD64 says so, too:

https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI

I tested it with this program:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

union N {
    double d;
    uint64_t u;
};

int main(int argc, char*argv[])
{
    union N x;
    union N y;
    union N z;
    x.d = 2.0;
    y.d = 3.0;
    z.d = x.d * y.d;
    printf("%"PRId64"\n", z.u);
    printf("%f\n", z.d);
    return 0;
}

and it prints this:

4618441417868443648
0.000000

I verified that the first number is the representation for the double float value 6, so it does at least the calculation.

I think this is a bug in CLANG, because when compiling it without the "-mno-sse", it places it in the XMM0 value, so CLANG knows that it has to place it in this register. If I specify that not XMM registers should be used, then it should abort with an error, because it can't place the value in this register anymore.

But I also noticed that it still generates fmul. Is this right? I thought with "-msoft-float" it shouldn't use the FPU instructions. This is the full main function, disassembled with "objdump -d":

0000000000401130 <main>:
  401130:       55                      push   %rbp
  401131:       48 89 e5                mov    %rsp,%rbp
  401134:       48 83 ec 30             sub    $0x30,%rsp
  401138:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  40113f:       89 7d f8                mov    %edi,-0x8(%rbp)
  401142:       48 89 75 f0             mov    %rsi,-0x10(%rbp)
  401146:       48 be 00 00 00 00 00    movabs $0x4000000000000000,%rsi
  40114d:       00 00 40 
  401150:       48 89 75 e8             mov    %rsi,-0x18(%rbp)
  401154:       48 be 00 00 00 00 00    movabs $0x4008000000000000,%rsi
  40115b:       00 08 40 
  40115e:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
  401162:       dd 45 e8                fldl   -0x18(%rbp)
  401165:       dd 45 e0                fldl   -0x20(%rbp)
  401168:       de c9                   fmulp  %st,%st(1)
  40116a:       48 89 e6                mov    %rsp,%rsi
  40116d:       dd 1e                   fstpl  (%rsi)
  40116f:       bf 04 20 40 00          mov    $0x402004,%edi
  401174:       31 c0                   xor    %eax,%eax
  401176:       88 c1                   mov    %al,%cl
  401178:       88 c8                   mov    %cl,%al
  40117a:       e8 b1 fe ff ff          callq  401030 <printf@plt>
  40117f:       31 d2                   xor    %edx,%edx
  401181:       89 45 dc                mov    %eax,-0x24(%rbp)
  401184:       89 d0                   mov    %edx,%eax
  401186:       48 83 c4 30             add    $0x30,%rsp
  40118a:       5d                      pop    %rbp
  40118b:       c3                      retq   
  40118c:       0f 1f 40 00             nopl   0x0(%rax)
topperc commented 4 years ago

I think the problem is that printf doesn’t know about the soft float switch since it’s in a precompiled library. It expects to receive floating point data in an xmm register. But the soft float setting prevents the compiler from generating any code that uses an xmm register.

llvmbot commented 2 months ago

@llvm/issue-subscribers-backend-x86

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [45004](https://llvm.org/bz45004) | | Version | 7.0 | | OS | Linux | | Reporter | LLVM Bugzilla Contributor | | CC | @topperc,@DougGregor,@zygoloid | ## Extended Description When I compile this program: #include <stdio.h> int main(int argc, char*argv[]) { double x = 2.0; double y = 3.0; printf("%f\n", x * y); return 0; } with "clang -msoft-float -mno-sse -O0 test.c", it prints 0 instead of 6. Output of clang --version: clang --version clang version 7.0.1-8 (tags/RELEASE_701/final) Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin I'm trying to use soft-float without any FPU or XMM registers, as it is e.g. possible on ARM.