使用GCC进行循环版本控制

使用GCC进行循环版本控制,gcc,alignment,simd,vectorization,Gcc,Alignment,Simd,Vectorization,我正在使用GCC进行自动矢量化。由于客户的要求,我不能使用本质或属性。(我无法获取支持矢量化的用户输入) 如果可以矢量化的数组的对齐信息未知,GCC将调用“循环版本控制”过程。在树上完成循环向量化时,将执行循环版本控制。当一个循环被标识为可向量化,并且对数据对齐或数据依赖性的约束阻碍了它(因为它们不能在编译时确定),那么将生成两个版本的循环。这些是循环的矢量化和非矢量化版本,以及运行时检查是否对齐或依赖以控制执行哪个版本 我的问题是,我们必须如何执行对齐?如果我发现了一个可矢量化的循环,我不应该

我正在使用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] ;
    }
}
short a[15];短b[15];短c[15];
int i;
void foo()
{
对于(i=0;i:
向量pb.30=(向量短整型*)&b;
向量pa.35=(向量短整型*)&a;
如果((有符号字符)vect_pa.35 |(有符号字符)vect_pb.30)&3==0);:

在“bb 3”生成矢量化代码的版本。在“bb 4”生成没有矢量化的代码。这些都是通过检查对齐方式(语句“A”)完成的。现在,如果不使用内部函数和其他属性,我应该如何仅获取矢量化代码(没有此运行时对齐方式检查)

如果所讨论的数据是静态分配的,那么您可以使用GCC支持的
\uuuuu align\uuuu
属性来指定它应该与必要的边界对齐。如果您是动态分配这些数组,您可以通过对齐值进行过度分配,然后将返回的指针向上撞到对齐位置你需要

如果您在支持它的系统上,也可以使用
posix_memalign()
函数。最后,请注意
malloc()
将始终按照最大内置类型的大小分配内存,通常双精度为8字节。如果您不需要更好的,那么
malloc
就足够了


编辑:如果您修改分配代码以强制该检查为真(即,如上所述,过度分配),编译器应该通过不限制循环代码来满足。如果您需要对齐到8字节边界,就像看起来的那样,这类似于
a=(a+7)&~3;

我只得到一个循环版本,使用您的精确代码和以下选项:
gcc-march=core2-c-O2-fdump tree optimized-ftree vectorize vec.c

我的GCC版本是
GCC版本4.4.1(Ubuntu 4.4.1-4ubuntu8)


GCC在这里做了一些聪明的事情。它强制数组
a
b
以16字节对齐。它对
c
不这样做,可能是因为
c
从来没有在可向量化循环中使用过。

如果使用
posix_memalign()
,可能会确保使用
int*\u attribute\uuuu((对齐)声明变量(二十) ))ptr
可能它没有生成2个版本的循环,因为您告诉gcc您正在使用
-march=core2
选项瞄准一台特定的机器,这意味着gcc可以自由忽略任何不支持
core2
支持的CPU,而core2确实支持适当的SSE/SSE2(事实上,还有更多)矢量化说明。当你在调用中省略
-march=core2
选项时,你会得到不同的输出吗?好吧,问题(和我的答案)中提到的特定类型的版本控制是由于对齐,而不是架构(这是三年前的事了;我的Ubuntu盒不再方便了……)
<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>