6

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

4

2 回答 2

4

如果有问题的数据是静态分配的,那么您可以使用__align__GCC 支持的属性来指定它应该与必要的边界对齐。如果您正在动态分配这些数组,您可以通过对齐值过度分配,然后将返回的指针提升到您需要的对齐。

posix_memalign()如果您使用的系统支持该功能,您也可以使用该功能。最后要注意的是,malloc()分配的内存总是会按照最大的内置类型的大小对齐,一般8字节为double。如果你不需要比这更好的,那么malloc就足够了。

编辑:如果您修改分配代码以强制该检查为真(即,如上所述,过度分配),编译器应该通过不对循环代码进行条件化来强制执行。如果您需要与 8 字节边界对齐,看起来,这将类似于a = (a + 7) & ~3;.

于 2009-11-10T03:58:43.107 回答
0

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

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

GCC 在这里做了一些聪明的事情。它强制数组ab16 字节对齐。它不会这样做c,大概是因为c从未在可矢量化循环中使用过。

于 2009-11-20T08:10:11.967 回答