如下代码所示,为什么uint32_t阻止编译器(GCC 12.1 + O3)通过自动矢量化进行优化。见哥德波特。
#include <cstdint>
// no auto vectorization
void test32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
for (uint32_t i = from; i < to; i++) {
array[nread++] = i;
}
}
// auto vectorization
void test64(uint32_t *array, uint64_t &nread, uint32_t from, uint32_t to) {
for (uint32_t i = from; i < to; i++) {
array[nread++] = i;
}
}
// no auto vectorization
void test_another_32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
uint32_t index = nread;
for (uint32_t i = from; i < to; i++) {
array[index++] = i;
}
nread = index;
}
// auto vectorization
void test_another_64(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to) {
uint64_t index = nread;
for (uint32_t i = from; i < to; i++) {
array[index++] = i;
}
nread = index;
}在运行命令g++ -O3 -fopt-info-vec-missed -c test.cc -o /dev/null之后,我得到了以下结果。怎么解释呢?
bash> g++ -O3 -fopt-info-vec-missed -c test.cc -o /dev/null
test.cc:5:31: missed: couldn't vectorize loop
test.cc:6:24: missed: not vectorized: not suitable for scatter store *_5 = i_18;
test.cc:21:31: missed: couldn't vectorize loop
test.cc:22:24: missed: not vectorized: not suitable for scatter store *_4 = i_22;发布于 2022-06-25 06:38:35
看看这个函数
void test32(uint32_t *array, uint32_t &nread, uint32_t from, uint32_t to)如果你这样称呼它,它应该如何表现:
uint32_t arr[16];
test32(arr, arr[3], &arr[0], &arr[15]);这叫做混叠。nread参数可能会别名来自array的元素,因为它们具有相同的类型。但当你有
void test64(uint32_t *array, uint64_t &nread, uint32_t from, uint32_t to)这样就不会出现混叠,因为uint32_t和uint64_t永远不会有相同的地址。
注意:传递对函数的引用在内部传递地址,因此它相当于别名参数的指针。
有一些特殊规则的类型称为混叠类型。C++标准说,您可以将uint32_t*强制转换为char*,然后访问uint32_t底层的原始内存。这意味着uint32_t*和char*可以合法地指向同一个地址。char*是一种别名类型,因为它与任何其他类型的(数据)指针别名。unsigned char*或包括std::byte在内的char的任何其他变体也是如此。
但是,您可以告诉编译器,即使类型允许使用限制,也不允许有2个指针别名。
void test32(uint32_t *array, uint32_t & restrict nread, uint32_t from, uint32_t to)PS:test_another_32看起来像是一个漏掉的编译器优化。
https://stackoverflow.com/questions/72751322
复制相似问题