Open
Description
func i(x int) int { return x }
func f(a int) bool {
switch a {
case 1, 2, 3, 4, 5, 6:
return true
}
return false
}
func g(a int) bool {
switch a {
case i(1), i(2), i(3), i(4), i(5), i(6):
return true
}
return false
}
f and g should compile to the same code. They don't. In g, i(n) is not recognized as a constant case, because i(n) ends up being a tempname introduced to hold the inlined return value from i. As a result, g does not use binary search over the cases. The SSA back-end can see past such things, but several important optimization decisions are made in the front-end on a const/non-const basis.
As a first pass, maybe recognized inlined functions containing exactly one return statement and inline the returned expression directly. This may also require work to avoid converting inlined arguments from constants to tempnames, which itself might be useful.
Sample real world code in which this occurs, from asm9.go in the s390x obj code:
func OPVCC(o uint32, xo uint32, oe uint32, rc uint32) uint32 {
return o<<26 | xo<<1 | oe<<10 | rc&1
}
func opform(ctxt *obj.Link, insn uint32) int {
switch insn {
default:
ctxt.Diag("bad insn in loadform: %x", insn)
case OPVCC(58, 0, 0, 0), // ld
OPVCC(58, 0, 0, 0) | 1<<1, // lwa
OPVCC(62, 0, 0, 0): // std
return DS_FORM
case OP_ADDI, // add
OPVCC(32, 0, 0, 0), // lwz
OPVCC(42, 0, 0, 0), // lha
OPVCC(40, 0, 0, 0), // lhz
OPVCC(34, 0, 0, 0), // lbz
OPVCC(50, 0, 0, 0), // lfd
OPVCC(48, 0, 0, 0), // lfs
OPVCC(36, 0, 0, 0), // stw
OPVCC(44, 0, 0, 0), // sth
OPVCC(38, 0, 0, 0), // stb
OPVCC(54, 0, 0, 0), // stfd
OPVCC(52, 0, 0, 0): // stfs
return D_FORM
}
return 0
}