我仍然试图让我的 1 到 2 cpb 脱离Power8 的 SHA 指令。此 C/C++ 代码将用户的消息复制到消息调度中:
void SHA256_SCHEDULE(uint32_t W[64+2], const uint8_t* D)
{
uint32_t* w = reinterpret_cast<uint32_t*>(W);
const uint32_t* d = reinterpret_cast<const uint32_t*>(D);
unsigned int i=0;
const uint8x16_p8 mask = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12};
for (i=0; i<16; i+=4, d+=4, w+=4)
VectorStore32x4u(VectorPermute32x4(VectorLoad32x4u(d, 0), mask), w, 0);
...
}
当我编译-O3
并查看反汇编时,我看到以下内容:
100008bc: 99 26 20 7c lxvd2x vs33,0,r4
...
100008d0: 57 0a 21 f0 xxswapd vs33,vs33
100008d8: 2b 08 21 10 vperm v1,v1,v1,v0
我相信正在发生的事情是:
- 负载发生在
100008bc
(lxvd2x
) - 预期转换发生在
100008d0
(xxswapd
) - 我的排列应用于
100008d8
(vperm
)
在 (1) 处,VSX 寄存器有值,但它是 little-endian 格式。元素 0 和 4 需要交换;元素 2 和 3 需要交换。
在 (2) 和 (3) 处应用了两个排列。这有点像在shuffle_epi32
x86shuffle_epi8
机器上调用。
PowerPC 的vec_perm
功能非常强大,任何两个排列都可以折叠成一个排列。
我的第一个问题是,为什么这两个排列没有被折叠成一个?
我的第二个问题是,如何强制编译器执行折叠?
我正在尽力避免内联汇编,因为代码支持 GCC、Clang 和 IBM 的 XL C/C++。IBM 的 XL C/C++ 不支持内联汇编以及 GCC 和 Clang,所以这将是一条痛苦的道路。
这是完整的反汇编:
0000000010000880 <SHA256_SCHEDULE(unsigned int*, unsigned char const*)>:
10000880: 03 10 40 3c lis r2,4099
10000884: 00 81 42 38 addi r2,r2,-32512
10000888: f0 ff c1 fb std r30,-16(r1)
1000088c: f8 ff e1 fb std r31,-8(r1)
10000890: fe ff 22 3d addis r9,r2,-2
10000894: 10 00 c4 3b addi r30,r4,16
10000898: 80 8e 29 39 addi r9,r9,-29056
1000089c: 10 00 e3 3b addi r31,r3,16
100008a0: 20 00 84 39 addi r12,r4,32
100008a4: 20 00 63 39 addi r11,r3,32
100008a8: 99 4e 00 7c lxvd2x vs32,0,r9
100008ac: 30 00 a3 38 addi r5,r3,48
100008b0: 40 00 23 39 addi r9,r3,64
100008b4: c4 ff c0 38 li r6,-60
100008b8: c0 ff e0 38 li r7,-64
100008bc: 99 26 20 7c lxvd2x vs33,0,r4
100008c0: 30 00 84 38 addi r4,r4,48
100008c4: f8 ff 00 39 li r8,-8
100008c8: e4 ff 40 39 li r10,-28
100008cc: 57 02 00 f0 xxswapd vs32,vs32
100008d0: 57 0a 21 f0 xxswapd vs33,vs33
100008d4: 97 05 00 f0 xxlnand vs32,vs32,vs32
100008d8: 2b 08 21 10 vperm v1,v1,v1,v0
100008dc: 57 0a 21 f0 xxswapd vs33,vs33
100008e0: 99 1f 20 7c stxvd2x vs33,0,r3
100008e4: 18 00 60 38 li r3,24
100008e8: a6 03 69 7c mtctr r3
100008ec: 99 f6 20 7c lxvd2x vs33,0,r30
100008f0: 57 0a 21 f0 xxswapd vs33,vs33
100008f4: 2b 08 21 10 vperm v1,v1,v1,v0
100008f8: 57 0a 21 f0 xxswapd vs33,vs33
100008fc: 99 ff 20 7c stxvd2x vs33,0,r31
10000900: 99 66 20 7c lxvd2x vs33,0,r12
10000904: 57 0a 21 f0 xxswapd vs33,vs33
10000908: 2b 08 21 10 vperm v1,v1,v1,v0
1000090c: 57 0a 21 f0 xxswapd vs33,vs33
10000910: 99 5f 20 7c stxvd2x vs33,0,r11
10000914: 99 26 20 7c lxvd2x vs33,0,r4
10000918: 57 0a 21 f0 xxswapd vs33,vs33
1000091c: 2b 08 01 10 vperm v0,v1,v1,v0
10000920: 57 02 00 f0 xxswapd vs32,vs32
10000924: 99 2f 00 7c stxvd2x vs32,0,r5
10000928: 00 00 00 60 nop
1000092c: 00 00 42 60 ori r2,r2,0
10000930: 99 36 09 7c lxvd2x vs32,r9,r6
10000934: 99 3e 89 7d lxvd2x vs44,r9,r7
10000938: 99 56 a9 7d lxvd2x vs45,r9,r10
1000093c: 99 46 29 7c lxvd2x vs33,r9,r8
10000940: 82 06 00 10 vshasigmaw v0,v0,0,0
10000944: 82 7e 21 10 vshasigmaw v1,v1,0,15
10000948: 80 60 00 10 vadduwm v0,v0,v12
1000094c: 80 68 00 10 vadduwm v0,v0,v13
10000950: 80 08 00 10 vadduwm v0,v0,v1
10000954: 99 4f 00 7c stxvd2x vs32,0,r9
10000958: 08 00 29 39 addi r9,r9,8
1000095c: d4 ff 00 42 bdnz 10000930 <SHA256_SCHEDULE(unsigned int*, unsigned char const*)+0xb0>
10000960: f0 ff c1 eb ld r30,-16(r1)
10000964: f8 ff e1 eb ld r31,-8(r1)
10000968: 20 00 80 4e blr
1000096c: 00 00 00 00 .long 0x0
10000970: 00 09 00 00 .long 0x900
10000974: 00 02 00 00 attn
10000978: 00 00 00 60 nop
1000097c: 00 00 42 60 ori r2,r2,0