我正在和GCC一起研究自动矢量化。由于客户的要求,我不能使用内部函数或属性。(我无法获得支持矢量化的用户输入)
如果可以矢量化的数组的对齐信息是未知的,则GCC调用一个循环版本控制的过程。在树上执行循环向量化时,将执行循环版本控制。当一个循环被识别为可矢量化,并且数据对齐或数据依赖的约束阻碍了它时(因为它们不能在编译时确定),那么将生成该循环的两个版本。这些是循环的矢量化和非矢量化版本,以及对齐或依赖的运行时检查,以控制执行哪个版本。
我的问题是,我们必须如何执行对齐?如果我发现了一个可向量化的循环,我不应该生成该循环的两个版本,因为缺少对齐信息。
例如。考虑下面的代码
short a[15]; short b[15]; short c[15];
int i;
void foo()
{
for (i=0; i<15; i++)
{
a[i] = b[i] ;
}
}树转储(选项:-fdump- Tree -optimized -ftree-vectorize)
<SNIP>
vector short int * vect_pa.49;
vector short int * vect_pb.42;
vector short int * vect_pa.35;
vector short int * vect_pb.30;
bb 2>:
vect_pb.30 = (vector short int *) &b;
vect_pa.35 = (vector short int *) &a;
if (((signed char) vect_pa.35 | (signed char) vect_pb.30) & 3 == 0) ;; <== (A)
goto <bb 3>;
else
goto <bb 4>;
bb 3>:
</SNIP>在'bb 3‘版本的矢量化代码被生成。在没有矢量化的情况下生成'bb 4‘代码。这些都是通过检查对齐来完成的(语句'A')。现在,在不使用内部函数和其他属性的情况下,我应该如何只获得矢量化的代码(没有运行时对齐检查)。
发布于 2009-11-10 11:58:43
如果有问题的数据是静态分配的,那么您可以使用GCC支持的__align__属性来指定它应该与必要的边界对齐。如果要动态分配这些数组,则可以按对齐值进行过度分配,然后将返回的指针向上调整为所需的对齐方式。
如果您在支持posix_memalign()函数的系统上,也可以使用它。最后,请注意,malloc()分配的内存总是与最大的内置类型的大小对齐,通常是8字节的双精度类型。如果你不需要比这更好的东西,那么malloc就足够了。
编辑:如果你修改你的分配代码以强制检查为真(如上面所建议的过度分配),编译器应该不对循环代码进行条件化。如果您需要对齐到8字节的边界,就像看起来那样,这将类似于a = (a + 7) & ~3;。
发布于 2009-11-20 16:10:12
我只得到了循环的一个版本,使用您的带有以下选项的精确代码:gcc -march=core2 -c -O2 -fdump-tree-optimized -ftree-vectorize vec.c
我的版本的GCC是gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8)。
在这里,GCC正在做一些聪明的事情。它强制数组a和b与16字节对齐。它不会对c这样做,大概是因为c从未在可向量化的循环中使用过。
https://stackoverflow.com/questions/1705468
复制相似问题