Closed
Description
package p
func f(s, t []byte) {
x := copy(s, t)
_ = s[x:]
}
compiles to
"".f t=1 size=122 args=0x30 locals=0x28
0x0000 00000 (x.go:3) TEXT "".f(SB), $40-48
0x0000 00000 (x.go:3) MOVQ (TLS), CX
0x0009 00009 (x.go:3) CMPQ SP, 16(CX)
0x000d 00013 (x.go:3) JLS 115
0x000f 00015 (x.go:3) SUBQ $40, SP
0x0013 00019 (x.go:3) MOVQ BP, 32(SP)
0x0018 00024 (x.go:3) LEAQ 32(SP), BP
0x001d 00029 (x.go:3) FUNCDATA $0, gclocals·5bdb7effe3ac48180ac4cdf9d49dc4dd(SB)
0x001d 00029 (x.go:3) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB)
0x001d 00029 (x.go:4) MOVQ "".s+56(FP), AX
0x0022 00034 (x.go:4) MOVQ "".t+80(FP), CX
0x0027 00039 (x.go:4) CMPQ AX, CX
0x002a 00042 (x.go:4) JLE 110
0x002c 00044 (x.go:4) MOVQ CX, "".x+24(SP)
0x0031 00049 (x.go:4) MOVQ "".s+48(FP), DX
0x0036 00054 (x.go:4) MOVQ DX, (SP)
0x003a 00058 (x.go:4) MOVQ "".t+72(FP), DX
0x003f 00063 (x.go:4) MOVQ DX, 8(SP)
0x0044 00068 (x.go:4) MOVQ CX, 16(SP)
0x0049 00073 (x.go:4) PCDATA $0, $0
0x0049 00073 (x.go:4) CALL runtime.memmove(SB)
0x004e 00078 (x.go:5) MOVQ "".x+24(SP), AX
0x0053 00083 (x.go:5) MOVQ "".s+56(FP), CX
0x0058 00088 (x.go:5) CMPQ AX, CX
0x005b 00091 (x.go:5) JHI $0, 103
0x005d 00093 (x.go:6) MOVQ 32(SP), BP
0x0062 00098 (x.go:6) ADDQ $40, SP
0x0066 00102 (x.go:6) RET
0x0067 00103 (x.go:5) PCDATA $0, $1
0x0067 00103 (x.go:5) CALL runtime.panicslice(SB)
0x006c 00108 (x.go:5) UNDEF
0x006e 00110 (x.go:4) MOVQ AX, CX
0x0071 00113 (x.go:4) JMP 44
0x0073 00115 (x.go:4) NOP
0x0073 00115 (x.go:3) CALL runtime.morestack_noctxt(SB)
0x0078 00120 (x.go:3) JMP 0
Observe the bounds check on _ = s[x:]
. In comparison, using _ = s[len(s):]
doesn't generate a bounds check. But the semantics of copy
guarantee that x <= len(s)
. So we should be able to eliminate the check.
See CL 27460 for a concrete instance in the runtime.