cmd/compile: eliminate copy for static literals

*p = [5]byte{1,2,3,4,5}

First we allocate a global containing the RHS.  Then we copy
that global to a local stack variable, and then copy that local
stack variable to *p.  The intermediate copy is unnecessary.

Note that this only works if the RHS is completely constant.
If the code was:
*p = [5]byte{1,2,x,4,5}
this optimization doesn't apply as we have to construct the
RHS on the stack before copying it to *p.

Fixes #12841

Change-Id: I7cd0404ecc7a2d1750cbd8fe1222dba0fa44611f
Reviewed-on: https://go-review.googlesource.com/22192
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Keith Randall 2016-04-18 11:17:55 -07:00
parent f60fcca5f1
commit b024ed0d94
2 changed files with 39 additions and 0 deletions

View file

@ -563,6 +563,32 @@ func getdyn(n *Node, top int) initGenType {
return mode
}
// isStaticCompositeLiteral reports whether n is a compile-time constant.
// n must be a struct or array literal.
func isStaticCompositeLiteral(n *Node) bool {
for _, r := range n.List.Slice() {
if r.Op != OKEY {
Fatalf("isStaticCompositeLiteral: rhs not OKEY: %v", r)
}
index := r.Left
if n.Op == OARRAYLIT && index.Op != OLITERAL {
return false
}
value := r.Right
switch value.Op {
case OSTRUCTLIT, OARRAYLIT:
if !isStaticCompositeLiteral(value) {
return false
}
default:
if value.Op != OLITERAL {
return false
}
}
}
return true
}
func structlit(ctxt int, pass int, n *Node, var_ *Node, init *Nodes) {
for _, r := range n.List.Slice() {
if r.Op != OKEY {