为什么现代C ++编译器不能优化这样的简单循环? (Clang,MSVC) [英] Why don't modern C++ compilers optimize away simple loops like this? (Clang, MSVC)
问题描述
当我用Clang( -O3
)或MSVC( / O2
)编译和运行此代码时。
When I compile and run this code with Clang (-O3
) or MSVC (/O2
)...
#include <stdio.h>
#include <time.h>
static int const N = 0x8000;
int main()
{
clock_t const start = clock();
for (int i = 0; i < N; ++i)
{
int a[N]; // Never used outside of this block, but not optimized away
for (int j = 0; j < N; ++j)
{
++a[j]; // This is undefined behavior too, but Clang doesn't see it
}
}
clock_t const finish = clock();
fprintf(stderr, "%u ms\n",
static_cast<unsigned int>((finish - start) * 1000 / CLOCKS_PER_SEC));
return 0;
}
...循环未被优化。
... the loop doesn't get optimized away.
此外,既不 Clang 3.6 也 Visual C ++ 2013 也 GCC 4.8.1告诉我,变量是未初始化的!
Furthermore, neither Clang 3.6 nor Visual C++ 2013 nor GCC 4.8.1 tells me that the variable is uninitialized!
现在我意识到,缺少优化不是一个bug本身,但我发现这令人惊讶,如何编译器应该是相当聪明如今。这看起来像这样一个简单的代码段,即使十年前的活跃分析技术应该能够照顾优化变量 a
,因此整个循环 - 不要介意这样的事实,即增加变量已经是未定义的行为。
Now I realize that the lack of an optimization isn't a bug per se, but I find this astonishing given how compilers are supposed to be pretty smart nowadays. This seems like such a simple piece of code that even liveness analysis techniques from a decade ago should be able to take care of optimizing away the variable a
and therefore the whole loop -- never mind the fact that incrementing the variable is already undefined behavior.
然而只有GCC能够弄清楚它是一个无操作,没有编译器告诉我这是一个未初始化的变量。
Yet only GCC is able to figure out that it's a no-op, and none of the compilers tells me that this is an uninitialized variable.
为什么?什么妨碍简单活性分析告诉编译器 a
未使用?此外,为什么编译器没有检测到 a [j]
首先未初始化?为什么所有这些编译器中的现有未初始化变量检测器不能捕获这个明显的错误?
Why is this? What's preventing simple liveness analysis from telling the compiler that a
is unused? Moreover, why isn't the compiler detecting that a[j]
is uninitialized in the first place? Why can't the existing uninitialized-variable-detectors in all of those compilers catch this obvious error?
推荐答案
更改 a 到
unsigned int [N]
的类型,循环消失。
Change the type of a
to unsigned int[N]
, and the loop goes away.
上述显然不正确,生成的代码不受此更改的影响
The above is apparently incorrect, the generated code is not affected by this change.
或者,将 a 作为
int [N]
,并将循环体更改为
Alternatively, leave a
as int[N]
and change the loop body to
a[j] = 0;
++a[j];
,它会完全消失。
我的猜想是 clang
不愿意优化掉某些种类的undefined
My guess is that clang
is unwilling to optimize away certain kinds of undefined behaviour.
这篇关于为什么现代C ++编译器不能优化这样的简单循环? (Clang,MSVC)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!