为了与"abc"进行比较,我们目前会发出代码来测试uint16(前两个字节)是否等于uint16("ab"),然后检查第三个字节是否等于"c"。我怀疑将这三个字节加载到uint32的前三个字节中(两个加载操作结合|)会更高效,然后将其与uint32("abc\0")进行比较。我不确定我们是否可以使用比较组合重写规则来实现这一点(请注意,通常加载操作会产生副作用,但在这个例子中,我们确信它们不会导致故障),或者是否最好在生成此优化的walk.go文件中修复它。低优先级。
|
fgw7neuy1#
cc @mundaym,他一直在思考如何将分支合并到SSA规则中。
qcuzuvrc2#
棘手的一个问题。这种转换可能会减慢/膨胀一些代码(通常当 uint16(first two bytes)==uint16("ab") 不太可能时),所以虽然我认为后端可以做到,但我不确定它是否应该这样做,除非它有类似的可能性信息。
uint16(first two bytes)==uint16("ab")
请注意,对于较长的字符串,我们可以重叠负载,因为它们本来就是不对齐的(不确定我们是否已经这样做了 - 我并不认为我们在我看到的 walk 中这样做):
x == "abcdefg" -> x[0:4] == "abcd" && x[3:7] == "defg"
我认为这种转换可以贪婪地应用,因为它不会向“未采用”路径添加任何额外的指令。它还可以应用于任何我们想要检查字符串最后3个字符的情况,并且我们也知道字符串的长度大于3(即我们可以在字符串中访问索引-1并在边界内)。我怀疑这偶尔会在字符串 switch 语句降低中出现。即使已知要避免在竞争性代码中出现双重加载相关问题,重叠的字符也可以被掩盖。话虽如此,这在 SSA 中都会非常困难,但也许字符串比较降低可以做到这一点。
cedebl8k3#
重叠负荷是个好主意,谢谢!我们应该在步行时进行。
l3zydbqr4#
我刚刚(模糊地)想起几年前,由于它们干扰了加载-存储转发,重叠负载导致了性能问题。
bjp0bcyl5#
我刚刚(模糊地)想起几年前,由于它们干扰了load-store forwarding,重叠负载导致了性能问题。是的,这可能是一个问题。尽管Go程序不太倾向于按值复制字符串,因此我们可能不会经常看到load-hit-store hazards。我的猜测是,当我们比较它们时,字符串很少仍然在存储缓冲区中,但这只是我的猜测。
hujrc8aj6#
这也适用于整数小数组的比较;参见walkcompare。
6条答案
按热度按时间fgw7neuy1#
cc @mundaym,他一直在思考如何将分支合并到SSA规则中。
qcuzuvrc2#
棘手的一个问题。这种转换可能会减慢/膨胀一些代码(通常当
uint16(first two bytes)==uint16("ab")
不太可能时),所以虽然我认为后端可以做到,但我不确定它是否应该这样做,除非它有类似的可能性信息。请注意,对于较长的字符串,我们可以重叠负载,因为它们本来就是不对齐的(不确定我们是否已经这样做了 - 我并不认为我们在我看到的 walk 中这样做):
我认为这种转换可以贪婪地应用,因为它不会向“未采用”路径添加任何额外的指令。它还可以应用于任何我们想要检查字符串最后3个字符的情况,并且我们也知道字符串的长度大于3(即我们可以在字符串中访问索引-1并在边界内)。我怀疑这偶尔会在字符串 switch 语句降低中出现。即使已知要避免在竞争性代码中出现双重加载相关问题,重叠的字符也可以被掩盖。话虽如此,这在 SSA 中都会非常困难,但也许字符串比较降低可以做到这一点。
cedebl8k3#
重叠负荷是个好主意,谢谢!我们应该在步行时进行。
l3zydbqr4#
我刚刚(模糊地)想起几年前,由于它们干扰了加载-存储转发,重叠负载导致了性能问题。
bjp0bcyl5#
我刚刚(模糊地)想起几年前,由于它们干扰了load-store forwarding,重叠负载导致了性能问题。
是的,这可能是一个问题。尽管Go程序不太倾向于按值复制字符串,因此我们可能不会经常看到load-hit-store hazards。我的猜测是,当我们比较它们时,字符串很少仍然在存储缓冲区中,但这只是我的猜测。
hujrc8aj6#
这也适用于整数小数组的比较;参见walkcompare。