6

我喜欢在启用浮点异常的情况下运行我的代码。我在 Linux 下使用:

feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );

到目前为止,一切都很好。

我遇到的问题是,有时编译器(我使用 clang8)决定使用 SIMD 指令进行标量除法。好吧,如果这样更快,即使是单个标量,为什么不呢。

但结果是 SIMD 寄存器中未使用的通道可能包含零。

并且在执行 SIMD 除法时,会抛出一个浮点异常。

这是否意味着如果您允许编译器使用 sse/avx 扩展,则根本不能使用浮点异常?

就我而言,这行 C 代码:

float a0, min, a, d;
...
a0 = (min - a) / (d);

...执行为:

divps  %xmm2,%xmm3

然后抛出一个:

Thread 1 "noisetuner" received signal SIGFPE, Arithmetic exception.
4

1 回答 1

4

我认为您在 clang 或 llvm 中发现了一个错误。

这是我复制的方式,clang 10.0 发出相同的代码,即也有该错误。显然,该vdivps指令仅在向量的前 2 个通道中具有有效数据,并且在较高的 2 个通道中它将运行 0.0 / 0.0,因此如果您在mxcsr寄存器中启用这些中断,您将获得运行时异常,就像您正在做的那样.

Microsoft、Intel 和 gcc 不会divps为该代码发出。如果可以的话,切换到 gcc 应该会很好。

更新: Clang 10+ 有一个控制此类优化的选项,-ffp-exception-behavior=maytrap看看:https ://godbolt.org/z/WG7bEE

于 2020-07-28T20:39:21.800 回答