在Powerpc上,有没有相当于intel的movemask内在函数?

时间:2015-11-26 12:20:18

标签: simd powerpc altivec

我想将__vector bool long long中的所有元素合并到一个int中,其中每个位都设置为输入向量的最高位

示例:

__vector bool long long vcmp = vec_cmplt(a, b);
int packedmask = /*SOME FUNCTION GOES HERE*/ (vcmp);

packedmask = x|y|0000000000000000....

其中x等于1,如果vcmd [0] = 0XFFFFF ...或0如果vcmp [0] = 0; 同样的y。

在intel上,我们可以通过使用_mm_movemask指令(intrinsic for intel)来实现这一点

有没有办法在PowerPC上做同样的事情?

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

您可以尝试这样的事情:

typedef __vector uint8_t v128_u8;
typedef __vector uint32_t v128_u32;

const v128_u8 KS = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128};
const v128_u8 K0 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const v128_u8 K1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
//const v128_u8 KP = {0, 8, 4, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};//little endian
const v128_u8 KP = {3, 11, 7, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};//big-endian

unit Tmp
{
     uint32_t u32;
     uint16_t u16[2];
};

uint16_t vec_movemask(v128_u8 value)
{
    Tmp tmp
    tmp.u32 = vec_extract(vec_perm(vec_msum(vec_and(value, KS), K1, K0), KP), 0);
    return tmp.u16[0] + tmp.u16[2];
}

详细说明:

value:
{0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff , 0x00, 0xff, 0x00, 0xff};
vec_and(value, KS):
{0x00, 0x02, 0x00, 0x00, 0x10, 0x20, 0x00, 0x80, 0x00, 0x00, 0x04, 0x08 , 0x00, 0x20, 0x00, 0x80};
vec_msum(vec_and(value, KS), K1, K0):
{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x0C , 0x00, 0x00, 0x00, 0xA0};
vec_perm(vec_msum(vec_and(value, KS), K1, K0):
{0x02, 0x0C, 0xB0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00};
vec_extract(vec_perm(vec_msum(vec_and(value, KS), K1, K0):
{0x02, 0x0C, 0xB0, 0xA0}
tmp.u16[0] + tmp.u16[2]:
{0xB2, 0xAC}

答案 1 :(得分:2)

听起来像vbpermq指令(和vec_vbpermq()内在的)在这里是合适的。给定无符号字符“指示”(即0-128)的向量,它使用这些索引将一个位选择为输出向量。如果索引大于128,则使用零位。

对16个结果位进行零扩展,以在结果向量的第一个双字中形成64位值。

这样的事情可行:

/*
 * our permutation indicies: the MSbit from the first bool long long,
 * then the MSbit from the second bool long long, then the rest as
 * >=128 (which gives a zero bit in the result vector)
 */
vector unsigned char perm = { 0, 64, 128, 128, 128, /*...*/};

/* compare the two-item vector into two bools */
vcmp = (vector unsigned char)vec_cmplt(a, b);

/* select a bit from each of the result bools */
result = vec_vbpermq(vcmp, perm);

从结果向量中获取int将取决于您要对其执行的操作。如果您需要它,vec_extract(result, 0)可能有效,但由于您只对结果的前两位感兴趣,您可以简化perm常数,和/或根据需要移动结果

另外,请注意结果的字节序注意事项。

PowerISA中第5.15节描述了

vbpermq