Commit d03c1248 authored by Sokolov Yura's avatar Sokolov Yura Committed by Josh Bleecher Snyder

runtime: implement fastrand in go

So it could be inlined.

Using bit-tricks it could be implemented without condition
(improved trick version by Minux Ma).

Simple benchmark shows it is faster on i386 and x86_64, though
I don't know will it be faster on other architectures?

benchmark                       old ns/op     new ns/op     delta
BenchmarkFastrand-3             2.79          1.48          -46.95%
BenchmarkFastrandHashiter-3     25.9          24.9          -3.86%

Change-Id: Ie2eb6d0f598c0bb5fac7f6ad0f8b5e3eddaa361b
Reviewed-on: https://go-review.googlesource.com/34782Reviewed-by: default avatarMinux Ma <minux@golang.org>
Run-TryBot: Minux Ma <minux@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 9f75ecd5
......@@ -1595,20 +1595,6 @@ allsame:
MOVL BX, (AX)
RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVL g(CX), AX
MOVL g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
JPL 2(PC)
MOVL BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX
RET
......
......@@ -2163,19 +2163,6 @@ eqret:
MOVB $0, ret+48(FP)
RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVQ g(CX), AX
MOVQ g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX
RET
......
......@@ -991,19 +991,6 @@ eqret:
MOVB AX, ret+24(FP)
RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
get_tls(CX)
MOVL g(CX), AX
MOVL g_m(AX), AX
MOVL m_fastrand(AX), DX
ADDL DX, DX
MOVL DX, BX
XORL $0x88888eef, DX
CMOVLMI BX, DX
MOVL DX, m_fastrand(AX)
MOVL DX, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVL $0, AX
RET
......
......@@ -971,15 +971,6 @@ _sib_notfound:
MOVW R0, ret+12(FP)
RET
TEXT runtime·fastrand(SB),NOSPLIT,$-4-4
MOVW g_m(g), R1
MOVW m_fastrand(R1), R0
ADD.S R0, R0
EOR.MI $0x88888eef, R0
MOVW R0, m_fastrand(R1)
MOVW R0, ret+0(FP)
RET
TEXT runtime·return0(SB),NOSPLIT,$0
MOVW $0, R0
RET
......
......@@ -959,18 +959,6 @@ equal:
MOVB R0, ret+48(FP)
RET
TEXT runtime·fastrand(SB),NOSPLIT,$-8-4
MOVD g_m(g), R1
MOVWU m_fastrand(R1), R0
ADD R0, R0
CMPW $0, R0
BGE notneg
EOR $0x88888eef, R0
notneg:
MOVW R0, m_fastrand(R1)
MOVW R0, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R0
RET
......
......@@ -831,16 +831,6 @@ notfound:
MOVV R1, ret+24(FP)
RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVV g_m(g), R2
MOVWU m_fastrand(R2), R1
ADDU R1, R1
BGEZ R1, 2(PC)
XOR $0x88888eef, R1
MOVW R1, m_fastrand(R2)
MOVW R1, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R1
RET
......
......@@ -904,16 +904,6 @@ cmp_ret:
MOVW R8, ret+24(FP)
RET
TEXT runtime·fastrand(SB),NOSPLIT,$0-4
MOVW g_m(g), R2
MOVW m_fastrand(R2), R1
ADDU R1, R1
BGEZ R1, 2(PC)
XOR $0x88888eef, R1
MOVW R1, m_fastrand(R2)
MOVW R1, ret+0(FP)
RET
TEXT runtime·return0(SB),NOSPLIT,$0
MOVW $0, R1
RET
......
......@@ -1224,17 +1224,6 @@ TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
BR cmpbodyBE<>(SB)
#endif
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVWZ m_fastrand(R4), R3
ADD R3, R3
CMPW R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVW R3, m_fastrand(R4)
MOVW R3, ret+0(FP)
RET
TEXT runtime·return0(SB), NOSPLIT, $0
MOVW $0, R3
RET
......
......@@ -851,17 +851,6 @@ TEXT runtime·memeqbodyclc(SB),NOSPLIT|NOFRAME,$0-0
CLC $1, 0(R3), 0(R5)
RET
TEXT runtime·fastrand(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVWZ m_fastrand(R4), R3
ADD R3, R3
CMPW R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVW R3, m_fastrand(R4)
MOVW R3, ret+0(FP)
RET
TEXT bytes·IndexByte(SB),NOSPLIT|NOFRAME,$0-40
MOVD s+0(FP), R3 // s => R3
MOVD s_len+8(FP), R4 // s_len => R4
......
......@@ -245,3 +245,5 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
return
}
func Fastrand() uint32 { return fastrand() }
// Copyright 2017 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.
package runtime_test
import (
. "runtime"
"testing"
)
func BenchmarkFastrand(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Fastrand()
}
})
}
func BenchmarkFastrandHashiter(b *testing.B) {
var m = make(map[int]int, 10)
for i := 0; i < 10; i++ {
m[i] = i
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
for _ = range m {
break
}
}
})
}
......@@ -93,8 +93,15 @@ func reflect_memmove(to, from unsafe.Pointer, n uintptr) {
// exported value for testing
var hashLoad = loadFactor
// in asm_*.s
func fastrand() uint32
//go:nosplit
func fastrand() uint32 {
mp := getg().m
fr := mp.fastrand
fr <<= 1
fr ^= uint32(int32(fr)>>31) & 0x88888eef
mp.fastrand = fr
return fr
}
//go:linkname sync_fastrand sync.fastrand
func sync_fastrand() uint32 { return fastrand() }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment