如果以下代码在支持无对齐加载/存储的平台上是等价的(386, amd64, arm64, ppc64le, s390x...),那就太好了。我在这些例子中使用了XOR,但对于其他逻辑运算符也是如此:
(1)
binary.LittleEndian.PutUint32(dst, binary.LittleEndian.Uint32(src) ^ x)
(2)
dst[0] = src[0] ^ byte(x)
dst[1] = src[1] ^ byte(x>>8)
dst[2] = src[2] ^ byte(x>>16)
dst[3] = src[3] ^ byte(x>>24)
(3) [不太重要]
x ^= uint32(src[0])
x ^= uint32(src[1]) << 8
x ^= uint32(src[2]) << 16
x ^= uint32(src[3]) << 24
binary.LittleEndian.PutUint32(dst, x)
目前(1)在具有无对齐加载的平台上是最优的,而(2)在其他平台上是最优的。如果编译器能将(2)优化为(1),那就太好了。我将(3)作为当前规则次优的情况添加进来。
如果这样做了,它将有助于简化通用的 golang.org/x/crypto/internal/chacha20
实现。
3条答案
按热度按时间eimct9ow1#
我认为我遗漏了一些东西:为什么(1)在其他平台上不是最优的?
uplii1fm2#
示例(1)等同于以下包含额外3个移位的代码:
另一方面,由于移位寄存器输入,这实际上在arm上并不会产生更多的指令。尽管如此,mips上的汇编语言从(2)中受益更多。我不知道是否存在速度差异。
dnph8jn43#
看起来(1)是我们期望人们写的代码,它可能比(2)更容易识别和重写。(通常,数学运算的分发比取消分发更容易,尤其是不带传递性的二进制运算。)