-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Closed
Labels
Milestone
Description
There are cases where duplicated code sequences can be merged without performance loss or invalidation of panic line info.
The most obvious are BlockRet
that do not contain anything that may cause run time panic.
Given this code:
package foo
func f1(v *int, y int) int {
x := 214
if *v == 0 {
return x + y
}
if *v == 1 {
return x + y
}
if *v == 2 {
return x - y
}
if *v == 3 {
return x - y
}
return 0
}
We currently get this output:
"".f1 STEXT nosplit size=115 args=0x18 locals=0x0
00000 (foo.go:3) TEXT "".f1(SB), NOSPLIT, $0-24
00000 (foo.go:3) MOVQ "".v+8(SP), AX
00005 (foo.go:5) MOVQ (AX), AX
00008 (foo.go:5) TESTQ AX, AX
00011 (foo.go:5) JEQ 98
00013 (foo.go:8) CMPQ AX, $1
00017 (foo.go:8) JEQ 81
00019 (foo.go:11) CMPQ AX, $2
00023 (foo.go:11) JEQ 61
00025 (foo.go:14) CMPQ AX, $3
00029 (foo.go:14) JNE 51
00031 (foo.go:15) MOVQ "".y+16(SP), AX
00036 (foo.go:15) ADDQ $-214, AX
00042 (foo.go:15) NEGQ AX
00045 (foo.go:15) MOVQ AX, "".~r2+24(SP)
00050 (foo.go:15) RET
00051 (foo.go:17) MOVQ $0, "".~r2+24(SP)
00060 (foo.go:17) RET
00061 (foo.go:12) MOVQ "".y+16(SP), AX
00066 (foo.go:12) ADDQ $-214, AX
00072 (foo.go:12) NEGQ AX
00075 (foo.go:12) MOVQ AX, "".~r2+24(SP)
00080 (foo.go:12) RET
00081 (foo.go:9) MOVQ "".y+16(SP), AX
00086 (foo.go:9) ADDQ $214, AX
00092 (foo.go:9) MOVQ AX, "".~r2+24(SP)
00097 (foo.go:9) RET
00098 (foo.go:6) MOVQ "".y+16(SP), AX
00103 (foo.go:6) ADDQ $214, AX
00109 (foo.go:6) MOVQ AX, "".~r2+24(SP)
00114 (foo.go:6) RET
If we were merging epilogue sequences, we could get this:
"".f1 STEXT nosplit size=78 args=0x18 locals=0x0
00000 (foo.go:3) TEXT "".f1(SB), NOSPLIT, $0-24
00000 (foo.go:3) MOVQ "".v+8(SP), AX
00005 (foo.go:5) MOVQ (AX), AX
00008 (foo.go:5) TESTQ AX, AX
00011 (foo.go:5) JEQ 61
00013 (foo.go:8) CMPQ AX, $1
00017 (foo.go:8) JEQ 61
00019 (foo.go:11) CMPQ AX, $2
00023 (foo.go:11) JEQ 41
00025 (foo.go:14) CMPQ AX, $3
00029 (foo.go:14) JEQ 41
00031 (foo.go:17) MOVQ $0, "".~r2+24(SP)
00040 (foo.go:17) RET
00041 (foo.go:12) MOVQ "".y+16(SP), AX
00046 (foo.go:12) ADDQ $-214, AX
00052 (foo.go:12) NEGQ AX
00055 (foo.go:12) MOVQ AX, "".~r2+24(SP)
00060 (foo.go:12) RET
00061 (foo.go:6) MOVQ "".y+16(SP), AX
00066 (foo.go:6) ADDQ $214, AX
00072 (foo.go:6) MOVQ AX, "".~r2+24(SP)
00077 (foo.go:6) RET
Proposed implementation will follow soon in form of CL.
Detailed bincmp
info for go
binary: bincmp.txt.
Main objectives/restrictions:
- Do not introduce additional branches. Only change existing jump target to merged return.
- Do not change program observable behavior (in particular, stack traces should also remain the same, source locations should be the same).
If any of those are not respected by implementation, it's a bug.