| // +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]) // 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-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() { | 
 | } |