带有内置函数的奇怪 GCC6 优化

布鲁兹

使用 GCC6 和下面的代码片段,这个测试

if (i > 31 || i < 0) {

false,并执行此 printf

printf("i > 31 || i < 0 is FALSE, where i=%d", i);

并产生这个非常奇怪的输出(GCC6):

我 > 31 || i < 0 是FALSE,其中i=32 /* GCC6 的奇怪结果!!!*/

而使用 GCC4 我得到:

我 > 31 || i < 0 为,其中i=32 /* 结果与 GCC4 一致 */

看起来完全没问题。

怎么会这样??

代码片段(损坏的遗留代码!):

static int check_params(... input parameters ...) {
    /* Note that value can be 0 (zero) */
    uint32_t value = ....
    int i;

    i = __builtin_ctz(value);
    if (i > 31 || i < 0) {
        printf("i > 31 || i < 0 is true, where i=%d", i);
        /* No 1 found  */
        return 0;
    } else {
        printf("i > 31 || i < 0 is FALSE, where i=%d", i);
    }
    return i;
}

根据关于 GCC 内置函数的文档,必须避免调用 __builtin_ctz(0) :

内置函数:int __builtin_ctz (unsigned int x) 返回 x 中从最低有效位位置开始的尾随 0 位的数量。如果 x 为 0,则结果为 undefined

所以很明显,编码错误的解决方案是在调用 __builtin_ctz(value) 之前简单地检查值。这是清楚明白的。

我可以停在那里并转向其他主题......但是,我仍然不明白我怎么可能(使用损坏的代码)获得以下输出:

我 > 31 || i < 0 是FALSE,其中i=32 /* GCC6 的奇怪结果!!!*/

奇怪的 GCC6 优化还是什么?

以防万一它很重要:

Cross-compiler: arm-linux-gcc
Architecture: -march=armv7-a

任何想法?

sepp2k

除非未定义的行为,__builtin_ctz将始终返回 0 到 31 之间的数字,GCC 知道这一点。因此,检查i > 31 || i < 0将始终为假(再次禁止未定义的行为)并且可以优化掉。

如果您查看生成的程序集,您会看到条件根本没有出现在代码中(then-case 也没有)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章