Что такое "вектор длинная длинная"?

Я тестирую на старом PowerMac G5, который является машиной Power4. Сборка не выполняется:

$ make
...
g++ -DNDEBUG -g2 -O3 -mcpu=power4 -maltivec -c ppc-simd.cpp
ppc-crypto.h:36: error: use of 'long long' in AltiVec types is invalid
make: *** [ppc-simd.o] Error 1

Ошибка связана с:

typedef __vector unsigned long long uint64x2_p8;

У меня проблемы с определением, когда я должен сделать typedef доступным. С -mcpu=power4 -maltivec машина сообщает о 64-битной доступности:

$ gcc -mcpu=power4 -maltivec -dM -E - </dev/null | sort | egrep -i -E 'power|ARCH'
#define _ARCH_PPC 1
#define _ARCH_PPC64 1
#define __POWERPC__ 1

OpenPOWER | 6.1. Руководство " Векторные типы данных" содержит хорошую информацию о векторных типах данных, но не обсуждает, когда vector long long доступны.

Что такое наличие __vector unsigned long long? Когда я могу использовать typedef?

1 ответ

Решение

TL:DR: похоже, что POWER7 является минимальным требованием для 64-битного размера элемента с AltiVec. Это часть VSX (Vector Scalar Extension), которая, как подтверждает Википедия, впервые появилась в POWER7.


Весьма вероятно, что gcc знает, что делает, и позволяет использовать 64-битные векторные элементы с минимальным размером элемента -mcpu= требование.

#include <altivec.h>

auto vec32(void) {       // compiles with your options: Power4
    return vec_splats((int) 1);
}

// gcc error: use of 'long long' in AltiVec types is invalid without -mvsx
vector long long vec64(void) {
    return vec_splats((long long) 1);
}

auto вместо vector long long, 2-ая функция компилируется в возвращение в двух 64-битных целочисленных регистрах.)

Добавление -mvsx позволяет 2-й функции скомпилировать. С помощью -mcpu=power7 тоже работает, но power6 нет.

source + asm на Godbolt (PowerPC64 gcc6.3)

# with auto without VSX:
vec64():     # -O3 -mcpu=power4 -maltivec -mregnames
    li %r4,1
    li %r3,1
    blr

vec64():  # -O3 -mcpu=power7 -maltivec -mregnames
.LCF2:
0:  addis 2,12,.TOC.-.LCF2@ha
    addi 2,2,.TOC.-.LCF2@l
    addis %r9,%r2,.LC0@toc@ha
    addi %r9,%r9,.LC0@toc@l       # PC-relative addressing for static constant, I think.
    lxvd2x %vs34,0,%r9            # vector load?
    xxpermdi %vs34,%vs34,%vs34,2
    blr


 .LC0:    # in .rodata
    .quad   1
    .quad   1

И кстати, vec_splats (скаляр сплат) с константой компилируется в одну инструкцию. Но с переменной времени выполнения (например, функцией arg), она компилируется в целочисленный store / vector load / vector-splat (например, vec_splat внутренняя). Видимо, нет ни одной инструкции для int->vec.

vec_splat_s32 и связанные встроенные функции принимают только небольшую (5-битную) константу, поэтому они компилируются только в тех случаях, когда компилятор может использовать соответствующую инструкцию, указывающую на сплат.

Эта миграция Intel SSE в PowerPC AltiVec выглядит в основном хорошо, но ошиблась (она утверждает, что vec_splats выдаёт подписанный байт).

Другие вопросы по тегам