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

Posted

技术标签:

【中文标题】如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?【英文标题】:How to use gnu gcc flag -mpc32, -mpc64 and -mpc80? 【发布时间】:2020-01-24 10:26:36 【问题描述】:

我从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

【问题讨论】:

更新了我测试的代码。 【参考方案1】:

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

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

顺便说一句,这个测试用例也依赖于使用默认的-O0 编译,否则编译时会发生持续传播。 (这不太可能尊重-mpc32。)


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


我假设这些选项只是在启动时设置 x87 精度。 MSVC 的 CRT 启动代码显然做了类似的事情,默认设置为 64 位精度(53 位尾数,如double,不是全精度)。请参阅 Bruce Dawson 的 Intermediate Floating-Point Precision 文章; FP 系列文章之一。 Index in this one.

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

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

【讨论】:

以上是关于如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?的主要内容,如果未能解决你的问题,请参考以下文章

GCC 编译器标志“-DEVAL”

使用 GNU make 编译启用配置文件的包

链接使用不同预处理器标志或 C 标准构建的库

如果设置了标志,GNU 如何理解?

如何在 gcc 中启用单个优化标志?

如何独立于标准启用 GCC 的 GNU 扩展?