go/test/opt_branchlikely.go

88 lines
2.1 KiB
Go
Raw Normal View History

// errorcheck -0 -d=ssa/likelyadjust/debug=1,ssa/insert_resched_checks/off
// rescheduling check insertion is turned off because the inserted conditional branches perturb the errorcheck
[dev.ssa] cmd/compile: adjust branch likeliness for calls/loops Static branch predictions (which guide block ordering) are adjusted based on: loop/not-loop (favor looping) abnormal-exit/not (avoid panic) call/not-call (avoid call) ret/default (treat returns as rare) This appears to make no difference in performance of real code, meaning the compiler itself. The earlier version of this has been stripped down to help make the cost of this only-aesthetic-on-Intel phase be as cheap as possible (we probably want information about inner loops for improving register allocation, but because register allocation follows close behind this pass, conceivably the information could be reused -- so we might do this anyway just to normalize output). For a ./make.bash that takes 200 user seconds, about .75 second is reported in likelyadjust (summing nanoseconds reported with -d=ssa/likelyadjust/time ). Upstream predictions are respected. Includes test, limited to build on amd64 only. Did several iterations on the debugging output to allow some rough checks on behavior. Debug=1 logging notes agree/disagree with earlier passes, allowing analysis like the following: Run on make.bash: GO_GCFLAGS=-d=ssa/likelyadjust/debug \ ./make.bash >& lkly5.log grep 'ranch prediction' lkly5.log | wc -l 78242 // 78k predictions grep 'ranch predi' lkly5.log | egrep -v 'agrees with' | wc -l 29633 // 29k NEW predictions grep 'disagrees' lkly5.log | wc -l 444 // contradicted 444 times grep '< exit' lkly5.log | wc -l 10212 // 10k exit predictions grep '< exit' lkly5.log | egrep 'disagrees' | wc -l 5 // 5 contradicted by previous prediction grep '< exit' lkly5.log | egrep -v 'agrees' | wc -l 702 // 702-5 redundant with previous prediction grep '< call' lkly5.log | egrep -v 'agrees' | wc -l 16699 // 16k new call predictions grep 'stay in loop' lkly5.log | egrep -v 'agrees' | wc -l 3951 // 4k new "remain in loop" predictions Fixes #11451. Change-Id: Iafb0504f7030d304ef4b6dc1aba9a5789151a593 Reviewed-on: https://go-review.googlesource.com/19995 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2016-02-27 16:54:52 +00:00
//go:build amd64
// Copyright 2016 The Go Authors. All rights reserved.
[dev.ssa] cmd/compile: adjust branch likeliness for calls/loops Static branch predictions (which guide block ordering) are adjusted based on: loop/not-loop (favor looping) abnormal-exit/not (avoid panic) call/not-call (avoid call) ret/default (treat returns as rare) This appears to make no difference in performance of real code, meaning the compiler itself. The earlier version of this has been stripped down to help make the cost of this only-aesthetic-on-Intel phase be as cheap as possible (we probably want information about inner loops for improving register allocation, but because register allocation follows close behind this pass, conceivably the information could be reused -- so we might do this anyway just to normalize output). For a ./make.bash that takes 200 user seconds, about .75 second is reported in likelyadjust (summing nanoseconds reported with -d=ssa/likelyadjust/time ). Upstream predictions are respected. Includes test, limited to build on amd64 only. Did several iterations on the debugging output to allow some rough checks on behavior. Debug=1 logging notes agree/disagree with earlier passes, allowing analysis like the following: Run on make.bash: GO_GCFLAGS=-d=ssa/likelyadjust/debug \ ./make.bash >& lkly5.log grep 'ranch prediction' lkly5.log | wc -l 78242 // 78k predictions grep 'ranch predi' lkly5.log | egrep -v 'agrees with' | wc -l 29633 // 29k NEW predictions grep 'disagrees' lkly5.log | wc -l 444 // contradicted 444 times grep '< exit' lkly5.log | wc -l 10212 // 10k exit predictions grep '< exit' lkly5.log | egrep 'disagrees' | wc -l 5 // 5 contradicted by previous prediction grep '< exit' lkly5.log | egrep -v 'agrees' | wc -l 702 // 702-5 redundant with previous prediction grep '< call' lkly5.log | egrep -v 'agrees' | wc -l 16699 // 16k new call predictions grep 'stay in loop' lkly5.log | egrep -v 'agrees' | wc -l 3951 // 4k new "remain in loop" predictions Fixes #11451. Change-Id: Iafb0504f7030d304ef4b6dc1aba9a5789151a593 Reviewed-on: https://go-review.googlesource.com/19995 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Keith Randall <khr@golang.org>
2016-02-27 16:54:52 +00:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test that branches have some prediction properties.
package foo
func f(x, y, z int) int {
a := 0
for i := 0; i < x; i++ { // ERROR "Branch prediction rule stay in loop"
for j := 0; j < y; j++ { // ERROR "Branch prediction rule stay in loop"
a += j
}
for k := 0; k < z; k++ { // ERROR "Branch prediction rule stay in loop"
a -= x + y + z
}
}
return a
}
func g(x, y, z int) int {
a := 0
if y == 0 { // ERROR "Branch prediction rule default < call"
y = g(y, z, x)
} else {
y++
}
if y == x { // ERROR "Branch prediction rule default < call"
y = g(y, z, x)
} else {
}
if y == 2 { // ERROR "Branch prediction rule default < call"
z++
} else {
y = g(z, x, y)
}
if y+z == 3 { // ERROR "Branch prediction rule call < exit"
println("ha ha")
} else {
panic("help help help")
}
if x != 0 { // ERROR "Branch prediction rule default < ret"
for i := 0; i < x; i++ { // ERROR "Branch prediction rule stay in loop"
if x == 4 { // ERROR "Branch prediction rule stay in loop"
return a
}
for j := 0; j < y; j++ { // ERROR "Branch prediction rule stay in loop"
for k := 0; k < z; k++ { // ERROR "Branch prediction rule stay in loop"
a -= j * i
}
a += j
}
}
}
return a
}
func h(x, y, z int) int {
a := 0
for i := 0; i < x; i++ { // ERROR "Branch prediction rule stay in loop"
for j := 0; j < y; j++ { // ERROR "Branch prediction rule stay in loop"
a += j
if i == j { // ERROR "Branch prediction rule stay in loop"
break
}
a *= j
}
for k := 0; k < z; k++ { // ERROR "Branch prediction rule stay in loop"
a -= k
if i == k {
continue
}
a *= k
}
}
if a > 0 { // ERROR "Branch prediction rule default < call"
a = g(x, y, z)
} else {
a = -a
}
return a
}