mirror of https://github.com/golang/go.git
cmd/compile: add a pass to print bound checks
Since BCE happens over several passes (opt, loopbce, prove) it's easy to regress especially with rewriting. The pass is only activated with special debug flag. Change-Id: I46205982e7a2751156db8e875d69af6138068f59 Reviewed-on: https://go-review.googlesource.com/21510 Run-TryBot: Alexandru Moșoi <alexandru@mosoi.ro> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
3bbede0c51
commit
1747788c56
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssa
|
||||
|
||||
// checkbce prints all bounds checks that are present in the function.
|
||||
// Useful to find regressions. checkbce is only activated when with
|
||||
// corresponsing debug options, so it's off by default.
|
||||
// See test/checkbce.go
|
||||
func checkbce(f *Func) {
|
||||
if f.pass.debug <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, b := range f.Blocks {
|
||||
for _, v := range b.Values {
|
||||
if v.Op == OpIsInBounds || v.Op == OpIsSliceInBounds {
|
||||
f.Config.Warnl(v.Line, "Found %v", v.Op)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -242,6 +242,7 @@ var passes = [...]pass{
|
|||
{name: "dec", fn: dec, required: true},
|
||||
{name: "late opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
|
||||
{name: "generic deadcode", fn: deadcode},
|
||||
{name: "check bce", fn: checkbce},
|
||||
{name: "fuse", fn: fuse},
|
||||
{name: "dse", fn: dse},
|
||||
{name: "tighten", fn: tighten}, // move values closer to their uses
|
||||
|
|
@ -290,6 +291,8 @@ var passOrder = [...]constraint{
|
|||
// tighten will be most effective when as many values have been removed as possible
|
||||
{"generic deadcode", "tighten"},
|
||||
{"generic cse", "tighten"},
|
||||
// checkbce needs the values removed
|
||||
{"generic deadcode", "check bce"},
|
||||
// don't run optimization pass until we've decomposed builtin objects
|
||||
{"decompose builtin", "late opt"},
|
||||
// don't layout blocks until critical edges have been removed
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssa
|
||||
|
||||
// phiopt eliminates boolean Phis based on the previous if.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
// +build amd64
|
||||
// errorcheck -0 -d=ssa/check_bce/debug=3
|
||||
|
||||
package main
|
||||
|
||||
func f0(a []int) {
|
||||
a[0] = 1 // ERROR "Found IsInBounds$"
|
||||
a[0] = 1
|
||||
a[6] = 1 // ERROR "Found IsInBounds$"
|
||||
a[6] = 1
|
||||
a[5] = 1
|
||||
a[5] = 1
|
||||
}
|
||||
|
||||
func f1(a [256]int, i int) {
|
||||
useInt(a[i]) // ERROR "Found IsInBounds$"
|
||||
useInt(a[i%256]) // ERROR "Found IsInBounds$"
|
||||
useInt(a[i&255])
|
||||
useInt(a[i&17])
|
||||
|
||||
if 4 <= i && i < len(a) {
|
||||
useInt(a[i])
|
||||
useInt(a[i-1]) // ERROR "Found IsInBounds$"
|
||||
useInt(a[i-4]) // ERROR "Found IsInBounds$"
|
||||
}
|
||||
}
|
||||
|
||||
func f2(a [256]int, i uint) {
|
||||
useInt(a[i]) // ERROR "Found IsInBounds$"
|
||||
useInt(a[i%256])
|
||||
useInt(a[i&255])
|
||||
useInt(a[i&17])
|
||||
}
|
||||
|
||||
func f3(a [256]int, i uint8) {
|
||||
useInt(a[i])
|
||||
useInt(a[i+10])
|
||||
useInt(a[i+14])
|
||||
}
|
||||
|
||||
func f4(a [27]int, i uint8) {
|
||||
useInt(a[i%15])
|
||||
useInt(a[i%19])
|
||||
useInt(a[i%27])
|
||||
}
|
||||
|
||||
func f5(a []int) {
|
||||
if len(a) > 5 {
|
||||
useInt(a[5])
|
||||
useSlice(a[6:])
|
||||
useSlice(a[:6]) // ERROR "Found IsSliceInBounds$"
|
||||
}
|
||||
}
|
||||
|
||||
func g1(a []int) {
|
||||
for i := range a {
|
||||
a[i] = i
|
||||
useSlice(a[:i+1])
|
||||
useSlice(a[:i])
|
||||
}
|
||||
}
|
||||
|
||||
func g2(a []int) {
|
||||
useInt(a[3]) // ERROR "Found IsInBounds$"
|
||||
useInt(a[2])
|
||||
useInt(a[1])
|
||||
useInt(a[0])
|
||||
}
|
||||
|
||||
func g3(a []int) {
|
||||
for i := range a[:256] { // ERROR "Found IsSliceInBounds$"
|
||||
useInt(a[i]) // ERROR "Found IsInBounds$"
|
||||
}
|
||||
b := a[:256]
|
||||
for i := range b {
|
||||
useInt(b[i])
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func useInt(a int) {
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func useSlice(a []int) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
Loading…
Reference in New Issue