Commit 1747788c authored by Alexandru Moșoi's avatar Alexandru Moșoi Committed by Alexandru Moșoi

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: default avatarDavid Chase <drchase@google.com>
parent 3bbede0c
// 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
......
// 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.
......
// +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() {
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment