]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: convert constants to interfaces without allocating
authorJosh Bleecher Snyder <josharian@gmail.com>
Sat, 21 Jan 2017 21:41:06 +0000 (13:41 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Thu, 2 Feb 2017 21:02:23 +0000 (21:02 +0000)
The order pass is responsible for ensuring that
values passed to runtime functions, including
convT2E/convT2I, are addressable.

Prior to this CL, this was always accomplished
by creating a temp, which frequently escaped to
the heap, causing allocations, perhaps most
notably in code like:

fmt.Println(1, 2, 3) // allocates three times

None of the runtime routines modify the contents
of the pointers they receive, so in the case of
constants, instead of creating a temp value,
we can create a static value.

(Marking the static value as read-only provides
protection against accidental attempts by the runtime
to modify the constant data.)

This improves code generation for code like:

panic("abc")
c <- 2 // c is a chan int

which can now simply refer to "abc" and 2,
rather than going by way of a temporary.

It also allows us to optimize convT2E/convT2I,
by recognizing static readonly values
and directly constructing the interface.

This CL adds ~0.5% to binary size, despite
decreasing the size of many functions,
because it also adds many static symbols.

This binary size regression could be recovered in
future (but currently unplanned) work.

There is a lot of content-duplication in these
symbols; this statement generates six new symbols,
three containing an int 1 and three containing
a pointer to the string "a":

fmt.Println(1, 1, 1, "a", "a", "a")

These symbols could be made content-addressable.

Furthermore, these symbols are small, so the
alignment and naming overhead is large.
As with the go.strings section, these symbols
could be hidden and have their alignment reduced.

The changes to test/live.go make it impossible
(at least with current optimization techniques)
to place the values being passed to the runtime
in static symbols, preserving autotmp creation.

Fixes #18704

Benchmarks from fmt and go-kit's logging package:

github.com/go-kit/kit/log

name                      old time/op    new time/op    delta
JSONLoggerSimple-8          1.91µs ± 2%    2.11µs ±22%     ~     (p=1.000 n=9+10)
JSONLoggerContextual-8      2.60µs ± 6%    2.43µs ± 2%   -6.29%  (p=0.000 n=9+10)
Discard-8                    101ns ± 2%      34ns ±14%  -66.33%  (p=0.000 n=10+9)
OneWith-8                    161ns ± 1%     102ns ±16%  -36.78%  (p=0.000 n=10+10)
TwoWith-8                    175ns ± 3%     106ns ± 7%  -39.36%  (p=0.000 n=10+9)
TenWith-8                    293ns ± 3%     227ns ±15%  -22.44%  (p=0.000 n=9+10)
LogfmtLoggerSimple-8         704ns ± 2%     608ns ± 2%  -13.65%  (p=0.000 n=10+9)
LogfmtLoggerContextual-8     962ns ± 1%     860ns ±17%  -10.57%  (p=0.003 n=9+10)
NopLoggerSimple-8            188ns ± 1%     120ns ± 1%  -36.39%  (p=0.000 n=9+10)
NopLoggerContextual-8        379ns ± 1%     243ns ± 0%  -35.77%  (p=0.000 n=9+10)
ValueBindingTimestamp-8      577ns ± 1%     499ns ± 1%  -13.51%  (p=0.000 n=10+10)
ValueBindingCaller-8         898ns ± 2%     844ns ± 2%   -6.00%  (p=0.000 n=10+10)

name                      old alloc/op   new alloc/op   delta
JSONLoggerSimple-8            904B ± 0%      872B ± 0%   -3.54%  (p=0.000 n=10+10)
JSONLoggerContextual-8      1.20kB ± 0%    1.14kB ± 0%   -5.33%  (p=0.000 n=10+10)
Discard-8                    64.0B ± 0%     32.0B ± 0%  -50.00%  (p=0.000 n=10+10)
OneWith-8                    96.0B ± 0%     64.0B ± 0%  -33.33%  (p=0.000 n=10+10)
TwoWith-8                     160B ± 0%      128B ± 0%  -20.00%  (p=0.000 n=10+10)
TenWith-8                     672B ± 0%      640B ± 0%   -4.76%  (p=0.000 n=10+10)
LogfmtLoggerSimple-8          128B ± 0%       96B ± 0%  -25.00%  (p=0.000 n=10+10)
LogfmtLoggerContextual-8      304B ± 0%      240B ± 0%  -21.05%  (p=0.000 n=10+10)
NopLoggerSimple-8             128B ± 0%       96B ± 0%  -25.00%  (p=0.000 n=10+10)
NopLoggerContextual-8         304B ± 0%      240B ± 0%  -21.05%  (p=0.000 n=10+10)
ValueBindingTimestamp-8       159B ± 0%      127B ± 0%  -20.13%  (p=0.000 n=10+10)
ValueBindingCaller-8          112B ± 0%       80B ± 0%  -28.57%  (p=0.000 n=10+10)

name                      old allocs/op  new allocs/op  delta
JSONLoggerSimple-8            19.0 ± 0%      17.0 ± 0%  -10.53%  (p=0.000 n=10+10)
JSONLoggerContextual-8        25.0 ± 0%      21.0 ± 0%  -16.00%  (p=0.000 n=10+10)
Discard-8                     3.00 ± 0%      1.00 ± 0%  -66.67%  (p=0.000 n=10+10)
OneWith-8                     3.00 ± 0%      1.00 ± 0%  -66.67%  (p=0.000 n=10+10)
TwoWith-8                     3.00 ± 0%      1.00 ± 0%  -66.67%  (p=0.000 n=10+10)
TenWith-8                     3.00 ± 0%      1.00 ± 0%  -66.67%  (p=0.000 n=10+10)
LogfmtLoggerSimple-8          4.00 ± 0%      2.00 ± 0%  -50.00%  (p=0.000 n=10+10)
LogfmtLoggerContextual-8      7.00 ± 0%      3.00 ± 0%  -57.14%  (p=0.000 n=10+10)
NopLoggerSimple-8             4.00 ± 0%      2.00 ± 0%  -50.00%  (p=0.000 n=10+10)
NopLoggerContextual-8         7.00 ± 0%      3.00 ± 0%  -57.14%  (p=0.000 n=10+10)
ValueBindingTimestamp-8       5.00 ± 0%      3.00 ± 0%  -40.00%  (p=0.000 n=10+10)
ValueBindingCaller-8          4.00 ± 0%      2.00 ± 0%  -50.00%  (p=0.000 n=10+10)

fmt

name                             old time/op    new time/op    delta
SprintfPadding-8                   88.9ns ± 3%    79.1ns ± 1%   -11.09%  (p=0.000 n=10+7)
SprintfEmpty-8                     12.6ns ± 3%    12.8ns ± 3%      ~     (p=0.136 n=10+10)
SprintfString-8                    38.7ns ± 5%    26.9ns ± 6%   -30.65%  (p=0.000 n=10+10)
SprintfTruncateString-8            56.7ns ± 2%    47.0ns ± 3%   -17.05%  (p=0.000 n=10+10)
SprintfQuoteString-8                164ns ± 2%     153ns ± 2%    -7.01%  (p=0.000 n=10+10)
SprintfInt-8                       38.9ns ±15%    26.5ns ± 2%   -31.93%  (p=0.000 n=10+9)
SprintfIntInt-8                    60.3ns ± 9%    38.2ns ± 1%   -36.67%  (p=0.000 n=10+8)
SprintfPrefixedInt-8               58.6ns ±13%    51.2ns ±11%   -12.66%  (p=0.001 n=10+10)
SprintfFloat-8                     71.4ns ± 3%    64.2ns ± 3%   -10.08%  (p=0.000 n=8+10)
SprintfComplex-8                    175ns ± 3%     159ns ± 2%    -9.03%  (p=0.000 n=10+10)
SprintfBoolean-8                   33.5ns ± 4%    25.7ns ± 5%   -23.28%  (p=0.000 n=10+10)
SprintfHexString-8                 65.3ns ± 3%    51.7ns ± 5%   -20.86%  (p=0.000 n=10+9)
SprintfHexBytes-8                  67.2ns ± 5%    67.9ns ± 4%      ~     (p=0.383 n=10+10)
SprintfBytes-8                      129ns ± 7%     124ns ± 7%      ~     (p=0.074 n=9+10)
SprintfStringer-8                   127ns ± 4%     126ns ± 8%      ~     (p=0.506 n=9+10)
SprintfStructure-8                  357ns ± 3%     359ns ± 3%      ~     (p=0.469 n=10+10)
ManyArgs-8                          203ns ± 6%     126ns ± 3%   -37.94%  (p=0.000 n=10+10)
FprintInt-8                         119ns ±10%      74ns ± 3%   -37.54%  (p=0.000 n=10+10)
FprintfBytes-8                      122ns ± 4%     120ns ± 3%      ~     (p=0.124 n=10+10)
FprintIntNoAlloc-8                 78.2ns ± 5%    74.1ns ± 3%    -5.28%  (p=0.000 n=10+10)
ScanInts-8                          349µs ± 1%     349µs ± 0%      ~     (p=0.606 n=9+8)
ScanRecursiveInt-8                 43.8ms ± 7%    40.1ms ± 2%    -8.42%  (p=0.000 n=10+10)
ScanRecursiveIntReaderWrapper-8    43.5ms ± 4%    40.4ms ± 2%    -7.16%  (p=0.000 n=10+9)

name                             old alloc/op   new alloc/op   delta
SprintfPadding-8                    24.0B ± 0%     16.0B ± 0%   -33.33%  (p=0.000 n=10+10)
SprintfEmpty-8                      0.00B          0.00B           ~     (all equal)
SprintfString-8                     21.0B ± 0%      5.0B ± 0%   -76.19%  (p=0.000 n=10+10)
SprintfTruncateString-8             32.0B ± 0%     16.0B ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfQuoteString-8                48.0B ± 0%     32.0B ± 0%   -33.33%  (p=0.000 n=10+10)
SprintfInt-8                        16.0B ± 0%      1.0B ± 0%   -93.75%  (p=0.000 n=10+10)
SprintfIntInt-8                     24.0B ± 0%      3.0B ± 0%   -87.50%  (p=0.000 n=10+10)
SprintfPrefixedInt-8                72.0B ± 0%     64.0B ± 0%   -11.11%  (p=0.000 n=10+10)
SprintfFloat-8                      16.0B ± 0%      8.0B ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfComplex-8                    48.0B ± 0%     32.0B ± 0%   -33.33%  (p=0.000 n=10+10)
SprintfBoolean-8                    8.00B ± 0%     4.00B ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfHexString-8                  96.0B ± 0%     80.0B ± 0%   -16.67%  (p=0.000 n=10+10)
SprintfHexBytes-8                    112B ± 0%      112B ± 0%      ~     (all equal)
SprintfBytes-8                      96.0B ± 0%     96.0B ± 0%      ~     (all equal)
SprintfStringer-8                   32.0B ± 0%     32.0B ± 0%      ~     (all equal)
SprintfStructure-8                   256B ± 0%      256B ± 0%      ~     (all equal)
ManyArgs-8                          80.0B ± 0%      0.0B       -100.00%  (p=0.000 n=10+10)
FprintInt-8                         8.00B ± 0%     0.00B       -100.00%  (p=0.000 n=10+10)
FprintfBytes-8                      32.0B ± 0%     32.0B ± 0%      ~     (all equal)
FprintIntNoAlloc-8                  0.00B          0.00B           ~     (all equal)
ScanInts-8                         15.2kB ± 0%    15.2kB ± 0%      ~     (p=0.248 n=9+10)
ScanRecursiveInt-8                 21.6kB ± 0%    21.6kB ± 0%      ~     (all equal)
ScanRecursiveIntReaderWrapper-8    21.7kB ± 0%    21.7kB ± 0%      ~     (all equal)

name                             old allocs/op  new allocs/op  delta
SprintfPadding-8                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfEmpty-8                       0.00           0.00           ~     (all equal)
SprintfString-8                      2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfTruncateString-8              2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfQuoteString-8                 2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfInt-8                         2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfIntInt-8                      3.00 ± 0%      1.00 ± 0%   -66.67%  (p=0.000 n=10+10)
SprintfPrefixedInt-8                 2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfFloat-8                       2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfComplex-8                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfBoolean-8                     2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfHexString-8                   2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=10+10)
SprintfHexBytes-8                    2.00 ± 0%      2.00 ± 0%      ~     (all equal)
SprintfBytes-8                       2.00 ± 0%      2.00 ± 0%      ~     (all equal)
SprintfStringer-8                    4.00 ± 0%      4.00 ± 0%      ~     (all equal)
SprintfStructure-8                   7.00 ± 0%      7.00 ± 0%      ~     (all equal)
ManyArgs-8                           8.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
FprintInt-8                          1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)
FprintfBytes-8                       1.00 ± 0%      1.00 ± 0%      ~     (all equal)
FprintIntNoAlloc-8                   0.00           0.00           ~     (all equal)
ScanInts-8                          1.60k ± 0%     1.60k ± 0%      ~     (all equal)
ScanRecursiveInt-8                  1.71k ± 0%     1.71k ± 0%      ~     (all equal)
ScanRecursiveIntReaderWrapper-8     1.71k ± 0%     1.71k ± 0%      ~     (all equal)

