-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
The Go compiler currently appears to be able to eliminate some amount of dead code that can be detected after inlining. However, it appears that escape analysis fails to take this into account. Take this program as an example:
package main
var g any
func foo(ptr *int, b bool) {
if b {
g = ptr
}
}
func main() {
a := 1
foo(&a, false)
}This generates the following assembly:
main.main STEXT size=46 args=0x0 locals=0x18 funcid=0x0 align=0x0
0x0000 00000 (main.go:11) TEXT main.main(SB), ABIInternal, $24-0
0x0000 00000 (main.go:11) CMPQ SP, 16(R14)
0x0004 00004 (main.go:11) PCDATA $0, $-2
0x0004 00004 (main.go:11) JLS 39
0x0006 00006 (main.go:11) PCDATA $0, $-1
0x0006 00006 (main.go:11) PUSHQ BP
0x0007 00007 (main.go:11) MOVQ SP, BP
0x000a 00010 (main.go:11) SUBQ $16, SP
0x000e 00014 (main.go:11) FUNCDATA $0, gclocals·FzY36IO2mY0y4dZ1+Izd/w==(SB)
0x000e 00014 (main.go:11) FUNCDATA $1, gclocals·FzY36IO2mY0y4dZ1+Izd/w==(SB)
0x000e 00014 (main.go:12) LEAQ type:int(SB), AX
0x0015 00021 (main.go:12) PCDATA $1, $0
0x0015 00021 (main.go:12) CALL runtime.newobject(SB)
0x001a 00026 (main.go:12) MOVQ $1, (AX)
0x0021 00033 (main.go:14) ADDQ $16, SP
0x0025 00037 (main.go:14) POPQ BP
0x0026 00038 (main.go:14) RET
0x0027 00039 (main.go:14) NOP
0x0027 00039 (main.go:11) PCDATA $1, $-1
0x0027 00039 (main.go:11) PCDATA $0, $-2
0x0027 00039 (main.go:11) CALL runtime.morestack_noctxt(SB)
0x002c 00044 (main.go:11) PCDATA $0, $-1
0x002c 00044 (main.go:11) JMP 0
0x0000 49 3b 66 10 76 21 55 48 89 e5 48 83 ec 10 48 8d I;f.v!UH..H...H.
0x0010 05 00 00 00 00 e8 00 00 00 00 48 c7 00 01 00 00 ..........H.....
0x0020 00 48 83 c4 10 5d c3 e8 00 00 00 00 eb d2 .H...]........
rel 2+0 t=R_USEIFACE type:*int+0
rel 17+4 t=R_PCREL type:int+0
rel 22+4 t=R_CALL runtime.newobject+0
rel 40+4 t=R_CALL runtime.morestack_noctxt+0The assembly indicates that foo is inlined to produce
func main() {
a := 1
if false {
g = &a
}
}And g = &a is eliminated from the assembly altogether. However, the allocation (runtime.newobject) remains.
However, escape analysis fails to understand that a no longer escapes after dead code elimination after inlining. #74364 is already filed as a more general issue for control-flow-aware escape analysis, but I filed this as a separate issue because performing escape analysis after inlining + dead code elimination seems to. #74383 is also related as the devirtualized type switch seems to similarly be dead code analysis being ordered after escape analysis. But I still wanted to file this issue to capture the issue more broadly since that issue is fairly specific to devirtualized type switches.