package src
func small(i int) bool {
switch i {
case 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15: // 9 is only small on a hot day
return true
}
return false
}
func small2(i int) bool {
switch {
case 0 <= i && i <= 8, 10 <= i && i <= 15:
return true
}
return false
}
We should compile small to the same code as small2. Instead, we handle each of the cases independently:
"".small t=1 size=112 args=0x10 locals=0x0
"".small2 t=1 size=48 args=0x10 locals=0x0
Worse, we end up paying a significant cost in the SSA backend juggling all the branches and blocks generated by the frontend.
This sounds theoretical, but I keep encountering large switch statements in functions with bad compile times, and I have seen a bunch of contiguous runs. Here's an excerpted example from cmd/vendor/golang.org/x/arch/x86/x86asm:
func gnuArg(inst *Inst, x Arg, usedPrefixes *bool) string {
// ...
switch inst.Op {
case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
if inst.DataSize == 16 && EAX <= x && x <= R15L {
x -= EAX - AX
}
// ...
Those constants all happen to be next to each other.
We should compile small to the same code as small2. Instead, we handle each of the cases independently:
Worse, we end up paying a significant cost in the SSA backend juggling all the branches and blocks generated by the frontend.
This sounds theoretical, but I keep encountering large switch statements in functions with bad compile times, and I have seen a bunch of contiguous runs. Here's an excerpted example from cmd/vendor/golang.org/x/arch/x86/x86asm:
Those constants all happen to be next to each other.