Repository navigation
cmd/compile: specialize instantiations of "certain" generic functions #81955
Description
Currently, generic functions are (almost) always shaped when instantiated, regardless of size. Shapes functions get the following overhead:
- Dictionary calls: any interface operation has to go through the dictionary, and this costs eight bytes of binary size per itab; any generic call must also have a dictionary entry for its relevant dictionary.
- Interface wrappers: interface calls to non-generic methods of generic type need a wrapper to shift the input registers and stick the dictionary in RAX or whatever.
This tradeoff has three benefits:
- Improved icache pressure because there are simply less functions. This helps mitigate overhead (1).
- Smaller binaries, which means faster link times (some people care a lot about this, although it is hard to know when to justify it over performance -- for the sake of disclosure, I only care about benefit (2) for the sake of (1)).
- Faster build times, because fewer functions hit SSA and ultimately produce assembly that the linker has to copy around.
My personal opinions aside (read: I come from C++), this is a pretty sound tradeoff between code density and performance for average code. However, I think we can do better.
A function is specialized when rather than being shaped, a brand new, non-shaped function is stamped "as if it were a macro". Specialization can coexist with shaping in the following way:
- shaped -> specialized. Requires a dictionary entry, except that this entry is a function pointer rather than a dictionary entry.
- specialized -> shaped. Exactly the same as calling a shaped function from monomorphic code: static call + pc-relative load of the dictionary.
So the question is, when do we specialize[1]? I am interested in investigating the following:
- Specialization of small functions (say, inline cost <80 or <40), especially those which only call other specialized functions.
- "Hot" functions, as reported by PGO. PGO does not currently record tparams of profiled functions, although we could, in theory, reconstruct this from the symbols of monomorphic functions called through a dictionary.
- Known-hot generic functions in the standard library, via a standard-library only
//go:specializepragma.
(1) and (3) are the easiest to investigate; (3) seems like it will have the easiest wins per code bloat (for example, specializing slices.Sort for ints and strings).
I do not know of any issues that are precisely about this topic, although #48849, #75056 appear relevant? I plan to investigate these avenues and get some performance numbers to see if there is some sensible middleground.
[1]: @dr2chase told me some time ago that "there is some function somewhere in the compiler for forcing specialization of an ir.Func given tparams", but I can't find such a thing. Perhaps it got ripped out.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
gabyhelp commentedon Oct 2, 2026
Related Issues
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
dmitshur commentedon Oct 5, 2026
CC @golang/compiler.