问题
I got these GCC flags from the GNU GCC compiler Manual. But when I tried to use those flags (-mpc32
, -mpc64
and -mpc80
) I couldn't observe the behavior. So I need help on how to use these flags with a sample code.
sample code I tried: test.cpp
#include<stdio.h>
#include<iomanip>
#include<math.h>
int main()
{
double weight = 1.0f;
double roiSize = 137.142364501953125f;
double thresholdValue = 5400.0f;
double alpha = weight / (roiSize * thresholdValue * thresholdValue);
std::cout<<std::setprecision(100)<<"alpha = "<<f<<std::endl;
double test = pow(roiSize, 10);
std::cout<<std::setprecision(100)<<"alpha = "<<f<<std::endl;
}
Compiling options:
g++ -mpc32 test.cpp
g++ -mpc64 test.cpp
g++ -mpc80 test.cpp
回答1:
The easiest way to test different x87 precisions might be to use long double
, which on x86 targets is the 80-bit x87 type. (Except on Windows where long double = double).
Another advantage to long double
is that you don't have to compile with -m32
to get it to use x87 at all. (The default for -m64
is -mfpmath=sse
; double and float math will be done in XMM registers, at the type width, not widened to x87 internal precision. But long double
will always use x87 because SSE/SSE2 can't do 80-bit). TL:DR: on a normal 64-bit system building with gcc -mpc32 foo.c
, -mpc32
won't make any difference for math on double
variables, because it doesn't even use the legacy x87 FPU.
BTW, this test case also depends on being compiled with the default -O0
, otherwise constant propagation at compile time will happen. (And that's unlikely to respect -mpc32
.)
137.142364501953125f
is a float
constant, rounded to float before being used as an initializer for a double
. So your starting values are all rounded to the nearest float
, despite being stored as double
. I assume the division isn't exact, though, so you would still get rounding.
I assume these options just set the x87 precision on startup. MSVC's CRT start code apparently does a similar thing, defaulting to setting 64-bit precision (53-bit mantissa, like double
, not full precision). See Bruce Dawson's Intermediate Floating-Point Precision article; one of a series of FP articles. Index in this one.
You can look at the compiler-generate asm to see how it does FP math: using fld
/ fmul
/ fstp
is x87 and will be affected by the x87 precision set in the x87 control word register.
movsd
/ mulsd
is SSE2 and precision is set by the instruction; no status / control bits can override it. (Only the rounding mode can be changed in MXCSR, and handling of subnormals.)
来源:https://stackoverflow.com/questions/59894562/how-to-use-gnu-gcc-flag-mpc32-mpc64-and-mpc80