gpt4 book ai didi

c++ - C++ 中的编译器指令重新排序优化(以及抑制它们的因素)

转载 作者:太空狗 更新时间:2023-10-29 21:05:39 29 4
gpt4 key购买 nike

我已将我的代码缩减为以下内容,在保留我感兴趣的编译器输出的同时尽可能简单。

void foo(const uint64_t used)
{
uint64_t ar[100];
for(int i = 0; i < 100; ++i)
{
ar[i] = some_global_array[i];
}

const uint64_t mask = ar[0];
if((used & mask) != 0)
{
return;
}

bar(ar); // Not inlined
}

使用带有/O2 和/Ob1 的 VC10,生成的程序集几乎反射(reflect)了上述 C++ 代码中指令的顺序。由于局部数组 ar 仅在条件失败时传递给 bar(),否则未使用,因此我希望编译器优化为如下所示。

if((used & some_global_array[0]) != 0)
{
return;
}

// Now do the copying to ar and call bar(ar)...

编译器不这样做是因为在一般情况下很难识别此类优化吗?或者它是否遵循一些禁止它这样做的严格规则?如果是这样,为什么,有什么方法可以提示它这样做不会改变我程序的语义?

注意:显然,仅通过重新排列代码来获得优化的输出是微不足道的,但我感兴趣的是为什么编译器在这种情况下不会优化,而不是如何优化 在这个(有意简化的)案例中这样做。

最佳答案

可能这没有得到优化的原因是全局数组。编译器无法事先知道访问 some_global_array[99] 是否会导致生成某种异常/信号,因此它必须执行整个循环。如果在同一个编译单元中静态定义全局数组,情况就会大不相同。

例如,在 LLVM 中,全局数组的以下三个定义将产生该函数的截然不同的输出:

// this yields pretty much what you're seeing
uint64_t *some_global_array;
// this calls memcpy and then performs the conditional check
uint64_t some_global_array[100] = {0};
// this calls memset (not memcpy!) on the ar array and then bar directly (no
// conditional checks since the array is const and filled with 0s, so the if
// is always false)
const uint64_t some_global_array[100] = {0};

第二个非常令人费解,但它可能只是错过了优化(或者我可能错过了其他东西)。

关于c++ - C++ 中的编译器指令重新排序优化(以及抑制它们的因素),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9441882/

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