【发布时间】:2018-01-19 23:05:51
【问题描述】:
考虑以下代码:
void foo(float* __restrict__ a)
{
int i; float val;
for (i = 0; i < 100; i++) {
val = 2 * i;
a[i] = val;
}
}
void bar(float* __restrict__ a)
{
int i; float val = 0.0;
for (i = 0; i < 100; i++) {
a[i] = val;
val += 2.0;
}
}
它们基于 Agner Fog 的 Optimizing software in C++ 中的示例 7.26a 和 7.26b,并且应该做同样的事情; bar 更“高效”,因为我们不会在每次迭代时进行整数到浮点数的转换,而是更便宜的浮点数加法(在 x86_64 上)。
Here 是这两个函数的 clang 和 gcc 结果(没有矢量化和展开)。
问题:在我看来,用添加一个常数值替换循环索引的乘法的优化 - 当这是有益的 - 应该由编译器执行,即使(或者特别是如果)有一个涉及类型转换。为什么这两个函数没有发生这种情况?
注意,如果我们使用int而不是float:
void foo(int* __restrict__ a)
{
int i; int val = 0;
for (i = 0; i < 100; i++) {
val = 2 * i;
a[i] = val;
}
}
void bar(int* __restrict__ a)
{
int i; int val = 0;
for (i = 0; i < 100; i++) {
a[i] = val;
val += 2;
}
}
clang 和 gcc 都执行预期的优化,尽管方式不完全相同(请参阅 this question)。
【问题讨论】:
标签: gcc type-conversion clang compiler-optimization