2015-02-13 14:40:36 -05:00
// Copyright 2009 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 gc
2016-06-01 10:15:02 -07:00
import "sort"
2015-02-13 14:40:36 -05:00
const (
2015-02-27 20:44:45 +00:00
// expression switch
switchKindExpr = iota // switch a {...} or switch 5 {...}
switchKindTrue // switch true {...} or switch {...}
switchKindFalse // switch false {...}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// type switch
switchKindType // switch a.(type) {...}
)
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
const (
caseKindDefault = iota // default:
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// expression switch
caseKindExprConst // case 5:
caseKindExprVar // case x:
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// type switch
caseKindTypeNil // case nil:
caseKindTypeConst // case time.Time: (concrete type, has type hash)
caseKindTypeVar // case io.Reader: (interface type)
)
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
const binarySearchMin = 4 // minimum number of cases for binary search
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// An exprSwitch walks an expression switch.
type exprSwitch struct {
exprname * Node // node for the expression being switched on
kind int // kind of switch statement (switchKind*)
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// A typeSwitch walks a type switch.
type typeSwitch struct {
hashname * Node // node for the hash of the type of the variable being switched on
facename * Node // node for the concrete type of the variable being switched on
okname * Node // boolean node used for comma-ok type assertions
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// A caseClause is a single case clause in a switch statement.
type caseClause struct {
node * Node // points at case statement
ordinal int // position in switch
hash uint32 // hash of a type switch
typ uint8 // type of case
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// typecheckswitch typechecks a switch statement.
func typecheckswitch ( n * Node ) {
2016-03-02 17:34:42 -08:00
lno := lineno
2016-03-19 17:02:01 -07:00
typecheckslice ( n . Ninit . Slice ( ) , Etop )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
var nilonly string
var top int
var t * Type
2015-02-13 14:40:36 -05:00
2015-05-26 21:30:20 -04:00
if n . Left != nil && n . Left . Op == OTYPESW {
2015-02-27 20:44:45 +00:00
// type switch
top = Etype
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
n . Left . Right = typecheck ( n . Left . Right , Erv )
2015-05-26 21:30:20 -04:00
t = n . Left . Right . Type
2016-03-30 14:56:08 -07:00
if t != nil && ! t . IsInterface ( ) {
2016-03-15 13:06:58 -07:00
Yyerror ( "cannot type switch on non-interface value %v" , Nconv ( n . Left . Right , FmtLong ) )
2015-02-27 20:44:45 +00:00
}
} else {
// expression switch
top = Erv
2015-05-26 21:30:20 -04:00
if n . Left != nil {
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
n . Left = typecheck ( n . Left , Erv )
n . Left = defaultlit ( n . Left , nil )
2015-05-26 21:30:20 -04:00
t = n . Left . Type
2015-02-13 14:40:36 -05:00
} else {
2015-02-27 20:44:45 +00:00
t = Types [ TBOOL ]
}
if t != nil {
switch {
2015-03-01 07:54:01 +00:00
case ! okforeq [ t . Etype ] :
2016-03-15 13:06:58 -07:00
Yyerror ( "cannot switch on %v" , Nconv ( n . Left , FmtLong ) )
2016-04-01 11:22:03 -07:00
case t . IsSlice ( ) :
2015-02-27 20:44:45 +00:00
nilonly = "slice"
2016-04-01 11:22:03 -07:00
case t . IsArray ( ) && ! t . IsComparable ( ) :
2016-03-15 13:06:58 -07:00
Yyerror ( "cannot switch on %v" , Nconv ( n . Left , FmtLong ) )
2016-04-01 11:22:03 -07:00
case t . IsStruct ( ) :
if f := t . IncomparableField ( ) ; f != nil {
Yyerror ( "cannot switch on %v (struct containing %v cannot be compared)" , Nconv ( n . Left , FmtLong ) , f . Type )
}
2015-02-27 20:44:45 +00:00
case t . Etype == TFUNC :
nilonly = "func"
2016-03-30 14:56:08 -07:00
case t . IsMap ( ) :
2015-02-27 20:44:45 +00:00
nilonly = "map"
}
2015-02-13 14:40:36 -05:00
}
}
2015-02-27 20:44:45 +00:00
n . Type = t
2015-02-13 14:40:36 -05:00
2016-05-30 16:42:38 -07:00
var def , niltype * Node
2016-03-08 15:10:26 -08:00
for _ , ncase := range n . List . Slice ( ) {
2015-02-27 20:44:45 +00:00
setlineno ( n )
2016-03-08 15:10:26 -08:00
if ncase . List . Len ( ) == 0 {
2015-02-27 20:44:45 +00:00
// default
if def != nil {
2016-05-31 15:02:40 -07:00
setlineno ( ncase )
2015-02-27 20:44:45 +00:00
Yyerror ( "multiple defaults in switch (first at %v)" , def . Line ( ) )
} else {
def = ncase
}
} else {
2016-03-09 12:39:36 -08:00
ls := ncase . List . Slice ( )
for i1 , n1 := range ls {
2016-03-08 15:10:26 -08:00
setlineno ( n1 )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
ls [ i1 ] = typecheck ( ls [ i1 ] , Erv | Etype )
2016-03-09 12:39:36 -08:00
n1 = ls [ i1 ]
if n1 . Type == nil || t == nil {
2015-02-27 20:44:45 +00:00
continue
}
setlineno ( ncase )
switch top {
// expression switch
case Erv :
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
ls [ i1 ] = defaultlit ( ls [ i1 ] , t )
2016-03-09 12:39:36 -08:00
n1 = ls [ i1 ]
2015-02-27 20:44:45 +00:00
switch {
2016-03-09 12:39:36 -08:00
case n1 . Op == OTYPE :
Yyerror ( "type %v is not an expression" , n1 . Type )
case n1 . Type != nil && assignop ( n1 . Type , t , nil ) == 0 && assignop ( t , n1 . Type , nil ) == 0 :
2015-05-26 21:30:20 -04:00
if n . Left != nil {
2016-03-09 12:39:36 -08:00
Yyerror ( "invalid case %v in switch on %v (mismatched types %v and %v)" , n1 , n . Left , n1 . Type , t )
2015-02-27 20:44:45 +00:00
} else {
2016-03-09 12:39:36 -08:00
Yyerror ( "invalid case %v in switch (mismatched types %v and bool)" , n1 , n1 . Type )
2015-02-27 20:44:45 +00:00
}
2016-03-09 12:39:36 -08:00
case nilonly != "" && ! isnil ( n1 ) :
Yyerror ( "invalid case %v in switch (can only compare %s %v to nil)" , n1 , nilonly , n . Left )
2016-04-01 11:22:03 -07:00
case t . IsInterface ( ) && ! n1 . Type . IsInterface ( ) && ! n1 . Type . IsComparable ( ) :
2016-03-15 13:06:58 -07:00
Yyerror ( "invalid case %v in switch (incomparable type)" , Nconv ( n1 , FmtLong ) )
2015-02-27 20:44:45 +00:00
}
// type switch
case Etype :
2016-03-14 01:20:49 -07:00
var missing , have * Field
2015-02-27 20:44:45 +00:00
var ptr int
switch {
2016-04-01 13:36:24 -07:00
case n1 . Op == OLITERAL && n1 . Type . IsKind ( TNIL ) :
2016-05-30 16:42:38 -07:00
// case nil:
if niltype != nil {
Yyerror ( "multiple nil cases in type switch (first at %v)" , niltype . Line ( ) )
} else {
niltype = ncase
}
2016-03-09 12:39:36 -08:00
case n1 . Op != OTYPE && n1 . Type != nil : // should this be ||?
2016-03-15 13:06:58 -07:00
Yyerror ( "%v is not a type" , Nconv ( n1 , FmtLong ) )
2015-02-27 20:44:45 +00:00
// reset to original type
2016-03-09 12:39:36 -08:00
n1 = n . Left . Right
ls [ i1 ] = n1
2016-03-30 14:56:08 -07:00
case ! n1 . Type . IsInterface ( ) && t . IsInterface ( ) && ! implements ( n1 . Type , t , & missing , & have , & ptr ) :
2015-09-07 10:37:26 +10:00
if have != nil && ! missing . Broke && ! have . Broke {
2016-03-15 13:06:58 -07:00
Yyerror ( "impossible type switch case: %v cannot have dynamic type %v" + " (wrong type for %v method)\n\thave %v%v\n\twant %v%v" , Nconv ( n . Left . Right , FmtLong ) , n1 . Type , missing . Sym , have . Sym , Tconv ( have . Type , FmtShort ) , missing . Sym , Tconv ( missing . Type , FmtShort ) )
2015-09-07 10:37:26 +10:00
} else if ! missing . Broke {
2016-03-15 13:06:58 -07:00
Yyerror ( "impossible type switch case: %v cannot have dynamic type %v" + " (missing %v method)" , Nconv ( n . Left . Right , FmtLong ) , n1 . Type , missing . Sym )
2015-02-27 20:44:45 +00:00
}
}
}
}
}
if top == Etype && n . Type != nil {
2016-03-04 17:28:07 -08:00
ll := ncase . List
2016-03-08 15:10:26 -08:00
if ncase . Rlist . Len ( ) != 0 {
nvar := ncase . Rlist . First ( )
2016-04-01 13:36:24 -07:00
if ll . Len ( ) == 1 && ll . First ( ) . Type != nil && ! ll . First ( ) . Type . IsKind ( TNIL ) {
2015-02-27 20:44:45 +00:00
// single entry type switch
2016-03-08 15:10:26 -08:00
nvar . Name . Param . Ntype = typenod ( ll . First ( ) . Type )
2015-02-27 20:44:45 +00:00
} else {
// multiple entry type switch or default
2015-05-27 00:44:05 -04:00
nvar . Name . Param . Ntype = typenod ( n . Type )
2015-02-27 20:44:45 +00:00
}
2015-02-13 14:40:36 -05:00
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
nvar = typecheck ( nvar , Erv | Easgn )
2016-03-09 12:39:36 -08:00
ncase . Rlist . SetIndex ( 0 , nvar )
2015-02-27 20:44:45 +00:00
}
}
2015-02-13 14:40:36 -05:00
2016-03-19 17:02:01 -07:00
typecheckslice ( ncase . Nbody . Slice ( ) , Etop )
2015-02-13 14:40:36 -05:00
}
2016-03-02 17:34:42 -08:00
lineno = lno
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// walkswitch walks a switch statement.
func walkswitch ( sw * Node ) {
// convert switch {...} to switch true {...}
2015-05-26 21:30:20 -04:00
if sw . Left == nil {
sw . Left = Nodbool ( true )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
sw . Left = typecheck ( sw . Left , Erv )
2015-02-13 14:40:36 -05:00
}
2015-05-26 21:30:20 -04:00
if sw . Left . Op == OTYPESW {
2015-02-27 20:44:45 +00:00
var s typeSwitch
s . walk ( sw )
} else {
var s exprSwitch
s . walk ( sw )
2015-02-13 14:40:36 -05:00
}
}
2015-02-27 20:44:45 +00:00
// walk generates an AST implementing sw.
// sw is an expression switch.
// The AST is generally of the form of a linear
// search using if..goto, although binary search
// is used with long runs of constants.
func ( s * exprSwitch ) walk ( sw * Node ) {
casebody ( sw , nil )
2015-02-13 14:40:36 -05:00
2015-05-26 21:30:20 -04:00
cond := sw . Left
sw . Left = nil
2015-02-27 20:44:45 +00:00
s . kind = switchKindExpr
2015-05-26 21:30:20 -04:00
if Isconst ( cond , CTBOOL ) {
2015-02-27 20:44:45 +00:00
s . kind = switchKindTrue
2015-05-27 00:47:05 -04:00
if ! cond . Val ( ) . U . ( bool ) {
2015-02-27 20:44:45 +00:00
s . kind = switchKindFalse
2015-02-13 14:40:36 -05:00
}
}
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
cond = walkexpr ( cond , & sw . Ninit )
2015-02-27 20:44:45 +00:00
t := sw . Type
if t == nil {
return
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// convert the switch into OIF statements
2016-02-27 14:31:33 -08:00
var cas [ ] * Node
2015-02-27 20:44:45 +00:00
if s . kind == switchKindTrue || s . kind == switchKindFalse {
s . exprname = Nodbool ( s . kind == switchKindTrue )
2015-05-26 21:30:20 -04:00
} else if consttype ( cond ) >= 0 {
2015-02-27 20:44:45 +00:00
// leave constants to enable dead code elimination (issue 9608)
2015-05-26 21:30:20 -04:00
s . exprname = cond
2015-02-13 14:40:36 -05:00
} else {
2015-05-26 21:30:20 -04:00
s . exprname = temp ( cond . Type )
2016-02-27 14:31:33 -08:00
cas = [ ] * Node { Nod ( OAS , s . exprname , cond ) }
typecheckslice ( cas , Etop )
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// enumerate the cases, and lop off the default case
cc := caseClauses ( sw , s . kind )
2016-03-08 15:10:26 -08:00
sw . List . Set ( nil )
2015-02-27 20:44:45 +00:00
var def * Node
if len ( cc ) > 0 && cc [ 0 ] . typ == caseKindDefault {
def = cc [ 0 ] . node . Right
cc = cc [ 1 : ]
} else {
def = Nod ( OBREAK , nil , nil )
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// handle the cases in order
for len ( cc ) > 0 {
// deal with expressions one at a time
2015-03-01 07:54:01 +00:00
if ! okforcmp [ t . Etype ] || cc [ 0 ] . typ != caseKindExprConst {
2015-02-27 20:44:45 +00:00
a := s . walkCases ( cc [ : 1 ] )
2016-02-27 14:31:33 -08:00
cas = append ( cas , a )
2015-02-27 20:44:45 +00:00
cc = cc [ 1 : ]
continue
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// do binary search on runs of constants
var run int
for run = 1 ; run < len ( cc ) && cc [ run ] . typ == caseKindExprConst ; run ++ {
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// sort and compile constants
sort . Sort ( caseClauseByExpr ( cc [ : run ] ) )
a := s . walkCases ( cc [ : run ] )
2016-02-27 14:31:33 -08:00
cas = append ( cas , a )
2015-02-27 20:44:45 +00:00
cc = cc [ run : ]
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// handle default case
if nerrors == 0 {
2016-02-27 14:31:33 -08:00
cas = append ( cas , def )
sw . Nbody . Set ( append ( cas , sw . Nbody . Slice ( ) ... ) )
2016-03-07 22:54:46 -08:00
walkstmtlist ( sw . Nbody . Slice ( ) )
2015-02-27 20:44:45 +00:00
}
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// walkCases generates an AST implementing the cases in cc.
func ( s * exprSwitch ) walkCases ( cc [ ] * caseClause ) * Node {
if len ( cc ) < binarySearchMin {
// linear search
2016-03-08 10:26:20 -08:00
var cas [ ] * Node
2015-02-27 20:44:45 +00:00
for _ , c := range cc {
n := c . node
2016-03-02 17:34:42 -08:00
lno := setlineno ( n )
2015-02-27 20:44:45 +00:00
a := Nod ( OIF , nil , nil )
if ( s . kind != switchKindTrue && s . kind != switchKindFalse ) || assignop ( n . Left . Type , s . exprname . Type , nil ) == OCONVIFACE || assignop ( s . exprname . Type , n . Left . Type , nil ) == OCONVIFACE {
2015-05-26 21:30:20 -04:00
a . Left = Nod ( OEQ , s . exprname , n . Left ) // if name == val
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a . Left = typecheck ( a . Left , Erv )
2015-02-27 20:44:45 +00:00
} else if s . kind == switchKindTrue {
2015-05-26 21:30:20 -04:00
a . Left = n . Left // if val
2015-02-27 20:44:45 +00:00
} else {
// s.kind == switchKindFalse
2015-05-26 21:30:20 -04:00
a . Left = Nod ( ONOT , n . Left , nil ) // if !val
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a . Left = typecheck ( a . Left , Erv )
2015-02-27 20:44:45 +00:00
}
2016-03-10 10:13:42 -08:00
a . Nbody . Set1 ( n . Right ) // goto l
2015-02-27 20:44:45 +00:00
2016-03-08 10:26:20 -08:00
cas = append ( cas , a )
2016-03-02 17:34:42 -08:00
lineno = lno
2015-02-27 20:44:45 +00:00
}
return liststmt ( cas )
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// find the middle and recur
half := len ( cc ) / 2
a := Nod ( OIF , nil , nil )
2015-03-17 16:10:31 -07:00
mid := cc [ half - 1 ] . node . Left
le := Nod ( OLE , s . exprname , mid )
if Isconst ( mid , CTSTR ) {
// Search by length and then by value; see exprcmp.
lenlt := Nod ( OLT , Nod ( OLEN , s . exprname , nil ) , Nod ( OLEN , mid , nil ) )
leneq := Nod ( OEQ , Nod ( OLEN , s . exprname , nil ) , Nod ( OLEN , mid , nil ) )
2015-05-26 21:30:20 -04:00
a . Left = Nod ( OOROR , lenlt , Nod ( OANDAND , leneq , le ) )
2015-03-17 16:10:31 -07:00
} else {
2015-05-26 21:30:20 -04:00
a . Left = le
2015-03-17 16:10:31 -07:00
}
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a . Left = typecheck ( a . Left , Erv )
2016-03-10 10:13:42 -08:00
a . Nbody . Set1 ( s . walkCases ( cc [ : half ] ) )
a . Rlist . Set1 ( s . walkCases ( cc [ half : ] ) )
2015-02-27 20:44:45 +00:00
return a
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// casebody builds separate lists of statements and cases.
// It makes labels between cases and statements
// and deals with fallthrough, break, and unreachable statements.
2015-02-13 14:40:36 -05:00
func casebody ( sw * Node , typeswvar * Node ) {
2016-03-08 15:10:26 -08:00
if sw . List . Len ( ) == 0 {
2015-02-13 14:40:36 -05:00
return
}
2015-02-23 16:07:24 -05:00
lno := setlineno ( sw )
2015-02-13 14:40:36 -05:00
2016-03-04 17:28:07 -08:00
var cas [ ] * Node // cases
var stat [ ] * Node // statements
var def * Node // defaults
2015-02-23 16:07:24 -05:00
br := Nod ( OBREAK , nil , nil )
2015-02-13 14:40:36 -05:00
2016-03-09 12:39:36 -08:00
for i , n := range sw . List . Slice ( ) {
2015-02-13 14:40:36 -05:00
setlineno ( n )
if n . Op != OXCASE {
2016-04-27 15:10:10 +10:00
Fatalf ( "casebody %v" , n . Op )
2015-02-13 14:40:36 -05:00
}
n . Op = OCASE
2016-03-08 15:10:26 -08:00
needvar := n . List . Len ( ) != 1 || n . List . First ( ) . Op == OLITERAL
2015-02-13 14:40:36 -05:00
2016-08-15 21:09:39 -07:00
jmp := Nod ( OGOTO , autolabel ( ".s" ) , nil )
2016-03-08 15:10:26 -08:00
if n . List . Len ( ) == 0 {
2015-02-13 14:40:36 -05:00
if def != nil {
Yyerror ( "more than one default case" )
}
// reuse original default case
2015-02-27 20:44:45 +00:00
n . Right = jmp
2015-02-13 14:40:36 -05:00
def = n
}
2016-03-08 15:10:26 -08:00
if n . List . Len ( ) == 1 {
2015-02-27 20:44:45 +00:00
// one case -- reuse OCASE node
2016-03-08 15:10:26 -08:00
n . Left = n . List . First ( )
2015-02-27 20:44:45 +00:00
n . Right = jmp
2016-03-08 15:10:26 -08:00
n . List . Set ( nil )
2016-03-04 17:28:07 -08:00
cas = append ( cas , n )
2015-02-13 14:40:36 -05:00
} else {
// expand multi-valued cases
2016-03-08 15:10:26 -08:00
for _ , n1 := range n . List . Slice ( ) {
cas = append ( cas , Nod ( OCASE , n1 , jmp ) )
2015-02-13 14:40:36 -05:00
}
}
2016-02-27 14:31:33 -08:00
stat = append ( stat , Nod ( OLABEL , jmp . Left , nil ) )
2016-03-08 15:10:26 -08:00
if typeswvar != nil && needvar && n . Rlist . Len ( ) != 0 {
2016-02-27 14:31:33 -08:00
l := [ ] * Node {
2016-03-08 15:10:26 -08:00
Nod ( ODCL , n . Rlist . First ( ) , nil ) ,
Nod ( OAS , n . Rlist . First ( ) , typeswvar ) ,
2016-02-27 14:31:33 -08:00
}
typecheckslice ( l , Etop )
stat = append ( stat , l ... )
2015-02-13 14:40:36 -05:00
}
2016-02-27 14:31:33 -08:00
stat = append ( stat , n . Nbody . Slice ( ) ... )
2015-02-13 14:40:36 -05:00
2016-04-03 12:43:27 +01:00
// botch - shouldn't fall through declaration
2016-02-27 14:31:33 -08:00
last := stat [ len ( stat ) - 1 ]
2015-02-13 14:40:36 -05:00
if last . Xoffset == n . Xoffset && last . Op == OXFALL {
if typeswvar != nil {
setlineno ( last )
Yyerror ( "cannot fallthrough in type switch" )
}
2016-03-09 12:39:36 -08:00
if i + 1 >= sw . List . Len ( ) {
2015-02-13 14:40:36 -05:00
setlineno ( last )
Yyerror ( "cannot fallthrough final case in switch" )
}
last . Op = OFALL
} else {
2016-02-27 14:31:33 -08:00
stat = append ( stat , br )
2015-02-13 14:40:36 -05:00
}
}
2016-02-27 14:31:33 -08:00
stat = append ( stat , br )
2015-02-13 14:40:36 -05:00
if def != nil {
2016-03-04 17:28:07 -08:00
cas = append ( cas , def )
2015-02-13 14:40:36 -05:00
}
2016-03-08 15:10:26 -08:00
sw . List . Set ( cas )
2016-02-27 14:31:33 -08:00
sw . Nbody . Set ( stat )
2015-02-13 14:40:36 -05:00
lineno = lno
}
2015-02-27 20:44:45 +00:00
// caseClauses generates a slice of caseClauses
// corresponding to the clauses in the switch statement sw.
// Kind is the kind of switch statement.
func caseClauses ( sw * Node , kind int ) [ ] * caseClause {
var cc [ ] * caseClause
2016-03-08 15:10:26 -08:00
for _ , n := range sw . List . Slice ( ) {
2015-02-27 20:44:45 +00:00
c := new ( caseClause )
cc = append ( cc , c )
c . ordinal = len ( cc )
2015-02-13 14:40:36 -05:00
c . node = n
if n . Left == nil {
2015-02-27 20:44:45 +00:00
c . typ = caseKindDefault
2015-02-13 14:40:36 -05:00
continue
}
2015-02-27 20:44:45 +00:00
if kind == switchKindType {
// type switch
switch {
case n . Left . Op == OLITERAL :
c . typ = caseKindTypeNil
2016-04-01 13:36:24 -07:00
case n . Left . Type . IsInterface ( ) :
2015-02-27 20:44:45 +00:00
c . typ = caseKindTypeVar
default :
c . typ = caseKindTypeConst
c . hash = typehash ( n . Left . Type )
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
} else {
// expression switch
2015-02-13 14:40:36 -05:00
switch consttype ( n . Left ) {
2015-02-27 20:44:45 +00:00
case CTFLT , CTINT , CTRUNE , CTSTR :
c . typ = caseKindExprConst
default :
c . typ = caseKindExprVar
2015-02-13 14:40:36 -05:00
}
}
}
2015-02-27 20:44:45 +00:00
if cc == nil {
2015-02-13 14:40:36 -05:00
return nil
}
// sort by value and diagnose duplicate cases
2015-02-27 20:44:45 +00:00
if kind == switchKindType {
// type switch
sort . Sort ( caseClauseByType ( cc ) )
for i , c1 := range cc {
if c1 . typ == caseKindTypeNil || c1 . typ == caseKindDefault {
break
}
for _ , c2 := range cc [ i + 1 : ] {
if c2 . typ == caseKindTypeNil || c2 . typ == caseKindDefault || c1 . hash != c2 . hash {
2015-02-13 14:40:36 -05:00
break
}
2015-02-27 20:44:45 +00:00
if Eqtype ( c1 . node . Left . Type , c2 . node . Left . Type ) {
2016-03-02 11:01:25 -08:00
yyerrorl ( c2 . node . Lineno , "duplicate case %v in type switch\n\tprevious case at %v" , c2 . node . Left . Type , c1 . node . Line ( ) )
2015-02-13 14:40:36 -05:00
}
}
}
2015-02-27 20:44:45 +00:00
} else {
// expression switch
sort . Sort ( caseClauseByExpr ( cc ) )
for i , c1 := range cc {
if i + 1 == len ( cc ) {
break
}
c2 := cc [ i + 1 ]
if exprcmp ( c1 , c2 ) != 0 {
2015-02-13 14:40:36 -05:00
continue
}
2015-02-27 20:44:45 +00:00
setlineno ( c2 . node )
2015-04-17 12:03:22 -04:00
Yyerror ( "duplicate case %v in switch\n\tprevious case at %v" , c1 . node . Left , c1 . node . Line ( ) )
2015-02-13 14:40:36 -05:00
}
}
// put list back in processing order
2015-02-27 20:44:45 +00:00
sort . Sort ( caseClauseByOrd ( cc ) )
return cc
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// walk generates an AST that implements sw,
// where sw is a type switch.
// The AST is generally of the form of a linear
// search using if..goto, although binary search
// is used with long runs of concrete types.
func ( s * typeSwitch ) walk ( sw * Node ) {
2015-05-26 21:30:20 -04:00
cond := sw . Left
sw . Left = nil
if cond == nil {
2016-03-08 15:10:26 -08:00
sw . List . Set ( nil )
2015-02-13 14:40:36 -05:00
return
}
2015-05-26 21:30:20 -04:00
if cond . Right == nil {
2015-02-13 14:40:36 -05:00
setlineno ( sw )
Yyerror ( "type switch must have an assignment" )
return
}
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
cond . Right = walkexpr ( cond . Right , & sw . Ninit )
2016-04-01 13:36:24 -07:00
if ! cond . Right . Type . IsInterface ( ) {
2015-02-13 14:40:36 -05:00
Yyerror ( "type switch must be on an interface" )
return
}
2016-02-27 14:31:33 -08:00
var cas [ ] * Node
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// predeclare temporary variables and the boolean var
2015-05-26 21:30:20 -04:00
s . facename = temp ( cond . Right . Type )
2015-02-13 14:40:36 -05:00
2015-05-26 21:30:20 -04:00
a := Nod ( OAS , s . facename , cond . Right )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = typecheck ( a , Etop )
2016-02-27 14:31:33 -08:00
cas = append ( cas , a )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
s . okname = temp ( Types [ TBOOL ] )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
s . okname = typecheck ( s . okname , Erv )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
s . hashname = temp ( Types [ TUINT32 ] )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
s . hashname = typecheck ( s . hashname , Erv )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// set up labels and jumps
casebody ( sw , s . facename )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
cc := caseClauses ( sw , switchKindType )
2016-03-08 15:10:26 -08:00
sw . List . Set ( nil )
2015-02-23 16:07:24 -05:00
var def * Node
2015-02-27 20:44:45 +00:00
if len ( cc ) > 0 && cc [ 0 ] . typ == caseKindDefault {
def = cc [ 0 ] . node . Right
cc = cc [ 1 : ]
2015-02-13 14:40:36 -05:00
} else {
def = Nod ( OBREAK , nil , nil )
}
2016-02-21 20:43:14 -08:00
var typenil * Node
if len ( cc ) > 0 && cc [ 0 ] . typ == caseKindTypeNil {
typenil = cc [ 0 ] . node . Right
cc = cc [ 1 : ]
}
// For empty interfaces, do:
// if e._type == nil {
// do nil case if it exists, otherwise default
// }
// h := e._type.hash
// Use a similar strategy for non-empty interfaces.
// Get interface descriptor word.
typ := Nod ( OITAB , s . facename , nil )
// Check for nil first.
i := Nod ( OIF , nil , nil )
i . Left = Nod ( OEQ , typ , nodnil ( ) )
if typenil != nil {
// Do explicit nil case right here.
2016-03-10 10:13:42 -08:00
i . Nbody . Set1 ( typenil )
2016-02-21 20:43:14 -08:00
} else {
// Jump to default case.
2016-08-15 21:09:39 -07:00
lbl := autolabel ( ".s" )
2016-03-10 10:13:42 -08:00
i . Nbody . Set1 ( Nod ( OGOTO , lbl , nil ) )
2016-02-21 20:43:14 -08:00
// Wrap default case with label.
blk := Nod ( OBLOCK , nil , nil )
2016-03-08 15:10:26 -08:00
blk . List . Set ( [ ] * Node { Nod ( OLABEL , lbl , nil ) , def } )
2016-02-21 20:43:14 -08:00
def = blk
}
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
i . Left = typecheck ( i . Left , Erv )
2016-02-27 14:31:33 -08:00
cas = append ( cas , i )
2016-02-21 20:43:14 -08:00
2016-04-01 13:36:24 -07:00
if ! cond . Right . Type . IsEmptyInterface ( ) {
2016-02-21 20:43:14 -08:00
// Load type from itab.
2016-06-06 08:29:52 -07:00
typ = itabType ( typ )
2016-02-21 20:43:14 -08:00
}
// Load hash from type.
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
h := NodSym ( ODOTPTR , typ , nil )
2016-02-21 20:43:14 -08:00
h . Type = Types [ TUINT32 ]
h . Typecheck = 1
h . Xoffset = int64 ( 2 * Widthptr ) // offset of hash in runtime._type
h . Bounded = true // guaranteed not to fault
a = Nod ( OAS , s . hashname , h )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = typecheck ( a , Etop )
2016-02-27 14:31:33 -08:00
cas = append ( cas , a )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// insert type equality check into each case block
for _ , c := range cc {
n := c . node
switch c . typ {
case caseKindTypeVar , caseKindTypeConst :
n . Right = s . typeone ( n )
2016-02-21 20:43:14 -08:00
default :
Fatalf ( "typeSwitch with bad kind: %d" , c . typ )
2015-02-13 14:40:36 -05:00
}
}
2015-02-27 20:44:45 +00:00
// generate list of if statements, binary search for constant sequences
for len ( cc ) > 0 {
if cc [ 0 ] . typ != caseKindTypeConst {
n := cc [ 0 ] . node
2016-02-27 14:31:33 -08:00
cas = append ( cas , n . Right )
2015-02-27 20:44:45 +00:00
cc = cc [ 1 : ]
2015-02-13 14:40:36 -05:00
continue
}
// identify run of constants
2015-02-27 20:44:45 +00:00
var run int
for run = 1 ; run < len ( cc ) && cc [ run ] . typ == caseKindTypeConst ; run ++ {
2015-02-13 14:40:36 -05:00
}
// sort by hash
2015-02-27 20:44:45 +00:00
sort . Sort ( caseClauseByType ( cc [ : run ] ) )
2015-02-13 14:40:36 -05:00
// for debugging: linear search
if false {
2015-02-27 20:44:45 +00:00
for i := 0 ; i < run ; i ++ {
n := cc [ i ] . node
2016-02-27 14:31:33 -08:00
cas = append ( cas , n . Right )
2015-02-13 14:40:36 -05:00
}
continue
}
// combine adjacent cases with the same hash
2015-02-27 20:44:45 +00:00
ncase := 0
for i := 0 ; i < run ; i ++ {
2015-02-13 14:40:36 -05:00
ncase ++
2016-03-08 10:26:20 -08:00
hash := [ ] * Node { cc [ i ] . node . Right }
2015-02-27 20:44:45 +00:00
for j := i + 1 ; j < run && cc [ i ] . hash == cc [ j ] . hash ; j ++ {
2016-03-08 10:26:20 -08:00
hash = append ( hash , cc [ j ] . node . Right )
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
cc [ i ] . node . Right = liststmt ( hash )
2015-02-13 14:40:36 -05:00
}
// binary search among cases to narrow by hash
2016-02-27 14:31:33 -08:00
cas = append ( cas , s . walkCases ( cc [ : ncase ] ) )
2015-02-27 20:44:45 +00:00
cc = cc [ ncase : ]
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// handle default case
2015-02-13 14:40:36 -05:00
if nerrors == 0 {
2016-02-27 14:31:33 -08:00
cas = append ( cas , def )
sw . Nbody . Set ( append ( cas , sw . Nbody . Slice ( ) ... ) )
2016-03-08 15:10:26 -08:00
sw . List . Set ( nil )
2016-03-07 22:54:46 -08:00
walkstmtlist ( sw . Nbody . Slice ( ) )
2015-02-13 14:40:36 -05:00
}
}
2015-02-27 20:44:45 +00:00
// typeone generates an AST that jumps to the
// case body if the variable is of type t.
func ( s * typeSwitch ) typeone ( t * Node ) * Node {
2015-05-27 10:43:53 -04:00
var name * Node
2016-03-08 10:26:20 -08:00
var init [ ] * Node
2016-03-08 15:10:26 -08:00
if t . Rlist . Len ( ) == 0 {
2015-02-27 20:44:45 +00:00
name = nblank
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
nblank = typecheck ( nblank , Erv | Easgn )
2015-02-27 20:44:45 +00:00
} else {
2016-03-08 15:10:26 -08:00
name = t . Rlist . First ( )
2016-03-08 10:26:20 -08:00
init = [ ] * Node { Nod ( ODCL , name , nil ) }
2015-07-30 00:46:42 -04:00
a := Nod ( OAS , name , nil )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = typecheck ( a , Etop )
2016-03-08 10:26:20 -08:00
init = append ( init , a )
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
a := Nod ( OAS2 , nil , nil )
2016-03-08 15:10:26 -08:00
a . List . Set ( [ ] * Node { name , s . okname } ) // name, ok =
2015-02-27 20:44:45 +00:00
b := Nod ( ODOTTYPE , s . facename , nil )
b . Type = t . Left . Type // interface.(type)
2016-03-10 10:13:42 -08:00
a . Rlist . Set1 ( b )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a = typecheck ( a , Etop )
2016-03-08 10:26:20 -08:00
init = append ( init , a )
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
c := Nod ( OIF , nil , nil )
2015-05-26 21:30:20 -04:00
c . Left = s . okname
2016-03-10 10:13:42 -08:00
c . Nbody . Set1 ( t . Right ) // if ok { goto l }
2015-02-27 20:44:45 +00:00
2016-03-08 10:26:20 -08:00
return liststmt ( append ( init , c ) )
2015-02-27 20:44:45 +00:00
}
// walkCases generates an AST implementing the cases in cc.
func ( s * typeSwitch ) walkCases ( cc [ ] * caseClause ) * Node {
if len ( cc ) < binarySearchMin {
2016-03-08 10:26:20 -08:00
var cas [ ] * Node
2015-02-27 20:44:45 +00:00
for _ , c := range cc {
n := c . node
if c . typ != caseKindTypeConst {
2015-08-30 23:10:03 +02:00
Fatalf ( "typeSwitch walkCases" )
2015-02-27 20:44:45 +00:00
}
a := Nod ( OIF , nil , nil )
2015-05-26 21:30:20 -04:00
a . Left = Nod ( OEQ , s . hashname , Nodintconst ( int64 ( c . hash ) ) )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a . Left = typecheck ( a . Left , Erv )
2016-03-10 10:13:42 -08:00
a . Nbody . Set1 ( n . Right )
2016-03-08 10:26:20 -08:00
cas = append ( cas , a )
2015-02-27 20:44:45 +00:00
}
return liststmt ( cas )
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
// find the middle and recur
half := len ( cc ) / 2
a := Nod ( OIF , nil , nil )
2015-05-26 21:30:20 -04:00
a . Left = Nod ( OLE , s . hashname , Nodintconst ( int64 ( cc [ half - 1 ] . hash ) ) )
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
a . Left = typecheck ( a . Left , Erv )
2016-03-10 10:13:42 -08:00
a . Nbody . Set1 ( s . walkCases ( cc [ : half ] ) )
a . Rlist . Set1 ( s . walkCases ( cc [ half : ] ) )
2015-02-27 20:44:45 +00:00
return a
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
type caseClauseByOrd [ ] * caseClause
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
func ( x caseClauseByOrd ) Len ( ) int { return len ( x ) }
func ( x caseClauseByOrd ) Swap ( i , j int ) { x [ i ] , x [ j ] = x [ j ] , x [ i ] }
func ( x caseClauseByOrd ) Less ( i , j int ) bool {
c1 , c2 := x [ i ] , x [ j ]
switch {
// sort default first
case c1 . typ == caseKindDefault :
return true
case c2 . typ == caseKindDefault :
return false
// sort nil second
case c1 . typ == caseKindTypeNil :
return true
case c2 . typ == caseKindTypeNil :
return false
}
// sort by ordinal
return c1 . ordinal < c2 . ordinal
2015-02-13 14:40:36 -05:00
}
2015-02-27 20:44:45 +00:00
type caseClauseByExpr [ ] * caseClause
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
func ( x caseClauseByExpr ) Len ( ) int { return len ( x ) }
func ( x caseClauseByExpr ) Swap ( i , j int ) { x [ i ] , x [ j ] = x [ j ] , x [ i ] }
func ( x caseClauseByExpr ) Less ( i , j int ) bool {
return exprcmp ( x [ i ] , x [ j ] ) < 0
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
func exprcmp ( c1 , c2 * caseClause ) int {
// sort non-constants last
if c1 . typ != caseKindExprConst {
return + 1
}
if c2 . typ != caseKindExprConst {
return - 1
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
n1 := c1 . node . Left
n2 := c2 . node . Left
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// sort by type (for switches on interface)
2015-10-26 16:00:59 -07:00
ct := n1 . Val ( ) . Ctype ( )
if ct > n2 . Val ( ) . Ctype ( ) {
2015-02-27 20:44:45 +00:00
return + 1
}
2015-10-26 16:00:59 -07:00
if ct < n2 . Val ( ) . Ctype ( ) {
2015-02-27 20:44:45 +00:00
return - 1
}
if ! Eqtype ( n1 . Type , n2 . Type ) {
if n1 . Type . Vargen > n2 . Type . Vargen {
return + 1
2015-02-13 14:40:36 -05:00
} else {
2015-02-27 20:44:45 +00:00
return - 1
2015-02-13 14:40:36 -05:00
}
}
2015-02-27 20:44:45 +00:00
// sort by constant value to enable binary search
switch ct {
case CTFLT :
2016-03-20 13:55:42 -07:00
return n1 . Val ( ) . U . ( * Mpflt ) . Cmp ( n2 . Val ( ) . U . ( * Mpflt ) )
2015-02-27 20:44:45 +00:00
case CTINT , CTRUNE :
2016-03-20 13:55:42 -07:00
return n1 . Val ( ) . U . ( * Mpint ) . Cmp ( n2 . Val ( ) . U . ( * Mpint ) )
2015-02-27 20:44:45 +00:00
case CTSTR :
2015-03-17 16:10:31 -07:00
// Sort strings by length and then by value.
// It is much cheaper to compare lengths than values,
// and all we need here is consistency.
// We respect this sorting in exprSwitch.walkCases.
2015-05-27 00:47:05 -04:00
a := n1 . Val ( ) . U . ( string )
b := n2 . Val ( ) . U . ( string )
2015-03-17 16:10:31 -07:00
if len ( a ) < len ( b ) {
return - 1
}
if len ( a ) > len ( b ) {
return + 1
}
2015-09-23 23:31:17 +02:00
if a == b {
return 0
}
if a < b {
return - 1
}
return + 1
2015-02-27 20:44:45 +00:00
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
return 0
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
type caseClauseByType [ ] * caseClause
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
func ( x caseClauseByType ) Len ( ) int { return len ( x ) }
func ( x caseClauseByType ) Swap ( i , j int ) { x [ i ] , x [ j ] = x [ j ] , x [ i ] }
func ( x caseClauseByType ) Less ( i , j int ) bool {
c1 , c2 := x [ i ] , x [ j ]
switch {
// sort non-constants last
case c1 . typ != caseKindTypeConst :
return false
case c2 . typ != caseKindTypeConst :
return true
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// sort by hash code
case c1 . hash != c2 . hash :
return c1 . hash < c2 . hash
}
2015-02-13 14:40:36 -05:00
2015-02-27 20:44:45 +00:00
// sort by ordinal
return c1 . ordinal < c2 . ordinal
}