From d6dbf3a0d38773b37bd8fa8d64a3f192102e388b Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 21 Apr 2016 19:35:26 -0700 Subject: [PATCH] cmd/compile: use List instead of OKEY for OSLICE* MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Performance changes are negligible, but that's expected. This is a part of a general effort to eliminate OKEY nodes. Passes toolstash -cmp. Updates #15350 name old alloc/op new alloc/op delta Template 40.6MB ± 0% 40.6MB ± 0% -0.04% (p=0.000 n=9+10) Unicode 33.4MB ± 0% 33.4MB ± 0% ~ (p=0.853 n=10+10) GoTypes 120MB ± 0% 120MB ± 0% -0.03% (p=0.000 n=9+10) Compiler 470MB ± 0% 469MB ± 0% -0.06% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Template 404k ± 0% 404k ± 0% ~ (p=0.165 n=10+10) Unicode 350k ± 0% 350k ± 0% ~ (p=0.211 n=9+10) GoTypes 1.21M ± 0% 1.21M ± 0% ~ (p=0.315 n=10+10) Compiler 4.35M ± 0% 4.35M ± 0% -0.03% (p=0.001 n=10+10) Change-Id: I17d547bf9568b1ee2514a7ffab930424617f995e Reviewed-on: https://go-review.googlesource.com/32213 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 12 +++++-- src/cmd/compile/internal/gc/subr.go | 46 +++++++++++++----------- src/cmd/compile/internal/gc/syntax.go | 10 +++--- src/cmd/compile/internal/gc/typecheck.go | 3 ++ 4 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 20d0d6ace1..57a8175724 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -248,9 +248,15 @@ func ishairy(n *Node, budget *int32, reason *string) bool { } (*budget)-- - // TODO(mdempsky): Hack to appease toolstash; remove. - if n.Op == OSTRUCTKEY { + // TODO(mdempsky/josharian): Hacks to appease toolstash; remove. + // See issue 17566 and CL 31674 for discussion. + switch n.Op { + case OSTRUCTKEY: + (*budget)-- + case OSLICE, OSLICEARR, OSLICESTR: (*budget)-- + case OSLICE3, OSLICE3ARR: + *budget -= 2 } return *budget < 0 || ishairy(n.Left, budget, reason) || ishairy(n.Right, budget, reason) || @@ -428,7 +434,7 @@ func inlnode(n *Node) *Node { default: s := n.List.Slice() for i1, n1 := range s { - if n1.Op == OINLCALL { + if n1 != nil && n1.Op == OINLCALL { s[i1] = inlconv2expr(s[i1]) } } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 555f27e2b0..4e908b2367 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -1020,20 +1020,17 @@ func (n *Node) IsMethod() bool { // SliceBounds returns n's slice bounds: low, high, and max in expr[low:high:max]. // n must be a slice expression. max is nil if n is a simple slice expression. func (n *Node) SliceBounds() (low, high, max *Node) { + if n.List.Len() == 0 { + return nil, nil, nil + } + switch n.Op { case OSLICE, OSLICEARR, OSLICESTR: - if n.Right == nil { - return nil, nil, nil - } - if n.Right.Op != OKEY { - Fatalf("SliceBounds right %s", opnames[n.Right.Op]) - } - return n.Right.Left, n.Right.Right, nil + s := n.List.Slice() + return s[0], s[1], nil case OSLICE3, OSLICE3ARR: - if n.Right.Op != OKEY || n.Right.Right.Op != OKEY { - Fatalf("SliceBounds right %s %s", opnames[n.Right.Op], opnames[n.Right.Right.Op]) - } - return n.Right.Left, n.Right.Right.Left, n.Right.Right.Right + s := n.List.Slice() + return s[0], s[1], s[2] } Fatalf("SliceBounds op %v: %v", n.Op, n) return nil, nil, nil @@ -1047,20 +1044,29 @@ func (n *Node) SetSliceBounds(low, high, max *Node) { if max != nil { Fatalf("SetSliceBounds %v given three bounds", n.Op) } - if n.Right == nil { - n.Right = nod(OKEY, low, high) + s := n.List.Slice() + if s == nil { + if low == nil && high == nil { + return + } + n.List.Set([]*Node{low, high}) return } - n.Right.Left = low - n.Right.Right = high + s[0] = low + s[1] = high return case OSLICE3, OSLICE3ARR: - if n.Right == nil { - n.Right = nod(OKEY, low, nod(OKEY, high, max)) + s := n.List.Slice() + if s == nil { + if low == nil && high == nil && max == nil { + return + } + n.List.Set([]*Node{low, high, max}) + return } - n.Right.Left = low - n.Right.Right.Left = high - n.Right.Right.Right = max + s[0] = low + s[1] = high + s[2] = max return } Fatalf("SetSliceBounds op %v: %v", n.Op, n) diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 5c48fb7459..74492fd853 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -409,11 +409,11 @@ const ( OPRINTN // println(List) OPAREN // (Left) OSEND // Left <- Right - OSLICE // Left[Right.Left : Right.Right] (Left is untypechecked or slice; Right.Op==OKEY) - OSLICEARR // Left[Right.Left : Right.Right] (Left is array) - OSLICESTR // Left[Right.Left : Right.Right] (Left is string) - OSLICE3 // Left[R.Left : R.R.Left : R.R.R] (R=Right; Left is untypedchecked or slice; R.Op and R.R.Op==OKEY) - OSLICE3ARR // Left[R.Left : R.R.Left : R.R.R] (R=Right; Left is array; R.Op and R.R.Op==OKEY) + OSLICE // Left[List[0] : List[1]] (Left is untypechecked or slice) + OSLICEARR // Left[List[0] : List[1]] (Left is array) + OSLICESTR // Left[List[0] : List[1]] (Left is string) + OSLICE3 // Left[List[0] : List[1] : List[2]] (Left is untypedchecked or slice) + OSLICE3ARR // Left[List[0] : List[1] : List[2]] (Left is array) ORECOVER // recover() ORECV // <-Left ORUNESTR // Type(Left) (Type is string, Left is rune) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 2f30967e66..7de8ab7d04 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3866,6 +3866,9 @@ func markbreaklist(l Nodes, implicit *Node) { s := l.Slice() for i := 0; i < len(s); i++ { n := s[i] + if n == nil { + continue + } if n.Op == OLABEL && i+1 < len(s) && n.Name.Defn == s[i+1] { switch n.Name.Defn.Op { case OFOR, OSWITCH, OTYPESW, OSELECT, ORANGE: -- 2.48.1