相关疑难解决方法(0)

如何强制GCC假定浮点表达式为非负数?

在某些情况下,您知道某个浮点表达式将始终为非负数。例如,计算一个矢量的长度时,一个做sqrt(a[0]*a[0] + ... + a[N-1]*a[N-1])(NB:我知道的std::hypot,这是不相关的问题),并且平方根下表达显然是非负的。但是,GCC 为以下输出以下程序集sqrt(x*x)

        mulss   xmm0, xmm0
        pxor    xmm1, xmm1
        ucomiss xmm1, xmm0
        ja      .L10
        sqrtss  xmm0, xmm0
        ret
.L10:
        jmp     sqrtf
Run Code Online (Sandbox Code Playgroud)

也就是说,它将结果x*x与零进行比较,如果结果为非负数,则执行sqrtss指令,否则调用sqrtf

因此,我的问题是:如何强制GCC假定该x*x值始终为非负值,从而跳过比较和sqrtf调用,而无需编写内联汇编?

我想强调的是,我对本地解决方案感兴趣,而不是像-ffast-math-fno-math-errno或那样做-ffinite-math-only(尽管确实可以解决问题,这要归功于ks1322,harold和Eric Postpischil的评论)。

此外,“强制将GCC假定x*x为非负数”应解释为assert(x*x >= 0.f),因此这也排除了x*xNaN 的情况。

我可以使用特定于编译器,特定于平台,特定于CPU等的解决方案。

c++ floating-point assembly gcc micro-optimization

57
推荐指数
3
解决办法
2529
查看次数

-Ofast 的 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 …

c gcc

5
推荐指数
1
解决办法
259
查看次数

标签 统计

gcc ×2

assembly ×1

c ×1

c++ ×1

floating-point ×1

micro-optimization ×1