-Ofast 的 GCC 问题?

die*_*gor 5 c gcc

我有一个关于最新 GCC 编译器(版本 >= 5)的问题,代码如下:

#include <math.h>

void test_nan (
    const float * const __restrict__ in,
    const int n,
    char * const __restrict__ out )
{
    for (int i = 0; i < n; ++i)
        out[i] = isnan(in[i]);
}
Run Code Online (Sandbox Code Playgroud)

来自 GCC 的程序集列表:

test_nan:
        movq    %rdx, %rdi
        testl   %esi, %esi
        jle     .L1
        movslq  %esi, %rdx
        xorl    %esi, %esi
        jmp     memset
.L1:
        ret
Run Code Online (Sandbox Code Playgroud)

这看起来像memset(out, 0, n)。为什么 GCC 假设没有条目可以是 NaN 与 -Ofast ?使用相同的编译选项,ICC 不会显示此问题。使用 GCC,问题会随着“-O3”消失。

请注意,对于“-O3”,此查询gcc -c -Q -O3 --help=optimizers | egrep -i nan给出-fsignaling-nans [disabled].

我在本地和Godbolt上都验证了这一点,并带有附加选项“-std=c99”。

编辑:按照下面的有用答案,我可以确认-Ofast -std=c99 -fno-finite-math-only正确解决了这个问题。

Bar*_*mar 7

来自控制优化文档的 GCC选项

-Ofast除了启用以下优化-O3

它打开-ffast-math、 -fallow-store-data-races 和 Fortran 特定的 -fstack-arrays,除非指定了 -fmax-stack-var-size 和 -fno-protect-parens。

-ffast-math 启用以下功能:

-fno-math-errno、-funsafe-math-optimizations、-ffinite-math-only、-fno-rounding-math、-fno-signaling-nans、-fcx-limited-range 和 -fexcess-precision=fast。

-ffinite-math-only 执行以下操作:

允许对假定参数和结果不是 NaN或 +-Infs 的浮点算术进行优化。

这允许它假设isnan()总是返回0.