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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…