【问题标题】:MinGW gcc set fp rounding modeMinGW gcc 设置 fp 舍入模式
【发布时间】:2017-04-03 19:04:46
【问题描述】:

我正在使用 gcc 编译器,我希望能够快速更改 sse 舍入模式。以下代码在linux下编译即可:

#include <xmmintrin.h>
unsigned int _mxcsr_up = _MM_MASK_MASK | _MM_ROUND_UP;
unsigned int _mxcsr_down = _MM_MASK_MASK | _MM_ROUND_DOWN;
unsigned int _mxcsr_n = _MM_MASK_MASK;

void round_nearest_mode() {
    asm (
    "ldmxcsr %0" : : "m" (_mxcsr_n)
    );
}

void round_up_mode() {
    asm (
    "ldmxcsr %0" : : "m" (_mxcsr_up)
    );
}

void round_down_mode() {
        asm (
        "ldmxcsr %0" : : "m" (_mxcsr_down)
        );
}

但是当我在windows下使用MinGW编译时,舍入模式并没有改变。是什么原因?

【问题讨论】:

  • @StoryTeller 我包含 但我不能使用它的内容。我认为条件'#if _GLIBCXX_USE_C99_FENV_TR1'不满足,但我不知道为什么。
  • 将项目构建为 C99。将-std=c99 添加到编译器调用(如果您使用IDE,则在项目选项中查找选项)。
  • 是什么让你觉得模式没变?你如何测试这个?
  • @DavidWohlferd:我认为他真的没有改变舍入模式,因为他正在 ORing _MM_MASK_MASK 而不是 ANDing。

标签: c gcc assembly floating-point mingw


【解决方案1】:

提供_MM_ROUND_UP 常量的相同标头还定义了相关指令周围的_mm_setcsr(unsigned int i)_mm_getcsr(void) 内部包装器。

您通常应该检索旧值,OR 或 ANDN 您要更改的位,然后应用新值。 (例如mxcsr &amp;= ~SOME_BITS)。您不会找到很多只是在不先执行 STMXCSR 的情况下使用 LDMXCSR 的示例。

哦,我认为您实际上在代码中做错了那部分。我还没有看过_MM_MASK_MASK 是如何定义的,但是它的名字中包含了 MASK 这个词。您将其与各种其他常量进行 ORing,而不是 ANDing。 您可能每次都将 MXCSR 设置为相同的值,因为您正在使用 _MM_MASK_MASK 对所有内容进行 ORing,我假设它已设置所有舍入模式位。


正如@StoryTeller 指出的那样,您不需要内联汇编或内部函数来更改舍入模式,因为x86 硬件提供的四种舍入模式与C99 中fenv.h 定义的四种匹配:(FE_DOWNWARD, FE_TONEAREST (the default), FE_TOWARDZERO, and FE_UPWARD),这你可以设置fesetround(FE_DOWNWARD);

如果您想即时更改舍入模式并确保优化器不会将任何 FP 操作重新排序到舍入模式设置不同的位置,您需要
#pragma STDC FENV_ACCESS ONbut gcc doesn't support it。另见this gcc bug from 2008 which is still open: Optimization generates incorrect code with -frounding-math option (#pragma STDC FENV_ACCESS not implemented)


使用 asm volatile 手动执行它仍然不会阻止 CSE 认为之前计算的 x/y 是相同的值,但不会在 asm 语句之后重新计算它。除非您使用 xy 作为从未实际使用过的 asm 语句的读写操作数。例如

asm volatile("" : "+g"(x));  // optimizer must not make any assumptions about x's value.

您可以将 LDMXCSR 放在同一个 inline-asm 语句中,以保证舍入模式更改的点也是编译器将 x 视为已更改的点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-30
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2020-12-28
    相关资源
    最近更新 更多