addNamedValue takes &loc of a local ssa.LocalSlot and stores it in the long-lived f.Names
and f.CanonicalLocalSlots. Escape analysis is flow-insensitive, so this heap-allocates loc on
every call even when the slot already exists. Allocating only on the first-sighting path (mirroring
(*Func).localSlotAddr) keeps loc on the stack otherwise. Generated code is byte-identical.
compilebench -alloc, allocs/op, linux/amd64 (-count 20):
│ /tmp/old.txt │ /tmp/new.txt │
│ allocs/op │ allocs/op vs base │
Template 820.9k ± 0% 816.2k ± 0% -0.58% (p=0.000 n=20)
Unicode 574.2k ± 0% 573.7k ± 0% -0.07% (p=0.000 n=20)
GoTypes 5.013M ± 0% 4.971M ± 0% -0.83% (p=0.000 n=20)
Compiler 702.2k ± 0% 698.6k ± 0% -0.51% (p=0.000 n=20)
SSA 47.02M ± 0% 46.50M ± 0% -1.12% (p=0.000 n=20)
Flate 823.9k ± 0% 813.8k ± 0% -1.23% (p=0.000 n=20)
GoParser 791.3k ± 0% 788.1k ± 0% -0.41% (p=0.000 n=20)
Reflect 2.318M ± 0% 2.302M ± 0% -0.69% (p=0.000 n=20)
Tar 937.7k ± 0% 930.1k ± 0% -0.81% (p=0.000 n=20)
XML 1.099M ± 0% 1.090M ± 0% -0.77% (p=0.000 n=20)
LinkCompiler 729.0k ± 0% 729.1k ± 0% ~ (p=0.101 n=20)
ExternalLinkCompiler 731.6k ± 0% 731.6k ± 0% ~ (p=0.449 n=20)
LinkWithoutDebugCompiler 143.3k ± 0% 143.3k ± 0% ~ (p=0.358 n=20)
geomean 1.187M 1.181M -0.54%
A CL follows.
cc @golang/compiler
addNamedValuetakes&locof a localssa.LocalSlotand stores it in the long-livedf.Namesand
f.CanonicalLocalSlots. Escape analysis is flow-insensitive, so this heap-allocatesloconevery call even when the slot already exists. Allocating only on the first-sighting path (mirroring
(*Func).localSlotAddr) keepslocon the stack otherwise. Generated code is byte-identical.compilebench -alloc,allocs/op, linux/amd64 (-count 20):A CL follows.
cc @golang/compiler