Что такое "вектор длинная длинная"?
Я тестирую на старом 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
выдаёт подписанный байт).