diff options
author | Martin Möhrmann <moehrmann@google.com> | 2018-10-23 13:50:07 +0200 |
---|---|---|
committer | Martin Möhrmann <moehrmann@google.com> | 2020-05-07 17:50:24 +0000 |
commit | 6ed4661807b219781d1aa452b7f210e21ad1974b (patch) | |
tree | d5ed10a2a7eb5096b1b67264468b8dc549d04d72 /test/codegen | |
parent | 97240d546c3ae54871c7c196e504e4a0a06faf87 (diff) | |
download | go-6ed4661807b219781d1aa452b7f210e21ad1974b.tar.gz go-6ed4661807b219781d1aa452b7f210e21ad1974b.zip |
cmd/compile: optimize make+copy pattern to avoid memclr
match:
m = make([]T, x); copy(m, s)
for pointer free T and x==len(s) rewrite to:
m = mallocgc(x*elemsize(T), nil, false); memmove(&m, &s, x*elemsize(T))
otherwise rewrite to:
m = makeslicecopy([]T, x, s)
This avoids memclear and shading of pointers in the newly created slice
before the copy.
With this CL "s" is only be allowed to bev a variable and not a more
complex expression. This restriction could be lifted in future versions
of this optimization when it can be proven that "s" is not referencing "m".
Triggers 450 times during make.bash..
Reduces go binary size by ~8 kbyte.
name old time/op new time/op delta
MakeSliceCopy/mallocmove/Byte 71.1ns ± 1% 65.8ns ± 0% -7.49% (p=0.000 n=10+9)
MakeSliceCopy/mallocmove/Int 71.2ns ± 1% 66.0ns ± 0% -7.27% (p=0.000 n=10+8)
MakeSliceCopy/mallocmove/Ptr 104ns ± 4% 99ns ± 1% -5.13% (p=0.000 n=10+10)
MakeSliceCopy/makecopy/Byte 70.3ns ± 0% 68.0ns ± 0% -3.22% (p=0.000 n=10+9)
MakeSliceCopy/makecopy/Int 70.3ns ± 0% 68.5ns ± 1% -2.59% (p=0.000 n=9+10)
MakeSliceCopy/makecopy/Ptr 102ns ± 0% 99ns ± 1% -2.97% (p=0.000 n=9+9)
MakeSliceCopy/nilappend/Byte 75.4ns ± 0% 74.9ns ± 2% -0.63% (p=0.015 n=9+9)
MakeSliceCopy/nilappend/Int 75.6ns ± 0% 76.4ns ± 3% ~ (p=0.245 n=9+10)
MakeSliceCopy/nilappend/Ptr 107ns ± 0% 108ns ± 1% +0.93% (p=0.005 n=9+10)
Fixes #26252
Change-Id: Iec553dd1fef6ded16197216a472351c8799a8e71
Reviewed-on: https://go-review.googlesource.com/c/go/+/146719
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'test/codegen')
-rw-r--r-- | test/codegen/slices.go | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/test/codegen/slices.go b/test/codegen/slices.go index cf569e27fb..40e857f9f6 100644 --- a/test/codegen/slices.go +++ b/test/codegen/slices.go @@ -104,6 +104,189 @@ func SliceExtensionInt64(s []int, l64 int64) []int { return append(s, make([]int, l64)...) } +// ------------------ // +// Make+Copy // +// ------------------ // + +// Issue #26252 - avoid memclr for make+copy + +func SliceMakeCopyLen(s []int) []int { + // amd64:`.*runtime\.mallocgc` + // amd64:`.*runtime\.memmove` + // amd64:-`.*runtime\.makeslice` + a := make([]int, len(s)) + copy(a, s) + return a +} + +func SliceMakeCopyLenPtr(s []*int) []*int { + // amd64:`.*runtime\.makeslicecopy` + // amd64:-`.*runtime\.makeslice\(` + // amd64:-`.*runtime\.typedslicecopy + a := make([]*int, len(s)) + copy(a, s) + return a +} + +func SliceMakeCopyConst(s []int) []int { + // amd64:`.*runtime\.makeslicecopy` + // amd64:-`.*runtime\.makeslice\(` + // amd64:-`.*runtime\.memmove` + a := make([]int, 4) + copy(a, s) + return a +} + +func SliceMakeCopyConstPtr(s []*int) []*int { + // amd64:`.*runtime\.makeslicecopy` + // amd64:-`.*runtime\.makeslice\(` + // amd64:-`.*runtime\.typedslicecopy + a := make([]*int, 4) + copy(a, s) + return a +} + +func SliceMakeCopyNoOptNoDeref(s []*int) []*int { + a := new([]*int) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + *a = make([]*int, 4) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(*a, s) + return *a +} + +func SliceMakeCopyNoOptNoVar(s []*int) []*int { + a := make([][]*int, 1) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a[0] = make([]*int, 4) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(a[0], s) + return a[0] +} + +func SliceMakeCopyNoOptBlank(s []*int) []*int { + var a []*int + // amd64:-`.*runtime\.makeslicecopy` + _ = make([]*int, 4) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(a, s) + return a +} + +func SliceMakeCopyNoOptNoMake(s []*int) []*int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:-`.*runtime\.objectnew` + a := *new([]*int) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(a, s) + return a +} + +func SliceMakeCopyNoOptNoHeapAlloc(s []*int) int { + // amd64:-`.*runtime\.makeslicecopy` + a := make([]*int, 4) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(a, s) + return cap(a) +} + +func SliceMakeCopyNoOptNoCap(s []*int) []*int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 0, 4) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.typedslicecopy` + copy(a, s) + return a +} + +func SliceMakeCopyNoOptNoCopy(s []*int) []*int { + copy := func(x, y []*int) {} + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 4) + // amd64:-`.*runtime\.makeslicecopy` + copy(a, s) + return a +} + +func SliceMakeCopyNoOptWrongOrder(s []*int) []*int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 4) + // amd64:`.*runtime\.typedslicecopy` + // amd64:-`.*runtime\.makeslicecopy` + copy(s, a) + return a +} + +func SliceMakeCopyNoOptWrongAssign(s []*int) []*int { + var a []*int + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + s = make([]*int, 4) + // amd64:`.*runtime\.typedslicecopy` + // amd64:-`.*runtime\.makeslicecopy` + copy(a, s) + return s +} + +func SliceMakeCopyNoOptCopyLength(s []*int) (int, []*int) { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 4) + // amd64:`.*runtime\.typedslicecopy` + // amd64:-`.*runtime\.makeslicecopy` + n := copy(a, s) + return n, a +} + +func SliceMakeCopyNoOptSelfCopy(s []*int) []*int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 4) + // amd64:`.*runtime\.typedslicecopy` + // amd64:-`.*runtime\.makeslicecopy` + copy(a, a) + return a +} + +func SliceMakeCopyNoOptTargetReference(s []*int) []*int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]*int, 4) + // amd64:`.*runtime\.typedslicecopy` + // amd64:-`.*runtime\.makeslicecopy` + copy(a, s[:len(a)]) + return a +} + +func SliceMakeCopyNoOptCap(s []int) []int { + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.makeslice\(` + a := make([]int, len(s), 9) + // amd64:-`.*runtime\.makeslicecopy` + // amd64:`.*runtime\.memmove` + copy(a, s) + return a +} + +func SliceMakeCopyNoMemmoveDifferentLen(s []int) []int { + // amd64:`.*runtime\.makeslicecopy` + // amd64:-`.*runtime\.memmove` + a := make([]int, len(s)-1) + // amd64:-`.*runtime\.memmove` + copy(a, s) + return a +} + // ---------------------- // // Nil check of &s[0] // // ---------------------- // |