请在提交问题之前回答以下问题。谢谢!
您使用的Go版本是什么(go version
)?
2018年3月25日的最新主分支
这个问题是否在最新版本中重现?
尚未尝试
您正在使用什么操作系统和处理器架构(go env
)?
amd64/ubuntu16.04
您都做了什么?
测试提交4b00d3f#diff-6b1f55ed5d66ec08fb9cbe82259791e9
func ssa(a []int) bool {
return a[0] > a[1]
}
编译为
00000 (2) TEXT "".ssa(SB)
00001 (2) FUNCDATA $0, gclocals·4032f753396f2012ad1784f398b170f4(SB)
00002 (2) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
v13 00003 (2) MOVQ "".a+8(SP), AX
v9 00004 (3) TESTQ AX, AX
b1 00005 (3) JLS 13
v25 00006 (3) MOVQ "".a(SP), CX
v16 00007 (3) MOVQ (CX), DX
v3 00008 (3) CMPQ AX, $1
b2 00009 (3) JLS 13
v4 00010 (3) CMPQ 8(CX), DX
v27 00011 (3) SETLT "".~r1+24(SP)
b4 00012 (3) RET
v12 00013 (3) PCDATA $0, $1
v12 00014 (3) CALL runtime.panicindex(SB)
b3 00015 (3) UNDEF
00016 (?) END
这是预期的结果。但是
func ssb(a []int) (bool, bool) {
return a[0] > a[1], a[2] != a[3]
}
编译为
00000 (6) TEXT "".ssb(SB)
00001 (6) FUNCDATA $0, gclocals·4032f753396f2012ad1784f398b170f4(SB)
00002 (6) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
v7 00003 (6) MOVQ "".a+8(SP), AX
v4 00004 (7) TESTQ AX, AX
b1 00005 (7) JLS 24
v38 00006 (7) MOVQ "".a(SP), CX
v17 00007 (7) MOVQ (CX), DX
v16 00008 (7) CMPQ AX, $1
b2 00009 (7) JLS 24
v10 00010 (7) MOVQ 8(CX), BX
v12 00011 (7) CMPQ BX, DX
v24 00012 (7) CMPQ AX, $2
b4 00013 (7) JLS 24
v34 00014 (7) MOVQ 16(CX), SI
v33 00015 (7) CMPQ AX, $3
b5 00016 (7) JLS 24
v43 00017 (7) MOVQ 24(CX), AX
v8 00018 (7) CMPQ AX, SI
v40 00019 (7) CMPQ BX, DX
v46 00020 (7) SETLT "".~r1+24(SP)
v14 00021 (7) CMPQ AX, SI
v48 00022 (7) SETNE "".~r2+25(SP)
b6 00023 (7) RET
v13 00024 (7) PCDATA $0, $1
v13 00025 (7) CALL runtime.panicindex(SB)
b3 00026 (7) UNDEF
00027 (?) END
这里的问题:
- 一个死掉的"v8 00018 (7) CMPQ AX, SI"没有被消除
- CMPQmem的使用不符合预期
3条答案
按热度按时间3df52oht1#
@josharian @cznic @randall77
3duebb1j2#
看起来在执行flagalloc之后,https://go-review.googlesource.com/86035 pass可以生成DEAD ops,并且在执行flagalloc之后我们不会运行late deadcode,这解释了1。
6yt4nkrj3#
对于你的第一点,当flagalloc需要"溢出"和"恢复"标志时,它总是留下旧的标志计算。消除这些比较应该不会太困难。甚至不需要完整的死代码传递,因为我们知道比较的参数仍然在使用。
对于你的第二点,这基本上是按预期工作的。CMPQmem被生成,但它们需要在flagalloc期间撤销。问题在于我们首先安排CMPQmem,然后为边界检查安排一个CMPQ。由于边界检查覆盖了标志,flagalloc必须将标志计算推迟到后面,但它认为将加载推迟到后面是不安全的(在这种情况下是安全的,但在一般情况下不是)。
我不知道我们是否应该通过使调度更智能(提前安排边界检查,也许?)来修复这个问题,或者教flagalloc何时可以安全地将加载推迟到后面。