1
0
mirror of https://github.com/golang/go synced 2024-11-19 23:54:40 -07:00

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 {

View File

@ -1531,6 +1531,19 @@ opswitch:
n = r
case OARRAYLIT, OMAPLIT, OSTRUCTLIT, OPTRLIT:
if (n.Op == OSTRUCTLIT || (n.Op == OARRAYLIT && !n.Type.IsSlice())) && isStaticCompositeLiteral(n) {
// n can be directly represented in the read-only data section.
// Make direct reference to the static data. See issue 12841.
vstat := staticname(n.Type, 0)
if n.Op == OSTRUCTLIT {
structlit(0, 1, n, vstat, init)
} else {
arraylit(0, 1, n, vstat, init)
}
n = vstat
n = typecheck(n, Erv)
break
}
var_ := temp(n.Type)
anylit(0, n, var_, init)
n = var_