| // +build amd64,!gcflags_noopt |
| // errorcheck -0 -d=ssa/check_bce/debug=3 |
| |
| // 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 |
| a[6] = 1 // ERROR "Found IsInBounds$" |
| a[6] = 1 |
| a[5] = 1 |
| a[5] = 1 |
| } |
| |
| func f1(a [256]int, i int) { |
| var j int |
| useInt(a[i]) // ERROR "Found IsInBounds$" |
| j = i % 256 |
| useInt(a[j]) // ERROR "Found IsInBounds$" |
| j = i & 255 |
| useInt(a[j]) |
| j = i & 17 |
| useInt(a[j]) |
| |
| if 4 <= i && i < len(a) { |
| useInt(a[i]) |
| useInt(a[i-1]) |
| useInt(a[i-4]) |
| } |
| } |
| |
| func f2(a [256]int, i uint) { |
| useInt(a[i]) // ERROR "Found IsInBounds$" |
| j := i % 256 |
| useInt(a[j]) |
| j = i & 255 |
| useInt(a[j]) |
| j = i & 17 |
| useInt(a[j]) |
| } |
| |
| func f2a(a [35]int, i uint8) { |
| useInt(a[i]) // ERROR "Found IsInBounds$" |
| j := i & 34 |
| useInt(a[j]) |
| j = i & 17 |
| useInt(a[j]) |
| } |
| |
| func f2b(a [35]int, i uint16) { |
| useInt(a[i]) // ERROR "Found IsInBounds$" |
| j := i & 34 |
| useInt(a[j]) |
| j = i & 17 |
| useInt(a[j]) |
| } |
| |
| func f2c(a [35]int, i uint32) { |
| useInt(a[i]) // ERROR "Found IsInBounds$" |
| j := i & 34 |
| useInt(a[j]) |
| j = i & 17 |
| useInt(a[j]) |
| } |
| |
| 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]) |
| } |
| } |
| |
| func f6(a [32]int, b [64]int, i int) { |
| useInt(a[uint32(i*0x07C4ACDD)>>27]) |
| useInt(b[uint64(i*0x07C4ACDD)>>58]) |
| useInt(a[uint(i*0x07C4ACDD)>>59]) |
| |
| // The following bounds should not be removed because they can overflow. |
| useInt(a[uint32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$" |
| useInt(b[uint64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$" |
| useInt(a[int32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$" |
| useInt(b[int64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$" |
| } |
| |
| 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]) |
| } |
| } |
| |
| func g4(a [100]int) { |
| for i := 10; i < 50; i++ { |
| useInt(a[i-10]) |
| useInt(a[i]) |
| useInt(a[i+25]) |
| useInt(a[i+50]) |
| |
| // The following are out of bounds. |
| 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) { |
| } |
| |
| //go:noinline |
| func useSlice(a []int) { |
| } |
| |
| func main() { |
| } |