From 500d79c410f8e9ad762ba318a0a4b05d0d4d1751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 30 Apr 2018 15:48:56 +0200 Subject: [PATCH] cmd/compile: refactor memclrrange for arrays and slices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/cmd/compile/internal/gc/range.go | 11 +++++++--- test/codegen/slices.go | 32 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/codegen/slices.go diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index a51cd16a8d3..5c3c5ca0889 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -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 index 00000000000..a5fae7426d7 --- /dev/null +++ b/test/codegen/slices.go @@ -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 +}