What is bounds check elimination (BCE), how do you see it, and how can you help the compiler?
Question 390HardGo 1.22 to 1.25
Go is memory safe: every s[i] gets a runtime check that panics if i is out of range. The SSA backend's prove pass removes checks it can prove redundant. In tight loops (codecs, hashing, parsers), the remaining checks cost compare-and-branch instructions, add code size, and can prevent optimizations such as combining adjacent byte loads into one wide load (Go's compiler does not auto-vectorize, so this is about scalar code quality).
go build -gcflags='-d=ssa/check_bce/debug=1' ./...
# ./enc.go:12:9: Found IsInBounds
// 4 bounds checks: the compiler can't assume len(b) >= 4
func load32Slow(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
// 1 bounds check: the early hint proves the rest safe
func load32(b []byte) uint32 {
_ = b[3] // bounds check hint
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
// Loop patterns the prover understands
func sum(s []int) int {
total := 0
for i := range s { // i in [0, len(s)): no check on s[i]
total += s[i]
}
return total
}
func addInto(dst, src []int) {
dst = dst[:len(src)] // one check here; then dst[i] and src[i] are free
for i := range src {
dst[i] += src[i]
}
}
This is exactly what encoding/binary.LittleEndian.Uint32 does. Gotchas: only bother after a profile shows the loop is hot; reslicing tricks can make code less readable; -B disables all bounds checks and should never ship. Iterating with for i := range s is both idiomatic and BCE-friendly.
More on Performance, Profiling & Testing
- Q388How does inlining work in the Go compiler, how do you inspect it, and what prevents a function from being inlined?
- Q389Explain escape analysis. Which of these allocate on the heap?
- Q391What are the tradeoffs of sync.Pool? When does it help, and when does it hurt?
- Q392Compare the performance of string concatenation approaches: +, fmt.Sprintf, strings.Builder, bytes.Buffer, strings.Join.
- Q393What does this program do?
- Q394How do GOGC and GOMEMLIMIT interact, and how would you tune the GC for a latency-sensitive service?