Версии петли с GCC - PullRequest
5 голосов
/ 10 ноября 2009

Я работаю над автоматической векторизацией с 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' генерируется код без векторизации. Это делается путем проверки выравнивания (утверждение «А»). Теперь без использования встроенных функций и других атрибутов, как мне получить только векторизованный код (без этой проверки выравнивания во время выполнения).

Ответы [ 2 ]

4 голосов
/ 10 ноября 2009

Если рассматриваемые данные размещаются статически, то вы можете использовать атрибут __align__, который поддерживает GCC, чтобы указать, что он должен быть выровнен по необходимой границе. Если вы динамически выделяете эти массивы, вы можете перераспределить их по значению выравнивания, а затем увеличить возвращаемый указатель до нужного выравнивания.

Вы также можете использовать функцию posix_memalign(), если вы работаете в системе, которая ее поддерживает. Наконец, обратите внимание, что malloc() всегда будет выделять память, выровненную по размеру самого большого встроенного типа, обычно 8 байтов для двойного. Если вам не нужно лучше, то malloc должно быть достаточно.

Редактировать : Если вы измените свой код выделения, чтобы заставить эту проверку быть истинной (то есть, перераспределить, как предложено выше), компилятор должен выполнить задачу, не обусловливая код цикла. Если вам нужно выравнивание по 8-байтовой границе, то, похоже, это будет что-то вроде a = (a + 7) & ~3;.

0 голосов
/ 20 ноября 2009

Я получаю только одну версию цикла, , используя ваш точный код с этими параметрами: 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 никогда не используется в векторизуемом цикле.

...