]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: refactor memclrrange for arrays and slices
authorMartin Möhrmann <moehrmann@google.com>
Mon, 30 Apr 2018 13:48:56 +0000 (15:48 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Wed, 2 May 2018 04:20:25 +0000 (04:20 +0000)
Rename memclrrange to signify that it does not handle
all types of range clears.

Simplify checks to detect the range clear idiom for
arrays and slices.

Add tests to verify the optimization for the slice
range clear idiom is being applied by the compiler.

Change-Id: I5c3b7c9a479699ebdb4c407fde692f30f377860c
Reviewed-on: https://go-review.googlesource.com/110477
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/compile/internal/gc/range.go
test/codegen/slices.go [new file with mode: 0644]

index a51cd16a8d306c5e60c15cb5193b0ec24743dea6..5c3c5ca088960f4a9eccd7fca29291ad5b3f1cc1 100644 (file)
@@ -204,7 +204,7 @@ func walkrange(n *Node) *Node {
                Fatalf("walkrange")
 
        case TARRAY, TSLICE:
-               if memclrrange(n, v1, v2, a) {
+               if arrayClear(n, v1, v2, a) {
                        lineno = lno
                        return n
                }
@@ -460,23 +460,28 @@ func walkrange(n *Node) *Node {
 // in which the evaluation of a is side-effect-free.
 //
 // Parameters are as in walkrange: "for v1, v2 = range a".
-func memclrrange(n, v1, v2, a *Node) bool {
+func arrayClear(n, v1, v2, a *Node) bool {
        if Debug['N'] != 0 || instrumenting {
                return false
        }
+
        if v1 == nil || v2 != nil {
                return false
        }
-       if n.Nbody.Len() == 0 || n.Nbody.First() == nil || n.Nbody.Len() > 1 {
+
+       if n.Nbody.Len() != 1 || n.Nbody.First() == nil {
                return false
        }
+
        stmt := n.Nbody.First() // only stmt in body
        if stmt.Op != OAS || stmt.Left.Op != OINDEX {
                return false
        }
+
        if !samesafeexpr(stmt.Left.Left, a) || !samesafeexpr(stmt.Left.Right, v1) {
                return false
        }
+
        elemsize := n.Type.Elem().Width
        if elemsize <= 0 || !isZero(stmt.Right) {
                return false
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
new file mode 100644 (file)
index 0000000..a5fae74
--- /dev/null
@@ -0,0 +1,32 @@
+// asmcheck
+
+// Copyright 2018 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 codegen
+
+// This file contains code generation tests related to the handling of
+// slice types.
+
+// ------------------ //
+//      Clear         //
+// ------------------ //
+
+// Issue #5373 optimize memset idiom
+
+func SliceClear(s []int) []int {
+       // amd64:`.*memclrNoHeapPointers`
+       for i := range s {
+               s[i] = 0
+       }
+       return s
+}
+
+func SliceClearPointers(s []*int) []*int {
+       // amd64:`.*memclrHasPointers`
+       for i := range s {
+               s[i] = nil
+       }
+       return s
+}