package main
func f(p *int, x int, b bool) {
if p == nil {
return
}
g()
if b {
*p = x
} else {
*p = x + 1
}
}
func g()
When compiled, the register allocator spills p
and x
before the call to g
. It then restores both p
and x
in both the then
and else
branches. It could instead do the restores before the if b
check, which would require only one restore of each.
The tricky part is to do the restores before the if
only if we're sure that they won't be dropped again before their use in both branches.
This comes up a lot in write barrier code:
package main
func f(p **int, q *int) {
if p == nil {
return
}
g()
*p = q
}
func g()
p
and q
are restored in both the write-barrier-on and write-barrier-off branches in the generated code. This is particularly ugly in the write barrier code because the write-barrier-off code block goes from having 0 instructions to having >0 instructions, meaning we need an additional jump as well.
Comment From: gabyhelp
Related Issues
Related Code Changes
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)