Change-Id: I7ba72a25fea4140a0ba40a9f443103ed87cc69b5
Reviewed-on: https://go-review.googlesource.com/35554
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/walk.go
src/cmd/internal/obj/data.go
test/live.go

index 616945685c33e39b7a4d7cde5b181a57abc3dff5..4913e3c11ae2fe0d0982d1b075080dc712c344aa 100644 (file)
@@ -183,7 +183,23 @@ func isaddrokay(n *Node) bool {
 // Orderaddrtemp ensures that n is okay to pass by address to runtime routines.
 // If the original argument n is not okay, orderaddrtemp creates a tmp, emits
 // tmp = n, and then returns tmp.
+// The result of orderaddrtemp MUST be assigned back to n, e.g.
+//     n.Left = orderaddrtemp(n.Left, order)
 func orderaddrtemp(n *Node, order *Order) *Node {
+       if consttype(n) >= 0 {
+               // TODO: expand this to all static composite literal nodes?
+               n = defaultlit(n, nil)
+               dowidth(n.Type)
+               vstat := staticname(n.Type)
+               vstat.Name.Readonly = true
+               var out []*Node
+               staticassign(vstat, n, &out)
+               if out != nil {
+                       Fatalf("staticassign of const generated code: %+v", n)
+               }
+               vstat = typecheck(vstat, Erv)
+               return vstat
+       }
        if isaddrokay(n) {
                return n
        }
index d5da17011936b367f55d8d3072bad90779792e62..ba4b1af4ff18f0ab2b23acf1c732bd23def45d77 100644 (file)
@@ -889,20 +889,29 @@ opswitch:
                        n = l
                        break
                }
-               // Optimize convT2{E,I} when T is not pointer-shaped.
-               // We make the interface by 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.
-               if !n.Left.Type.IsInterface() && n.Esc == EscNone && n.Left.Type.Width <= 1024 {
-                       tmp := temp(n.Left.Type)
-                       init.Append(typecheck(nod(OAS, tmp, n.Left), Etop))
+
+               // Optimize convT2{E,I} when T is not pointer-shaped,
+               // but the value does not escape or is a readonly global.
+               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
+               }
+
+               if value != nil {
                        var t *Node
                        if n.Type.IsEmptyInterface() {
                                t = typename(n.Left.Type)
                        } else {
                                t = itabname(n.Left.Type, n.Type)
                        }
-                       l := nod(OEFACE, t, typecheck(nod(OADDR, tmp, nil), Erv))
+                       l := nod(OEFACE, t, typecheck(nod(OADDR, value, nil), Erv))
                        l.Type = n.Type
                        l.Typecheck = n.Typecheck
                        n = l
index d5565f24dcfc65e6783a4d67c4cddce2f997d74a..114841dedb471f607858647766d1c4c8a9f19df9 100644 (file)
@@ -70,7 +70,7 @@ func (s *LSym) GrowCap(c int64) {
 // prepwrite prepares to write data of size siz into s at offset off.
 func (s *LSym) prepwrite(ctxt *Link, off int64, siz int) {
        if off < 0 || siz < 0 || off >= 1<<30 {
-               log.Fatalf("prepwrite: bad off=%d siz=%d", off, siz)
+               log.Fatalf("prepwrite: bad off=%d siz=%d s=%v", off, siz, s)
        }
        if s.Type == SBSS || s.Type == STLSBSS {
                ctxt.Diag("cannot supply data for BSS var")
index b23e1509e01da640e33a0023dd41817e02f2116d..462f3ef12e92965d6b5fbb9707d20c09f797e226 100644 (file)
@@ -141,7 +141,7 @@ var i9 interface{}
 func f9() bool {
        g8()
        x := i9
-       y := interface{}(99.0i) // ERROR "live at call to convT2E: x.data x.type$"
+       y := interface{}(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+ x.data x.type$" "live at call to str: x.data x.type$"
        i9 = y                  // make y escape so the line above has to call convT2E
        return x != y
 }
@@ -256,12 +256,15 @@ func g15() string
 
 var m map[string]int
 
+// str is used to ensure that a temp is required for runtime calls below.
+func str() string
+
 func f16() {
        if b {
-               delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+               delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
        }
-       delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
-       delete(m, "hi") // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+       delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
+       delete(m, str()) // ERROR "live at call to mapdelete: .autotmp_[0-9]+$"
 }
 
 var m2s map[string]*byte
@@ -280,19 +283,19 @@ func f17a(p *byte) { // ERROR "live at entry to f17a: p$"
 func f17b(p *byte) { // ERROR "live at entry to f17b: p$"
        // key temporary
        if b {
-               m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
+               m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
        }
-       m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
-       m2s["x"] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$"
+       m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
+       m2s[str()] = p // ERROR "live at call to mapassign: p .autotmp_[0-9]+$" "live at call to str: p$"
 }
 
 func f17c() {
        // key and value temporaries
        if b {
-               m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+               m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
        }
-       m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
-       m2s["x"] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+       m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
+       m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign: .autotmp_[0-9]+ .autotmp_[0-9]+$"
 }
 
 func f17d() *byte
@@ -313,6 +316,9 @@ func f18() {
 
 var ch chan *byte
 
+// byteptr is used to ensure that a temp is required for runtime calls below.
+func byteptr() *byte
+
 func f19() {
        // dest temporary for channel receive.
        var z *byte
@@ -328,10 +334,10 @@ func f19() {
 func f20() {
        // src temporary for channel send
        if b {
-               ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+               ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
        }
-       ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
-       ch <- nil // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+       ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
+       ch <- byteptr() // ERROR "live at call to chansend1: .autotmp_[0-9]+$"
 }
 
 func f21() {
@@ -488,13 +494,13 @@ func f30(b bool) {
 
 func f31(b1, b2, b3 bool) {
        if b1 {
-               g31("a") // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to g31: .autotmp_[0-9]+$"
+               g31(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to g31: .autotmp_[0-9]+$"
        }
        if b2 {
-               h31("b") // ERROR "live at call to convT2E: .autotmp_[0-9]+ .autotmp_[0-9]+$" "live at call to h31: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
+               h31(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+ .autotmp_[0-9]+$" "live at call to h31: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
        }
        if b3 {
-               panic("asdf") // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to gopanic: .autotmp_[0-9]+$"
+               panic(str()) // ERROR "live at call to convT2E: .autotmp_[0-9]+$" "live at call to gopanic: .autotmp_[0-9]+$"
        }
        print(b3)
 }
@@ -529,7 +535,7 @@ func call32(func())
 var m33 map[interface{}]int
 
 func f33() {
-       if m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+       if m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
                printnl()
                return
        } else {
@@ -539,7 +545,7 @@ func f33() {
 }
 
 func f34() {
-       if m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+       if m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
                printnl()
                return
        }
@@ -547,7 +553,7 @@ func f34() {
 }
 
 func f35() {
-       if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+       if m33[byteptr()] == 0 && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
                printnl()
                return
        }
@@ -555,7 +561,7 @@ func f35() {
 }
 
 func f36() {
-       if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+       if m33[byteptr()] == 0 || m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
                printnl()
                return
        }
@@ -563,7 +569,7 @@ func f36() {
 }
 
 func f37() {
-       if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+       if (m33[byteptr()] == 0 || m33[byteptr()] == 0) && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
                printnl()
                return
        }