我正在测试一台旧的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 Data Types手册有关于矢量数据类型的良好信息,但它没有讨论vector long long
何时可用。
__vector unsigned long long
的可用性是什么?我什么时候可以使用typedef?
TL:DR:看起来POWER7是AltiVec对64位元素大小的最低要求。这是VSX (Vector Scalar Extension)的一部分,维基百科确认首次出现在POWER7中。
gcc很可能知道它在做什么,并且能够以最低的-mcpu=
要求启用64位元素大小的向量内在函数。
#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
,第二个函数编译为返回两个64位整数寄存器。)
添加-mvsx
可以编译第二个函数。使用-mcpu=power7
也可以,但是power6没有。
source + asm on 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
而BTW,vec_splats
(splat标量)与常量编译为单个指令。但是使用运行时变量(例如函数arg),它会编译为整数存储/向量加载/向量 - splat(如vec_splat
内在函数)。显然,int-> vec没有一条指令。
vec_splat_s32
和相关的内在函数只接受一个小的(5位)常量,因此它们只在编译器可以使用相应的splat-immediate指令的情况下进行编译。
这个Intel SSE to PowerPC AltiVec migration看起来很好,但是错了(它声称vec_splats
splats一个有符号的字节)。