通知 c 或 c++ 编译器循环长度是 8 的倍数
Inform c or c++ compiler loop length is mutliple of 8
我想用 c++ 编写以下函数(使用 gcc 11.1 和 -O3 -mavx -std=c++17
进行编译)
void f( float * __restrict__ a, float * __restrict__ b, float * __restrict__ c, int64_t n) {
for (int64_t i = 0; i != n; ++i) {
a[i] = b[i] + c[i];
}
}
这会生成大约 60 行汇编代码,其中许多处理 n 不是 8 的倍数的情况。https://godbolt.org/z/61MYPG7an
我知道 n
始终是 8 的倍数。我可以更改此代码的一种方法是将 for (int64_t i = 0; i != n; ++i)
替换为 for (int64_t i = 0; i != (n / 8 * 8); ++i)
。这只会生成大约 20 条汇编指令。 https://godbolt.org/z/vhvdKMfE9
然而,在第二个godboltlink的第5行,有一条指令将n
的最低三位归零。如果有办法通知编译器 n
将始终是 8 的倍数,则可以省略该指令而不会改变行为。有谁知道在任何 c 或 c++ 编译器(尤其是 gcc 或 clang)上执行此操作的方法?就我而言,这实际上并不重要,但我很感兴趣,但不确定去哪里找。
用__builtin_unreachable
声明假设
void f(float *__restrict__ a, float *__restrict__ b, float *__restrict__ c, int64_t n) {
if(n % 8 != 0) __builtin_unreachable(); // control flow cannot reach this branch so the condition is not necessary and is optimized out
for (int64_t i = 0; i != n; ++i) { // if control flow reaches this point n is a multiple of 8
a[i] = b[i] + c[i];
}
}
这会产生 much shorter code。
我想用 c++ 编写以下函数(使用 gcc 11.1 和 -O3 -mavx -std=c++17
进行编译)
void f( float * __restrict__ a, float * __restrict__ b, float * __restrict__ c, int64_t n) {
for (int64_t i = 0; i != n; ++i) {
a[i] = b[i] + c[i];
}
}
这会生成大约 60 行汇编代码,其中许多处理 n 不是 8 的倍数的情况。https://godbolt.org/z/61MYPG7an
我知道 n
始终是 8 的倍数。我可以更改此代码的一种方法是将 for (int64_t i = 0; i != n; ++i)
替换为 for (int64_t i = 0; i != (n / 8 * 8); ++i)
。这只会生成大约 20 条汇编指令。 https://godbolt.org/z/vhvdKMfE9
然而,在第二个godboltlink的第5行,有一条指令将n
的最低三位归零。如果有办法通知编译器 n
将始终是 8 的倍数,则可以省略该指令而不会改变行为。有谁知道在任何 c 或 c++ 编译器(尤其是 gcc 或 clang)上执行此操作的方法?就我而言,这实际上并不重要,但我很感兴趣,但不确定去哪里找。
用__builtin_unreachable
void f(float *__restrict__ a, float *__restrict__ b, float *__restrict__ c, int64_t n) {
if(n % 8 != 0) __builtin_unreachable(); // control flow cannot reach this branch so the condition is not necessary and is optimized out
for (int64_t i = 0; i != n; ++i) { // if control flow reaches this point n is a multiple of 8
a[i] = b[i] + c[i];
}
}
这会产生 much shorter code。