2

我正在一台旧的 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?

4

1 回答 1

1

TL:DR:看起来 POWER7 是使用 AltiVec 的 64 位元素大小的最低要求。这是VSX(向量标量扩展)的一部分,维基百科确认它首次出现在 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让第二个函数编译。using-mcpu=power7也可以,但 power6 不行。

Godbolt 上的源 + asm (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带有常量的(splat scalar)编译成一条指令。但是使用运行时变量(例如函数 arg),它会编译为整数存储/向量加载/向量-splat(如vec_splat内在函数)。显然,int->vec 没有一条指令。

和相关的vec_splat_s32内在函数接受一个小的(5 位)常量,因此它们仅在编译器可以使用相应的 splat-immediate 指令的情况下编译。

这个英特尔 SSE 到 PowerPC AltiVec 的迁移看起来大部分都不错,但是弄错了(它声称会vec_splats释放一个有符号字节)。

于 2017-12-26T02:26:36.560 回答