"vperm v0,v0,v0,v17" with unused v0 有什么作用?
What does "vperm v0,v0,v0,v17" with unused v0 do?
我正在研究 SHA-256 implementation using Power8 built-ins。性能有点差。我估计它每字节关闭大约 2 个周期 (cpb)。
在块上执行 SHA 的 C/C++ 代码如下所示:
// Schedule 64-byte message
SHA256_SCHEDULE(W, data);
uint32x4_p8 a = abcd, e = efgh;
uint32x4_p8 b = VectorShiftLeft<4>(a);
uint32x4_p8 f = VectorShiftLeft<4>(e);
uint32x4_p8 c = VectorShiftLeft<4>(b);
uint32x4_p8 g = VectorShiftLeft<4>(f);
uint32x4_p8 d = VectorShiftLeft<4>(c);
uint32x4_p8 h = VectorShiftLeft<4>(g);
for (unsigned int i=0; i<64; i+=4)
{
const uint32x4_p8 k = VectorLoad32x4u(K, i*4);
const uint32x4_p8 w = VectorLoad32x4u(W, i*4);
SHA256_ROUND<0>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<1>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<2>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<3>(w,k, a,b,c,d,e,f,g,h);
}
我在 ppc64-le 机器上使用 -O3
和 -mcpu=power8
用 GCC 编译程序。当我查看反汇编时,我看到了其中的几个:
...
10000b0c: a6 03 09 7d mtctr r8
10000b10: 57 02 00 f0 xxswapd vs32,vs32
10000b14: 6b 04 00 10 vperm v0,v0,v0,v17
10000b18: 57 02 00 f0 xxswapd vs32,vs32
10000b1c: 99 57 00 7c stxvd2x vs32,0,r10
10000b20: 99 26 0c 7c lxvd2x vs32,r12,r4
10000b24: 57 02 00 f0 xxswapd vs32,vs32
10000b28: 6b 04 00 10 vperm v0,v0,v0,v17
10000b2c: 57 02 00 f0 xxswapd vs32,vs32
10000b30: 99 67 0a 7c stxvd2x vs32,r10,r12
10000b34: 99 26 0b 7c lxvd2x vs32,r11,r4
10000b38: 57 02 00 f0 xxswapd vs32,vs32
10000b3c: 6b 04 00 10 vperm v0,v0,v0,v17
10000b40: 57 02 00 f0 xxswapd vs32,vs32
10000b44: 99 5f 0a 7c stxvd2x vs32,r10,r11
10000b48: 99 26 05 7c lxvd2x vs32,r5,r4
10000b4c: 57 02 00 f0 xxswapd vs32,vs32
10000b50: 6b 04 00 10 vperm v0,v0,v0,v17
10000b54: 57 02 00 f0 xxswapd vs32,vs32
10000b58: 99 2f 0a 7c stxvd2x vs32,r10,r5
...
vperm v0,v0,v0,v17
看起来像死指令,因为 v0
在排列后没有使用。
vperm v0,v0,v0,v17
是做什么的?
C++ 源代码位于 sha256-p8.cxx
。
源文件是用g++ -g3 -O3 -Wall -DTEST_MAIN -mcpu=power8 sha256-2-p8.cxx -o sha256-2-p8.exe
编译的。
可在 PPC64 SHA-256 disassembly 获得完整的反汇编。
我认为上面的片段是由 SHA256_SCHEDULE
制作的。我在相关块之后看到 VectorShiftLeft
(vsldoi
) 的集合。
要更归零,我相当确定它是前 16 个单词的字节序交换器:
const uint8x16_p8 mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12};
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorPermute32x4(VectorLoad32x4u(data, i*4), mask), W, i*4);
SHA256_SCHEDULE
看起来像这样:
// +2 because Schedule reads beyond the last element
void SHA256_SCHEDULE(uint32_t W[64+2], const uint8_t* data)
{
#if (__LITTLE_ENDIAN__)
const uint8x16_p8 mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12};
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorPermute32x4(VectorLoad32x4u(data, i*4), mask), W, i*4);
#else
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorLoad32x4u(data, i*4), W, i*4);
#endif
// At i=62, W[i-2] reads the 65th and 66th elements. W[] has 2 extra "don't care" elements.
for (unsigned int i = 16; i < 64; i+=2)
{
const uint32x4_p8 s0 = Vector_sigma0(VectorLoad32x4u(W, (i-15)*4));
const uint32x4_p8 w0 = VectorLoad32x4u(W, (i-16)*4);
const uint32x4_p8 s1 = Vector_sigma1(VectorLoad32x4u(W, (i-2)*4));
const uint32x4_p8 w1 = VectorLoad32x4u(W, (i-7)*4);
const uint32x4_p8 r = vec_add(s1, vec_add(w1, vec_add(s0, w0)));
VectorStore32x4u(r, W, i*4);
}
}
这是相关部分的图片,其中 v0
突出显示。
乍一看,您已经完成了所有繁重的工作,该屏幕截图看起来很像是 LE endian swapper 部分。我假设你在这里。我希望 v17 是掩码变量——它在早些时候从 TOC 加载为 vs49。
您遗漏的关键信息是 v0 是 vs32(我知道这是无休止的混乱)。我不确定证明这一点的最佳地点在哪里,但 ABI 可以。您可以在这里下载:https://members.openpowerfoundation.org/document/dl/576.
图2-17。矢量寄存器作为 VSR 的一部分 第 44 页应该有助于说明我的意思,这就是硬件中的情况。
我正在研究 SHA-256 implementation using Power8 built-ins。性能有点差。我估计它每字节关闭大约 2 个周期 (cpb)。
在块上执行 SHA 的 C/C++ 代码如下所示:
// Schedule 64-byte message
SHA256_SCHEDULE(W, data);
uint32x4_p8 a = abcd, e = efgh;
uint32x4_p8 b = VectorShiftLeft<4>(a);
uint32x4_p8 f = VectorShiftLeft<4>(e);
uint32x4_p8 c = VectorShiftLeft<4>(b);
uint32x4_p8 g = VectorShiftLeft<4>(f);
uint32x4_p8 d = VectorShiftLeft<4>(c);
uint32x4_p8 h = VectorShiftLeft<4>(g);
for (unsigned int i=0; i<64; i+=4)
{
const uint32x4_p8 k = VectorLoad32x4u(K, i*4);
const uint32x4_p8 w = VectorLoad32x4u(W, i*4);
SHA256_ROUND<0>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<1>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<2>(w,k, a,b,c,d,e,f,g,h);
SHA256_ROUND<3>(w,k, a,b,c,d,e,f,g,h);
}
我在 ppc64-le 机器上使用 -O3
和 -mcpu=power8
用 GCC 编译程序。当我查看反汇编时,我看到了其中的几个:
...
10000b0c: a6 03 09 7d mtctr r8
10000b10: 57 02 00 f0 xxswapd vs32,vs32
10000b14: 6b 04 00 10 vperm v0,v0,v0,v17
10000b18: 57 02 00 f0 xxswapd vs32,vs32
10000b1c: 99 57 00 7c stxvd2x vs32,0,r10
10000b20: 99 26 0c 7c lxvd2x vs32,r12,r4
10000b24: 57 02 00 f0 xxswapd vs32,vs32
10000b28: 6b 04 00 10 vperm v0,v0,v0,v17
10000b2c: 57 02 00 f0 xxswapd vs32,vs32
10000b30: 99 67 0a 7c stxvd2x vs32,r10,r12
10000b34: 99 26 0b 7c lxvd2x vs32,r11,r4
10000b38: 57 02 00 f0 xxswapd vs32,vs32
10000b3c: 6b 04 00 10 vperm v0,v0,v0,v17
10000b40: 57 02 00 f0 xxswapd vs32,vs32
10000b44: 99 5f 0a 7c stxvd2x vs32,r10,r11
10000b48: 99 26 05 7c lxvd2x vs32,r5,r4
10000b4c: 57 02 00 f0 xxswapd vs32,vs32
10000b50: 6b 04 00 10 vperm v0,v0,v0,v17
10000b54: 57 02 00 f0 xxswapd vs32,vs32
10000b58: 99 2f 0a 7c stxvd2x vs32,r10,r5
...
vperm v0,v0,v0,v17
看起来像死指令,因为 v0
在排列后没有使用。
vperm v0,v0,v0,v17
是做什么的?
C++ 源代码位于 sha256-p8.cxx
。
源文件是用g++ -g3 -O3 -Wall -DTEST_MAIN -mcpu=power8 sha256-2-p8.cxx -o sha256-2-p8.exe
编译的。
可在 PPC64 SHA-256 disassembly 获得完整的反汇编。
我认为上面的片段是由 SHA256_SCHEDULE
制作的。我在相关块之后看到 VectorShiftLeft
(vsldoi
) 的集合。
要更归零,我相当确定它是前 16 个单词的字节序交换器:
const uint8x16_p8 mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12};
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorPermute32x4(VectorLoad32x4u(data, i*4), mask), W, i*4);
SHA256_SCHEDULE
看起来像这样:
// +2 because Schedule reads beyond the last element
void SHA256_SCHEDULE(uint32_t W[64+2], const uint8_t* data)
{
#if (__LITTLE_ENDIAN__)
const uint8x16_p8 mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12};
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorPermute32x4(VectorLoad32x4u(data, i*4), mask), W, i*4);
#else
for (unsigned int i=0; i<16; i+=4)
VectorStore32x4u(VectorLoad32x4u(data, i*4), W, i*4);
#endif
// At i=62, W[i-2] reads the 65th and 66th elements. W[] has 2 extra "don't care" elements.
for (unsigned int i = 16; i < 64; i+=2)
{
const uint32x4_p8 s0 = Vector_sigma0(VectorLoad32x4u(W, (i-15)*4));
const uint32x4_p8 w0 = VectorLoad32x4u(W, (i-16)*4);
const uint32x4_p8 s1 = Vector_sigma1(VectorLoad32x4u(W, (i-2)*4));
const uint32x4_p8 w1 = VectorLoad32x4u(W, (i-7)*4);
const uint32x4_p8 r = vec_add(s1, vec_add(w1, vec_add(s0, w0)));
VectorStore32x4u(r, W, i*4);
}
}
这是相关部分的图片,其中 v0
突出显示。
乍一看,您已经完成了所有繁重的工作,该屏幕截图看起来很像是 LE endian swapper 部分。我假设你在这里。我希望 v17 是掩码变量——它在早些时候从 TOC 加载为 vs49。
您遗漏的关键信息是 v0 是 vs32(我知道这是无休止的混乱)。我不确定证明这一点的最佳地点在哪里,但 ABI 可以。您可以在这里下载:https://members.openpowerfoundation.org/document/dl/576.
图2-17。矢量寄存器作为 VSR 的一部分 第 44 页应该有助于说明我的意思,这就是硬件中的情况。