Commit 8958d8ce authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: skip convT2E for empty structs

Fixes #18402

Change-Id: I5af800857fb2e365ce4224eece9171277106ec7d
Reviewed-on: https://go-review.googlesource.com/35562
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 3d5eb4a6
...@@ -365,6 +365,7 @@ var Thearch Arch ...@@ -365,6 +365,7 @@ var Thearch Arch
var ( var (
staticbytes, staticbytes,
zerobase,
Newproc, Newproc,
Deferproc, Deferproc,
Deferreturn, Deferreturn,
......
...@@ -894,26 +894,35 @@ opswitch: ...@@ -894,26 +894,35 @@ opswitch:
staticbytes = newname(Pkglookup("staticbytes", Runtimepkg)) staticbytes = newname(Pkglookup("staticbytes", Runtimepkg))
staticbytes.Class = PEXTERN staticbytes.Class = PEXTERN
staticbytes.Type = typArray(Types[TUINT8], 256) staticbytes.Type = typArray(Types[TUINT8], 256)
zerobase = newname(Pkglookup("zerobase", Runtimepkg))
zerobase.Class = PEXTERN
zerobase.Type = Types[TUINTPTR]
} }
// Optimize convT2{E,I} when T is not pointer-shaped, // Optimize convT2{E,I} for many cases in which T is not pointer-shaped,
// but the value does not escape or is a readonly global or is a bool/byte. // by using an existing addressable value identical to n.Left
// or creating one on the stack.
var value *Node var value *Node
switch { switch {
case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024: case n.Left.Type.Size() == 0:
// Initializing a stack temporary to the value we want to put in the interface, // n.Left is zero-sized. Use zerobase.
// then using the address of that stack temporary for the interface data word. value = zerobase
value = temp(n.Left.Type)
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly:
// readonly global; use directly.
value = n.Left
case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()): case n.Left.Type.IsBoolean() || (n.Left.Type.Size() == 1 && n.Left.Type.IsInteger()):
// n.Left is a bool/byte. Use staticbytes[n.Left].
value = nod(OINDEX, staticbytes, byteindex(n.Left)) value = nod(OINDEX, staticbytes, byteindex(n.Left))
value.Bounded = true value.Bounded = true
case n.Left.Class == PEXTERN && n.Left.Name != nil && n.Left.Name.Readonly:
// n.Left is a readonly global; use it directly.
value = n.Left
case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024:
// n.Left does not escape. Use a stack temporary initialized to n.Left.
value = temp(n.Left.Type)
init.Append(typecheck(nod(OAS, value, n.Left), Etop))
} }
if value != nil { if value != nil {
// Value is identical to n.Left.
// Construct the interface directly: {type/itab, &value}.
var t *Node var t *Node
if n.Type.IsEmptyInterface() { if n.Type.IsEmptyInterface() {
t = typename(n.Left.Type) t = typename(n.Left.Type)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment