gpt4 book ai didi

c++ - 为什么 GCC 不能优化 "x && (x & 4242)"到 "x & 4242"中的逻辑/按位与对?

转载 作者:IT老高 更新时间:2023-10-28 12:12:26 25 4
gpt4 key购买 nike

这里有两个我声称做同样事情的函数:

bool fast(int x)
{
return x & 4242;
}

bool slow(int x)
{
return x && (x & 4242);
}

从逻辑上讲,它们做同样的事情,只是为了 100% 确定我编写了一个测试,通过它们运行所有 40 亿个可能的输入,并且它们匹配。 (x & 4242 只有在特定位置设置位时才为非零,这意味着 x 具有非零值,因此测试 x!= 0 单独作为逻辑 && 的另一端是多余的。)但汇编代码是另一回事:

fast:
andl $4242, %edi
setne %al
ret

slow:
xorl %eax, %eax
testl %edi, %edi
je .L3
andl $4242, %edi
setne %al
.L3:
rep
ret

令我惊讶的是,GCC 无法通过逻辑飞跃来消除冗余测试。我用 -O2、-O3 和 -Os 尝试了 g++ 4.4.3 和 4.7.2,所有这些都生成了相同的代码。平台是 Linux x86_64。

有人能解释一下为什么 GCC 不应该足够聪明地在两种情况下生成相同的代码吗?

编辑以添加测试工具:

#include <cstdlib>
#include <vector>
using namespace std;

int main(int argc, char* argv[])
{
// make vector filled with numbers starting from argv[1]
int seed = atoi(argv[1]);
vector<int> v(100000);
for (int j = 0; j < 100000; ++j)
v[j] = j + seed;

// count how many times the function returns true
int result = 0;
for (int j = 0; j < 100000; ++j)
for (int i : v)
result += slow(i); // or fast(i), try both

return result;
}

我在带有 -O3 的 Mac OS 上使用 clang 5.1 测试了上述内容。使用 fast() 需要 2.9 秒,使用 slow() 需要 3.8 秒。如果我改为使用全零 vector ,则两个函数之间的性能没有显着差异。


其他编译器:

  • mainline clang 3.7 及更高版本甚至对 && 进行优化,clang 3.6 及更早版本不这样做。 https://godbolt.org/z/v5bjrvrP1
  • 最新的 GCC 主干(2022 年 3 月)和 11.2 仍然没有。
  • 当前的 MSVC 使用分支来完成这两个部分,而不是使用 setcc
  • ICC 使 asm 像 GCC,基于 LLVM 的 ICX 像 clang。 https://godbolt.org/z/cjKfr8r5b

最佳答案

究竟为什么应该能够优化代码?您假设将完成任何有效的转换。这根本不是优化器的工作方式。它们不是人工智能。它们只是通过参数替换已知模式来工作。例如。 “Common Subexpression Elimination” 会扫描表达式中的公共(public)子表达式,并将它们向前移动,如果这不会改变副作用的话。

(顺便说一句,CSE 表明优化器已经非常清楚在可能存在副作用的情况下允许哪些代码移动。他们知道您必须小心 &&。无论 expr && expr 是否可以进行 CSE 优化取决于 expr 的副作用。)

所以,总而言之:您认为哪种模式适用于这里?

关于c++ - 为什么 GCC 不能优化 "x && (x & 4242)"到 "x & 4242"中的逻辑/按位与对?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23055704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com