]> Cypherpunks.ru repositories - gostls13.git/blob - test/checkbce.go
cmd/internal/obj/ppc64: generate small, shifted constants in register
[gostls13.git] / test / checkbce.go
1 // +build amd64,!gcflags_noopt
2 // errorcheck -0 -d=ssa/check_bce/debug=3
3
4 // Copyright 2016 The Go Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file.
7
8 // Test that the compiler does bounds check elimination as expected.
9 // This avoids accidental regressions.
10
11 package main
12
13 import "encoding/binary"
14
15 func f0(a []int) {
16         a[0] = 1 // ERROR "Found IsInBounds$"
17         a[0] = 1
18         a[6] = 1 // ERROR "Found IsInBounds$"
19         a[6] = 1
20         a[5] = 1
21         a[5] = 1
22 }
23
24 func f1(a [256]int, i int) {
25         var j int
26         useInt(a[i]) // ERROR "Found IsInBounds$"
27         j = i % 256
28         useInt(a[j]) // ERROR "Found IsInBounds$"
29         j = i & 255
30         useInt(a[j])
31         j = i & 17
32         useInt(a[j])
33
34         if 4 <= i && i < len(a) {
35                 useInt(a[i])
36                 useInt(a[i-1])
37                 useInt(a[i-4])
38         }
39 }
40
41 func f2(a [256]int, i uint) {
42         useInt(a[i]) // ERROR "Found IsInBounds$"
43         j := i % 256
44         useInt(a[j])
45         j = i & 255
46         useInt(a[j])
47         j = i & 17
48         useInt(a[j])
49 }
50
51 func f2a(a [35]int, i uint8) {
52         useInt(a[i]) // ERROR "Found IsInBounds$"
53         j := i & 34
54         useInt(a[j])
55         j = i & 17
56         useInt(a[j])
57 }
58
59 func f2b(a [35]int, i uint16) {
60         useInt(a[i]) // ERROR "Found IsInBounds$"
61         j := i & 34
62         useInt(a[j])
63         j = i & 17
64         useInt(a[j])
65 }
66
67 func f2c(a [35]int, i uint32) {
68         useInt(a[i]) // ERROR "Found IsInBounds$"
69         j := i & 34
70         useInt(a[j])
71         j = i & 17
72         useInt(a[j])
73 }
74
75 func f3(a [256]int, i uint8) {
76         useInt(a[i])
77         useInt(a[i+10])
78         useInt(a[i+14])
79 }
80
81 func f4(a [27]int, i uint8) {
82         useInt(a[i%15])
83         useInt(a[i%19])
84         useInt(a[i%27])
85 }
86
87 func f5(a []int) {
88         if len(a) > 5 {
89                 useInt(a[5])
90                 useSlice(a[6:])
91                 useSlice(a[:6])
92         }
93 }
94
95 func f6(a [32]int, b [64]int, i int) {
96         useInt(a[uint32(i*0x07C4ACDD)>>27])
97         useInt(b[uint64(i*0x07C4ACDD)>>58])
98         useInt(a[uint(i*0x07C4ACDD)>>59])
99
100         // The following bounds should not be removed because they can overflow.
101         useInt(a[uint32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$"
102         useInt(b[uint64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$"
103         useInt(a[int32(i*0x106297f105d0cc86)>>26])  // ERROR "Found IsInBounds$"
104         useInt(b[int64(i*0x106297f105d0cc86)>>57])  // ERROR "Found IsInBounds$"
105 }
106
107 func g1(a []int) {
108         for i := range a {
109                 a[i] = i
110                 useSlice(a[:i+1])
111                 useSlice(a[:i])
112         }
113 }
114
115 func g2(a []int) {
116         useInt(a[3]) // ERROR "Found IsInBounds$"
117         useInt(a[2])
118         useInt(a[1])
119         useInt(a[0])
120 }
121
122 func g3(a []int) {
123         for i := range a[:256] { // ERROR "Found IsSliceInBounds$"
124                 useInt(a[i]) // ERROR "Found IsInBounds$"
125         }
126         b := a[:256]
127         for i := range b {
128                 useInt(b[i])
129         }
130 }
131
132 func g4(a [100]int) {
133         for i := 10; i < 50; i++ {
134                 useInt(a[i-10])
135                 useInt(a[i])
136                 useInt(a[i+25])
137                 useInt(a[i+50])
138
139                 // The following are out of bounds.
140                 if a[0] == 0xdeadbeef {
141                         // This is a trick to prohibit sccp to optimize out the following out of bound check
142                         continue
143                 }
144                 useInt(a[i-11]) // ERROR "Found IsInBounds$"
145                 useInt(a[i+51]) // ERROR "Found IsInBounds$"
146         }
147 }
148
149 func decode1(data []byte) (x uint64) {
150         for len(data) >= 32 {
151                 x += binary.BigEndian.Uint64(data[:8])
152                 x += binary.BigEndian.Uint64(data[8:16])
153                 x += binary.BigEndian.Uint64(data[16:24])
154                 x += binary.BigEndian.Uint64(data[24:32])
155                 data = data[32:]
156         }
157         return x
158 }
159
160 func decode2(data []byte) (x uint64) {
161         // TODO(rasky): this should behave like decode1 and compile to no
162         // boundchecks. We're currently not able to remove all of them.
163         for len(data) >= 32 {
164                 x += binary.BigEndian.Uint64(data)
165                 data = data[8:]
166                 x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
167                 data = data[8:]
168                 x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
169                 data = data[8:]
170                 x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
171                 data = data[8:]
172         }
173         return x
174 }
175
176 //go:noinline
177 func useInt(a int) {
178 }
179
180 //go:noinline
181 func useSlice(a []int) {
182 }
183
184 func main() {
185 }