Open
Description
package p
func g_ssa(a, b int) int {
if a < 5 {
return 1
}
if b < 5 {
return 1
}
return 0
}
At the end of the layout pass (chosen for readability--this remains true at the end of compilation), the SSA looks like:
g_ssa <nil>
b1:
v1 = Arg <mem> [.mem]
v2 = FP <uint64>
v18 = MOVQconst <int> [1]
v22 = MOVQconst <int> [0]
v28 = MOVQload <int> [0] v2 v1
v32 = MOVQload <int> [8] v2 v1
v24 = CMPQconst <flags> [5] v28
v7 = MOVQstore <mem> [16] v2 v22 v1
LT v24 -> b3 b4
b3:
v14 = MOVQstore <mem> [16] v2 v18 v7
Plain -> b2
b2:
v29 = Phi <mem> v14 v21 v25
Exit v29
b4:
v20 = CMPQconst <flags> [5] v32
LT v20 -> b5 b6
b5:
v21 = MOVQstore <mem> [16] v2 v18 v7
Plain -> b2
b6:
v25 = MOVQstore <mem> [16] v2 v22 v7
Plain -> b2
Note that blocks b3
and b5
are effectively identical. One of them could be eliminated.
This happens fairly often in practice. For example, our generated equality code looks like:
func eq(a, b T) {
if a.X != b.X {
return false
}
if a.Y != b.Y {
return false
}
return true
}
This ought to produce code that is just as efficient as:
func eq(a, b T) {
return a.X == b.X && a.Y == b.Y
}
Right now it doesn't, but we can do better. There's also a lot of code in the compiler that looks like this. Also complex Less methods for sort.Interface.
Is this worth doing? Ought this to occur as part of an existing pass, or as a new one?