问题
Someone told me that:
Under x86-64, FP arithmetic is done with SSE, and therefore long double is 64 bits.
But in the x86-64 ABI it says that:
C type | sizeof | alignment | AMD64 Architecture
long double | 16 | 16 | 80-bit extended (IEEE-754)
See: amd64-abi.pdf
and gcc says sizeof(long double)
is 16 and gives FLT_DBL
= 1.79769e+308
and FLT_LDBL = 1.18973e+4932
So I'm confused, how is long double
64 bit? I thought it is an 80-bit representation.
回答1:
Under x86-64, FP arithmetic is done with SSE, and therefore long double is 64 bits.
That's what usually happens under x86-64 (where the presence of SSE instructions is guaranteed), but the program is still free to use x87, to which the compiler can resort when you use a long double
.
You can have confirmation of this by compiling a program like this with g++
on Linux:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
std::srand(std::time(NULL));
float f1=rand(), f2=rand();
double d1=rand(), d2=rand();
long double l1=rand(), l2=rand();
std::cout<<f1*f2<<" "<<d1*d2<<" "<<l1*l2<<std::endl;
return 0;
}
In the assembly output, I find mulsd xmm1, xmm0
for the double
product and mulss xmm0, xmm2
for the float
product (both SSE instructions), but fmulp st(1), st
(x87 instruction) for the long double
product.
So, it's confirmed, the compiler uses SSE when it can, but still allows 80-bit precision computations via the old x87 instruction set.
Notice that this is compiler-specific - some compilers (e.g. VC++) always ignored 80-bit precision types and just treated long double
as a synonym of double
.
On the other hand, since the x86-64 System V ABI (adopted on Linux) mandates that long double
is 80 bit, the only way for a compiler to perform computations using all the available precision of the type is to use the x87 instructions.
回答2:
The AMD ABI cannot actually compel what the C long double
type is, because it does not have the jurisdiction/authority to do so. Each C implementation can make its own specification of what the types are, subject to the C standard (if the C implementation is conforming to the standard), and each C implementation can choose whether or not to conform to the AMD ABI.
This means you cannot simply ask “What is long double
on x86-64?” You must ask what is long double
in a specific C implementation. That means specifying a particular C compiler, version, and switches used to compile. (A compiler might have a switch for which one setting makes long double
a 64-bit binary IEEE 754-floating-point object and another setting makes long double
the 80-bit Intel floating-point object. Technically, each different combination of compiler, version, and switches is a distinct C implementation.)
A compiler that implements long double
as a 64-bit binary IEEE-754 floating-point object simply passes them as what the AMD ABI calls double
; it never passes them as what the ABI calls long double
. In doing so, this aspect of the compiler would be compatible only with other software that treats long double
similarly.
回答3:
The SSE calculation is double precision and the intermediate representation is 64 bits.
That's not long double
, as you have pointed out. The 64 bit value is just written to the long double after calculation.
来源:https://stackoverflow.com/questions/15176290/what-is-long-double-on-x86-64