libgo: update to Go 1.11
[official-gcc.git] / libgo / go / runtime / memmove_test.go
blobb490cd815f5f91f2e309a24285603ad389c7ac92
1 // Copyright 2013 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.
5 package runtime_test
7 import (
8 "crypto/rand"
9 "encoding/binary"
10 "fmt"
11 "internal/race"
12 "internal/testenv"
13 . "runtime"
14 "testing"
17 func TestMemmove(t *testing.T) {
18 t.Parallel()
19 size := 256
20 if testing.Short() {
21 size = 128 + 16
23 src := make([]byte, size)
24 dst := make([]byte, size)
25 for i := 0; i < size; i++ {
26 src[i] = byte(128 + (i & 127))
28 for i := 0; i < size; i++ {
29 dst[i] = byte(i & 127)
31 for n := 0; n <= size; n++ {
32 for x := 0; x <= size-n; x++ { // offset in src
33 for y := 0; y <= size-n; y++ { // offset in dst
34 copy(dst[y:y+n], src[x:x+n])
35 for i := 0; i < y; i++ {
36 if dst[i] != byte(i&127) {
37 t.Fatalf("prefix dst[%d] = %d", i, dst[i])
40 for i := y; i < y+n; i++ {
41 if dst[i] != byte(128+((i-y+x)&127)) {
42 t.Fatalf("copied dst[%d] = %d", i, dst[i])
44 dst[i] = byte(i & 127) // reset dst
46 for i := y + n; i < size; i++ {
47 if dst[i] != byte(i&127) {
48 t.Fatalf("suffix dst[%d] = %d", i, dst[i])
56 func TestMemmoveAlias(t *testing.T) {
57 t.Parallel()
58 size := 256
59 if testing.Short() {
60 size = 128 + 16
62 buf := make([]byte, size)
63 for i := 0; i < size; i++ {
64 buf[i] = byte(i)
66 for n := 0; n <= size; n++ {
67 for x := 0; x <= size-n; x++ { // src offset
68 for y := 0; y <= size-n; y++ { // dst offset
69 copy(buf[y:y+n], buf[x:x+n])
70 for i := 0; i < y; i++ {
71 if buf[i] != byte(i) {
72 t.Fatalf("prefix buf[%d] = %d", i, buf[i])
75 for i := y; i < y+n; i++ {
76 if buf[i] != byte(i-y+x) {
77 t.Fatalf("copied buf[%d] = %d", i, buf[i])
79 buf[i] = byte(i) // reset buf
81 for i := y + n; i < size; i++ {
82 if buf[i] != byte(i) {
83 t.Fatalf("suffix buf[%d] = %d", i, buf[i])
91 func TestMemmoveLarge0x180000(t *testing.T) {
92 if testing.Short() && testenv.Builder() == "" {
93 t.Skip("-short")
96 t.Parallel()
97 if race.Enabled {
98 t.Skip("skipping large memmove test under race detector")
100 testSize(t, 0x180000)
103 func TestMemmoveOverlapLarge0x120000(t *testing.T) {
104 if testing.Short() && testenv.Builder() == "" {
105 t.Skip("-short")
108 t.Parallel()
109 if race.Enabled {
110 t.Skip("skipping large memmove test under race detector")
112 testOverlap(t, 0x120000)
115 func testSize(t *testing.T, size int) {
116 src := make([]byte, size)
117 dst := make([]byte, size)
118 _, _ = rand.Read(src)
119 _, _ = rand.Read(dst)
121 ref := make([]byte, size)
122 copyref(ref, dst)
124 for n := size - 50; n > 1; n >>= 1 {
125 for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
126 for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
127 copy(dst[y:y+n], src[x:x+n])
128 copyref(ref[y:y+n], src[x:x+n])
129 p := cmpb(dst, ref)
130 if p >= 0 {
131 t.Fatalf("Copy failed, copying from src[%d:%d] to dst[%d:%d].\nOffset %d is different, %v != %v", x, x+n, y, y+n, p, dst[p], ref[p])
138 func testOverlap(t *testing.T, size int) {
139 src := make([]byte, size)
140 test := make([]byte, size)
141 ref := make([]byte, size)
142 _, _ = rand.Read(src)
144 for n := size - 50; n > 1; n >>= 1 {
145 for x := 0; x <= size-n; x = x*7 + 1 { // offset in src
146 for y := 0; y <= size-n; y = y*9 + 1 { // offset in dst
147 // Reset input
148 copyref(test, src)
149 copyref(ref, src)
150 copy(test[y:y+n], test[x:x+n])
151 if y <= x {
152 copyref(ref[y:y+n], ref[x:x+n])
153 } else {
154 copybw(ref[y:y+n], ref[x:x+n])
156 p := cmpb(test, ref)
157 if p >= 0 {
158 t.Fatalf("Copy failed, copying from src[%d:%d] to dst[%d:%d].\nOffset %d is different, %v != %v", x, x+n, y, y+n, p, test[p], ref[p])
166 // Forward copy.
167 func copyref(dst, src []byte) {
168 for i, v := range src {
169 dst[i] = v
173 // Backwards copy
174 func copybw(dst, src []byte) {
175 if len(src) == 0 {
176 return
178 for i := len(src) - 1; i >= 0; i-- {
179 dst[i] = src[i]
183 // Returns offset of difference
184 func matchLen(a, b []byte, max int) int {
185 a = a[:max]
186 b = b[:max]
187 for i, av := range a {
188 if b[i] != av {
189 return i
192 return max
195 func cmpb(a, b []byte) int {
196 l := matchLen(a, b, len(a))
197 if l == len(a) {
198 return -1
200 return l
203 func benchmarkSizes(b *testing.B, sizes []int, fn func(b *testing.B, n int)) {
204 for _, n := range sizes {
205 b.Run(fmt.Sprint(n), func(b *testing.B) {
206 b.SetBytes(int64(n))
207 fn(b, n)
212 var bufSizes = []int{
213 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
214 32, 64, 128, 256, 512, 1024, 2048, 4096,
217 func BenchmarkMemmove(b *testing.B) {
218 benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
219 x := make([]byte, n)
220 y := make([]byte, n)
221 for i := 0; i < b.N; i++ {
222 copy(x, y)
227 func BenchmarkMemmoveUnalignedDst(b *testing.B) {
228 benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
229 x := make([]byte, n+1)
230 y := make([]byte, n)
231 for i := 0; i < b.N; i++ {
232 copy(x[1:], y)
237 func BenchmarkMemmoveUnalignedSrc(b *testing.B) {
238 benchmarkSizes(b, bufSizes, func(b *testing.B, n int) {
239 x := make([]byte, n)
240 y := make([]byte, n+1)
241 for i := 0; i < b.N; i++ {
242 copy(x, y[1:])
247 func TestMemclr(t *testing.T) {
248 size := 512
249 if testing.Short() {
250 size = 128 + 16
252 mem := make([]byte, size)
253 for i := 0; i < size; i++ {
254 mem[i] = 0xee
256 for n := 0; n < size; n++ {
257 for x := 0; x <= size-n; x++ { // offset in mem
258 MemclrBytes(mem[x : x+n])
259 for i := 0; i < x; i++ {
260 if mem[i] != 0xee {
261 t.Fatalf("overwrite prefix mem[%d] = %d", i, mem[i])
264 for i := x; i < x+n; i++ {
265 if mem[i] != 0 {
266 t.Fatalf("failed clear mem[%d] = %d", i, mem[i])
268 mem[i] = 0xee
270 for i := x + n; i < size; i++ {
271 if mem[i] != 0xee {
272 t.Fatalf("overwrite suffix mem[%d] = %d", i, mem[i])
279 func BenchmarkMemclr(b *testing.B) {
280 for _, n := range []int{5, 16, 64, 256, 4096, 65536} {
281 x := make([]byte, n)
282 b.Run(fmt.Sprint(n), func(b *testing.B) {
283 b.SetBytes(int64(n))
284 for i := 0; i < b.N; i++ {
285 MemclrBytes(x)
289 for _, m := range []int{1, 4, 8, 16, 64} {
290 x := make([]byte, m<<20)
291 b.Run(fmt.Sprint(m, "M"), func(b *testing.B) {
292 b.SetBytes(int64(m << 20))
293 for i := 0; i < b.N; i++ {
294 MemclrBytes(x)
300 func BenchmarkGoMemclr(b *testing.B) {
301 benchmarkSizes(b, []int{5, 16, 64, 256}, func(b *testing.B, n int) {
302 x := make([]byte, n)
303 for i := 0; i < b.N; i++ {
304 for j := range x {
305 x[j] = 0
311 func BenchmarkClearFat8(b *testing.B) {
312 for i := 0; i < b.N; i++ {
313 var x [8 / 4]uint32
314 _ = x
317 func BenchmarkClearFat12(b *testing.B) {
318 for i := 0; i < b.N; i++ {
319 var x [12 / 4]uint32
320 _ = x
323 func BenchmarkClearFat16(b *testing.B) {
324 for i := 0; i < b.N; i++ {
325 var x [16 / 4]uint32
326 _ = x
329 func BenchmarkClearFat24(b *testing.B) {
330 for i := 0; i < b.N; i++ {
331 var x [24 / 4]uint32
332 _ = x
335 func BenchmarkClearFat32(b *testing.B) {
336 for i := 0; i < b.N; i++ {
337 var x [32 / 4]uint32
338 _ = x
341 func BenchmarkClearFat40(b *testing.B) {
342 for i := 0; i < b.N; i++ {
343 var x [40 / 4]uint32
344 _ = x
347 func BenchmarkClearFat48(b *testing.B) {
348 for i := 0; i < b.N; i++ {
349 var x [48 / 4]uint32
350 _ = x
353 func BenchmarkClearFat56(b *testing.B) {
354 for i := 0; i < b.N; i++ {
355 var x [56 / 4]uint32
356 _ = x
359 func BenchmarkClearFat64(b *testing.B) {
360 for i := 0; i < b.N; i++ {
361 var x [64 / 4]uint32
362 _ = x
365 func BenchmarkClearFat128(b *testing.B) {
366 for i := 0; i < b.N; i++ {
367 var x [128 / 4]uint32
368 _ = x
371 func BenchmarkClearFat256(b *testing.B) {
372 for i := 0; i < b.N; i++ {
373 var x [256 / 4]uint32
374 _ = x
377 func BenchmarkClearFat512(b *testing.B) {
378 for i := 0; i < b.N; i++ {
379 var x [512 / 4]uint32
380 _ = x
383 func BenchmarkClearFat1024(b *testing.B) {
384 for i := 0; i < b.N; i++ {
385 var x [1024 / 4]uint32
386 _ = x
390 func BenchmarkCopyFat8(b *testing.B) {
391 var x [8 / 4]uint32
392 for i := 0; i < b.N; i++ {
393 y := x
394 _ = y
397 func BenchmarkCopyFat12(b *testing.B) {
398 var x [12 / 4]uint32
399 for i := 0; i < b.N; i++ {
400 y := x
401 _ = y
404 func BenchmarkCopyFat16(b *testing.B) {
405 var x [16 / 4]uint32
406 for i := 0; i < b.N; i++ {
407 y := x
408 _ = y
411 func BenchmarkCopyFat24(b *testing.B) {
412 var x [24 / 4]uint32
413 for i := 0; i < b.N; i++ {
414 y := x
415 _ = y
418 func BenchmarkCopyFat32(b *testing.B) {
419 var x [32 / 4]uint32
420 for i := 0; i < b.N; i++ {
421 y := x
422 _ = y
425 func BenchmarkCopyFat64(b *testing.B) {
426 var x [64 / 4]uint32
427 for i := 0; i < b.N; i++ {
428 y := x
429 _ = y
432 func BenchmarkCopyFat128(b *testing.B) {
433 var x [128 / 4]uint32
434 for i := 0; i < b.N; i++ {
435 y := x
436 _ = y
439 func BenchmarkCopyFat256(b *testing.B) {
440 var x [256 / 4]uint32
441 for i := 0; i < b.N; i++ {
442 y := x
443 _ = y
446 func BenchmarkCopyFat512(b *testing.B) {
447 var x [512 / 4]uint32
448 for i := 0; i < b.N; i++ {
449 y := x
450 _ = y
453 func BenchmarkCopyFat520(b *testing.B) {
454 var x [520 / 4]uint32
455 for i := 0; i < b.N; i++ {
456 y := x
457 _ = y
460 func BenchmarkCopyFat1024(b *testing.B) {
461 var x [1024 / 4]uint32
462 for i := 0; i < b.N; i++ {
463 y := x
464 _ = y
468 func BenchmarkIssue18740(b *testing.B) {
469 // This tests that memmove uses one 4-byte load/store to move 4 bytes.
470 // It used to do 2 2-byte load/stores, which leads to a pipeline stall
471 // when we try to read the result with one 4-byte load.
472 var buf [4]byte
473 for j := 0; j < b.N; j++ {
474 s := uint32(0)
475 for i := 0; i < 4096; i += 4 {
476 copy(buf[:], g[i:])
477 s += binary.LittleEndian.Uint32(buf[:])
479 sink = uint64(s)
483 // TODO: 2 byte and 8 byte benchmarks also.
485 var g [4096]byte