为什么 g++ 不优化局部数组而是优化全局数组?
Why does g++ not optimize a local array but a global?
我有以下两个函数,它们的作用基本相同:
enum Direction{
N = 0,
NW,
W,
SW,
S,
SE,
E,
NE,
TOTAL_DIRS
};
char const * const strings[] = {"N", "NW", "W", "SW", "S", "SE", "E", "NE"};
char const *
getDirString2(unsigned dir) {
if (TOTAL_DIRS > dir)
return strings[dir];
return nullptr;
}
char const *
getDirString3(unsigned dir) {
char const * const strings[] = {"N", "NW", "W", "SW", "S", "SE", "E", "NE"};
if (TOTAL_DIRS > dir)
return strings[dir];
return nullptr;
}
但是,虽然 g++ 优化了像我期望的那样使用全局数组的函数。它为替代方案创建了更多复杂的代码。Clang为两者创建相同的代码,如果我改用switch语句,clang和c ++也会创建与getDirString2
相同的代码。
这是编译器资源管理器 https://godbolt.org/z/GxvrTv 的链接
这是我应该为 g++ 提交错误报告的事情,还是有充分的理由?
我想你可以称之为错过的优化,尽管这对 gcc 的人来说有点苛刻。
GCC 在编译getDirString3
时,正在做你要求它做的事情 - 在堆栈上构造一个字符串数组,然后只返回它的一个元素。
另一方面,Clang 看到这个数组永远不会改变,而是在静态存储中构造它,请参阅:https://godbolt.org/z/24n-N7
要使 gcc 像 clang 一样生成代码,请将getDirString3
中的数组声明为static
(这首先是一个好主意),请参阅:https://godbolt.org/z/henD2Z
注意:起初,我说这是一个不符合标准的优化,但在评论中与Chris Dodd讨论后,我意识到这是部分不正确的。
更新的答案:
这是我应该为 g++ 提交错误报告的事情,还是有充分的理由?
clang 和 gcc 都可以做同样的优化,但默认情况下在 gcc 中是禁用的。所以这不是一个错误,这是有原因的。
叮当做了什么?
在您的示例中,编译器看到局部数组是常量,因此无需在每次调用函数时在堆栈上构造它。
如何在 gcc 中启用相同的优化?
要在 gcc 中启用相同的优化,请使用标志 -fmerge-all-constants。生成的代码将与 clang 的代码几乎相同(参见:https://godbolt.org/z/Ldx_qe):
getDirString3(unsigned int):
xor eax, eax
cmp edi, 7
ja .L1
mov edi, edi
mov rax, QWORD PTR strings.2080[0+rdi*8]
为什么在 gcc 中默认禁用它?
来自 gcc 文档网站:
-合并所有常量...像 C 或 C++ 这样的语言需要每个变量,包括同一变量的多个实例 递归调用,具有不同的位置,因此使用此选项 导致不符合项的行为。
在上面的示例中,优化是安全的,并且遵循 as-if 规则,因为未使用此本地数组的地址或与来自不同调用的地址进行比较。但是,似乎这种优化在某些情况下会导致非重叠行为。您可以检查这些情况:此处和此处。
那么,你应该使用 -fnmerge-all-constants 标志吗?
两个编译器都不会检查是否使用常量的地址,因此我不建议这样做。在您的示例中很明显,优化是安全的,但是您无法知道编译器每次都会在哪里进行优化(否则您将自己完成),并且您无法确定它不会导致有时不协调行为。
- 如何以优化的方式同时迭代两个间距不相等的数组
- C++数组与向量排序(在我的情况下,向量比数组慢~2.5倍(无优化))
- 优化 c++ 数组和向量
- 为什么优化大型 std::vector 数组会导致 SegFault?
- C++ C 样式字符串/字符数组的大小 - 优化
- C++优化从 int 到 float 的数组转换
- 当 95% 情况下的值为 0 或 1 时,对非常大的数组进行随机访问的任何优化
- 为什么 g++ 不优化局部数组而是优化全局数组?
- 数组初始化优化
- C++全局常量数组:是否保证合并(优化)到一个副本中
- 用于在数组中找到零并切换标志 更新另一个数组的循环的SSE优化
- 优化数组中的Bitshift
- 字节数组置换SSE优化
- C++是检查多维数组中匹配项的最佳优化方法
- 使用函数优化数组中的代码最大元素
- 优化只有3个不同值的数组?如何设计
- 如何通过常量优化数组乘法
- 优化C++中的字符数组成员交换
- C++ 指针到字节数组优化
- 为什么为了简单的数组访问,我必须在g++中打开优化