如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?

How to use gnu gcc flag -mpc32, -mpc64 and -mpc80?

我从 GNU GCC compiler Manual 获得了这些 GCC 标志。但是当我尝试使用这些标志(-mpc32-mpc64-mpc80)时,我无法观察到这种行为。所以我需要有关如何通过示例代码使用这些标志的帮助。

我试过的示例代码: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;
}

编译选项:

g++ -mpc32 test.cpp
g++ -mpc64 test.cpp
g++ -mpc80 test.cpp

测试不同 x87 精度的最简单方法可能是使用 long double,它在 x86 目标上是 80 位 x87 类型。 (除了 Windows,其中 long double = double)。

long double 的另一个优点是您根本不需要使用 -m32 进行编译就可以使用 x87。 (-m64 的默认值是 -mfpmath=sse;double 和 float 数学运算将在 XMM 寄存器中以类型宽度完成,不会扩大到 x87 内部精度。但是 long double 将始终使用 x87,因为SSE/SSE2 不能做 80 位)。 TL:DR:在使用 gcc -mpc32 foo.c 构建的普通 64 位系统上,-mpc32double 变量的数学运算没有任何影响,因为它不会甚至使用传统的 x87 FPU。

顺便说一句,此测试用例还依赖于使用默认 -O0 进行编译,否则会在编译时发生不断传播。 (这不太可能尊重 -mpc32。)


137.142364501953125f 是一个 float 常量,在用作 double 的初始值设定项之前四舍五入为浮点数。因此,尽管存储为 double,但您的起始值都四舍五入到最接近的 float。不过,我假设除法不准确,所以您仍然会四舍五入。


我假设这些选项只是在启动时设置 x87 精度。 MSVC 的 CRT 起始代码显然做了类似的事情,默认设置 64 位精度(53 位尾数,如 double,不是全精度)。参见 Bruce Dawson 的 Intermediate Floating-Point Precision article; one of a series of FP articles. Index in this one.

您可以查看编译器生成的 asm 以了解它如何进行 FP 数学运算:使用 fld / fmul / fstp 是 x87 并且会受到 x87 精度的影响在 x87 控制字寄存器中设置。

movsd / mulsd 是SSE2,精度由指令设置;没有状态/控制位可以覆盖它。 (只有舍入模式可以在 MXCSR 中更改,以及次正规的处理。)