2017-09-12 55 views
1

请原谅我对以下问题的无知。我们支持GCC 4.8(及以上)和IBM XL C/C++ 12(及以上)。我们还在AIX和Linux上支持big和little-endian。编译器和平台使代码相当混乱。如何将一个小常量载入一个向量?

我们希望将常量1加载到VSX寄存器中。这是我们已经能够制作的代码,但它似乎是错误的,因为它非常复杂。宏XLC_VERSION,GCC_VERSIONLITTLE_ENDIAN具有它们的习惯含义,所以导致它们的附加预处理器宏已被省略。

typedef __vector unsigned char  uint8x16_p8; 
typedef __vector unsigned long long uint64x2_p8; 

#if defined(XLC_VERSION) 
    typedef uint8x16_p8 VectorType; 
#elif defined(GCC_VERSION) 
    typedef uint64x2_p8 VectorType; 
#endif 

#if defined(LITTLE_ENDIAN) 
    const VectorType one = {1}; 
#else 
    const VectorType one = (VectorType)((uint64x2_p8){0,1}); 
#endif 

什么是不明显的是,XL C/C++支持所有的数据安排,并有一个丰富的API集。 IBM编译器很容易处理(当它不产生很难理解的警告和错误时)。

GCC回到4.8只支持64x2排列,它只有一个API子集。例如,GCC在8x16排列中缺少IBM API,而GCC没有vec_reve(这将使endian反转变得容易)。

我真正想要做的就是这样的事情,并将它“只是工作”无处不在,但它无法编译:

VectorType one = 1; 

是否有一个小常数加载到矢量不太复杂的方式寄存器?

+0

哦,你想加载1到每个矢量插槽?或只有一个? –

+0

@Jeremy - 只有一个;没有一个splat'd。我遇到的问题是,我们必须手动处理endian转换。例如,参见['rijndael.cpp':1152](https://github.com/weidai11/cryptopp/blob/master/rijndael-simd.cpp#L1152)。我想要一些不太复杂,更直观的东西,比如没有编译的语句。 – jww

+0

@Jeremy - 相信与否,我花了6个小时追踪AES/CTR模式下的一次失败自测。这是因为我想'VectorType one = 1;'所以我写了'VectorType one = {1};'。它在一台小型Linux机器上运行良好,但在一台大型AIX机器上失败。现在我想添加一个避免问题的控件。这个问题试图找到我可以放置的控制,以便将来不会出现问题。 – jww

回答

2

你的

VectorType one = 1; 

例如试图标量分配给一个载体。尝试使用矢量。对于16个字符的载体,这将是:

vector char one = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; 

gcc-4.8似乎编译这个好吧;我没有LE 4.8方便,但至少适用于big-endian:

0: 10 41 03 0c  vspltisb v2,1 

LE与gcc-5工作正常。

0: 0c 03 41 10  vspltisb v2,1 
2

您可能想要检查BCD_INIT示例here。它使用宏来反转向量初始化。

关于vec_reve:这是vec_perm的语法糖。您可以将其作为头文件中的内联函数或库函数实现,并将其用于没有它的编译器。

相关问题