go cmd/compile: less optimized AMD64 code

abithluo  于 5个月前  发布在  Go
关注(0)|答案(3)|浏览(59)

请在提交问题之前回答以下问题。谢谢!

您使用的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

这里的问题:

  1. 一个死掉的"v8 00018 (7) CMPQ AX, SI"没有被消除
  2. CMPQmem的使用不符合预期
3df52oht

3df52oht1#

@josharian @cznic @randall77

3duebb1j

3duebb1j2#

看起来在执行flagalloc之后,https://go-review.googlesource.com/86035 pass可以生成DEAD ops,并且在执行flagalloc之后我们不会运行late deadcode,这解释了1。

6yt4nkrj

6yt4nkrj3#

对于你的第一点,当flagalloc需要"溢出"和"恢复"标志时,它总是留下旧的标志计算。消除这些比较应该不会太困难。甚至不需要完整的死代码传递,因为我们知道比较的参数仍然在使用。

对于你的第二点,这基本上是按预期工作的。CMPQmem被生成,但它们需要在flagalloc期间撤销。问题在于我们首先安排CMPQmem,然后为边界检查安排一个CMPQ。由于边界检查覆盖了标志,flagalloc必须将标志计算推迟到后面,但它认为将加载推迟到后面是不安全的(在这种情况下是安全的,但在一般情况下不是)。

我不知道我们是否应该通过使调度更智能(提前安排边界检查,也许?)来修复这个问题,或者教flagalloc何时可以安全地将加载推迟到后面。

相关问题