使用GCC进行循环版本控制

时间:2009-11-10 03:29:37

标签: gcc alignment simd vectorization

我正在使用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')来完成的。现在不使用内在函数和其他属性,我应该如何只获得矢量化代码(没有这个运行时对齐检查。)

2 个答案:

答案 0 :(得分:4)

如果有问题的数据是静态分配的,那么您可以使用GCC支持的__align__属性来指定它应该与必要的边界对齐。如果要动态分配这些数组,则可以按对齐值进行过度分配,然后将返回的指针向上移动到所需的对齐方式。

如果您使用支持它的系统,也可以使用posix_memalign()功能。最后,请注意malloc()将始终分配与最大内置类型的大小对齐的内存,通常为double的8个字节。如果你不需要更好,那么malloc就足够了。

编辑:如果您修改分配代码以强制该检查为真(即,如上所述,请进行分配),编译器应该通过不条件化循环代码来强制执行。如果你需要对齐一个8字节的边界,就像看起来那样a = (a + 7) & ~3;

答案 1 :(得分:0)

我只使用您的确切代码以及以下选项}

我的GCC版本为gcc -march=core2 -c -O2 -fdump-tree-optimized -ftree-vectorize vec.c

海湾合作委员会正在做一些聪明的事情。它强制数组gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8)a对齐16字节。它不会对b执行此操作,可能是因为c从未在可向量化的循环中使用。