From 8958d8ce37fdae15693787019869ab21e7b8347a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Sun, 22 Jan 2017 10:17:12 -0800 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/go.go | 1 + src/cmd/compile/internal/gc/walk.go | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 7c205f43c4..22e64b3764 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -365,6 +365,7 @@ var Thearch Arch var ( staticbytes, + zerobase, Newproc, Deferproc, Deferreturn, diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 148e629bd0..c57d15c2a1 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -894,26 +894,35 @@ opswitch: staticbytes = newname(Pkglookup("staticbytes", Runtimepkg)) staticbytes.Class = PEXTERN 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, - // but the value does not escape or is a readonly global or is a bool/byte. + // Optimize convT2{E,I} for many cases in which T is not pointer-shaped, + // by using an existing addressable value identical to n.Left + // or creating one on the stack. var value *Node switch { - case !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024: - // Initializing a stack temporary to the value we want to put in the interface, - // then using the address of that stack temporary for the interface data word. - 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.Size() == 0: + // n.Left is zero-sized. Use zerobase. + value = zerobase 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.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 { + // Value is identical to n.Left. + // Construct the interface directly: {type/itab, &value}. var t *Node if n.Type.IsEmptyInterface() { t = typename(n.Left.Type) -- 2.50.0