-// +build amd64
// errorcheck -0 -d=ssa/check_bce/debug=3
+//go:build amd64 && !gcflags_noopt
+
+// 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.
+
+// Test that the compiler does bounds check elimination as expected.
+// This avoids accidental regressions.
+
package main
+import "encoding/binary"
+
func f0(a []int) {
a[0] = 1 // ERROR "Found IsInBounds$"
a[0] = 1
if 4 <= i && i < len(a) {
useInt(a[i])
- useInt(a[i-1]) // ERROR "Found IsInBounds$"
- // TODO: 'if 4 <= i && i < len(a)' gets rewritten to 'if uint(i - 4) < 256 - 4',
- // which the bounds checker cannot yet use to infer that the next line doesn't need a bounds check.
+ useInt(a[i-1])
useInt(a[i-4])
}
}
useInt(a[i+50])
// The following are out of bounds.
+ if a[0] == 0xdeadbeef {
+ // This is a trick to prohibit sccp to optimize out the following out of bound check
+ continue
+ }
useInt(a[i-11]) // ERROR "Found IsInBounds$"
useInt(a[i+51]) // ERROR "Found IsInBounds$"
}
}
+func decode1(data []byte) (x uint64) {
+ for len(data) >= 32 {
+ x += binary.BigEndian.Uint64(data[:8])
+ x += binary.BigEndian.Uint64(data[8:16])
+ x += binary.BigEndian.Uint64(data[16:24])
+ x += binary.BigEndian.Uint64(data[24:32])
+ data = data[32:]
+ }
+ return x
+}
+
+func decode2(data []byte) (x uint64) {
+ // TODO(rasky): this should behave like decode1 and compile to no
+ // boundchecks. We're currently not able to remove all of them.
+ for len(data) >= 32 {
+ x += binary.BigEndian.Uint64(data)
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ }
+ return x
+}
+
//go:noinline
func useInt(a int) {
}