Skip to content

Commit 1747788

Browse files
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent 3bbede0 commit 1747788

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

Diff for: src/cmd/compile/internal/ssa/checkbce.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package ssa
6+
7+
// checkbce prints all bounds checks that are present in the function.
8+
// Useful to find regressions. checkbce is only activated when with
9+
// corresponsing debug options, so it's off by default.
10+
// See test/checkbce.go
11+
func checkbce(f *Func) {
12+
if f.pass.debug <= 0 {
13+
return
14+
}
15+
16+
for _, b := range f.Blocks {
17+
for _, v := range b.Values {
18+
if v.Op == OpIsInBounds || v.Op == OpIsSliceInBounds {
19+
f.Config.Warnl(v.Line, "Found %v", v.Op)
20+
}
21+
}
22+
}
23+
}

Diff for: src/cmd/compile/internal/ssa/compile.go

+3
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ var passes = [...]pass{
242242
{name: "dec", fn: dec, required: true},
243243
{name: "late opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
244244
{name: "generic deadcode", fn: deadcode},
245+
{name: "check bce", fn: checkbce},
245246
{name: "fuse", fn: fuse},
246247
{name: "dse", fn: dse},
247248
{name: "tighten", fn: tighten}, // move values closer to their uses
@@ -290,6 +291,8 @@ var passOrder = [...]constraint{
290291
// tighten will be most effective when as many values have been removed as possible
291292
{"generic deadcode", "tighten"},
292293
{"generic cse", "tighten"},
294+
// checkbce needs the values removed
295+
{"generic deadcode", "check bce"},
293296
// don't run optimization pass until we've decomposed builtin objects
294297
{"decompose builtin", "late opt"},
295298
// don't layout blocks until critical edges have been removed

Diff for: src/cmd/compile/internal/ssa/phiopt.go

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
15
package ssa
26

37
// phiopt eliminates boolean Phis based on the previous if.

Diff for: test/checkbce.go

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// +build amd64
2+
// errorcheck -0 -d=ssa/check_bce/debug=3
3+
4+
package main
5+
6+
func f0(a []int) {
7+
a[0] = 1 // ERROR "Found IsInBounds$"
8+
a[0] = 1
9+
a[6] = 1 // ERROR "Found IsInBounds$"
10+
a[6] = 1
11+
a[5] = 1
12+
a[5] = 1
13+
}
14+
15+
func f1(a [256]int, i int) {
16+
useInt(a[i]) // ERROR "Found IsInBounds$"
17+
useInt(a[i%256]) // ERROR "Found IsInBounds$"
18+
useInt(a[i&255])
19+
useInt(a[i&17])
20+
21+
if 4 <= i && i < len(a) {
22+
useInt(a[i])
23+
useInt(a[i-1]) // ERROR "Found IsInBounds$"
24+
useInt(a[i-4]) // ERROR "Found IsInBounds$"
25+
}
26+
}
27+
28+
func f2(a [256]int, i uint) {
29+
useInt(a[i]) // ERROR "Found IsInBounds$"
30+
useInt(a[i%256])
31+
useInt(a[i&255])
32+
useInt(a[i&17])
33+
}
34+
35+
func f3(a [256]int, i uint8) {
36+
useInt(a[i])
37+
useInt(a[i+10])
38+
useInt(a[i+14])
39+
}
40+
41+
func f4(a [27]int, i uint8) {
42+
useInt(a[i%15])
43+
useInt(a[i%19])
44+
useInt(a[i%27])
45+
}
46+
47+
func f5(a []int) {
48+
if len(a) > 5 {
49+
useInt(a[5])
50+
useSlice(a[6:])
51+
useSlice(a[:6]) // ERROR "Found IsSliceInBounds$"
52+
}
53+
}
54+
55+
func g1(a []int) {
56+
for i := range a {
57+
a[i] = i
58+
useSlice(a[:i+1])
59+
useSlice(a[:i])
60+
}
61+
}
62+
63+
func g2(a []int) {
64+
useInt(a[3]) // ERROR "Found IsInBounds$"
65+
useInt(a[2])
66+
useInt(a[1])
67+
useInt(a[0])
68+
}
69+
70+
func g3(a []int) {
71+
for i := range a[:256] { // ERROR "Found IsSliceInBounds$"
72+
useInt(a[i]) // ERROR "Found IsInBounds$"
73+
}
74+
b := a[:256]
75+
for i := range b {
76+
useInt(b[i])
77+
}
78+
}
79+
80+
//go:noinline
81+
func useInt(a int) {
82+
}
83+
84+
//go:noinline
85+
func useSlice(a []int) {
86+
}
87+
88+
func main() {
89+
}

0 commit comments

Comments
 (0)