You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The compiler currently compiles large structs conservatively. If a struct type has more than 4 fields (or a few other conditions), we treat that type as unSSAable. All operations on variables of that type go to the stack, as if their address was taken.
This is suboptimal in various ways. For example:
type T struct {
a, b, c, d int
}
func f(x *T) {
t := T{}
*x = t
}
type U struct {
a, b, c, d, e int
}
func g(x *U) {
u := U{}
*x = u
}
MOVQ BP, 40(SP)
LEAQ 40(SP), BP
MOVQ $0, "".u(SP)
XORPS X0, X0
MOVUPS X0, "".u+8(SP)
MOVUPS X0, "".u+24(SP)
MOVQ "".u(SP), AX
MOVQ "".x+56(SP), CX
MOVQ AX, (CX)
LEAQ 8(CX), DI
LEAQ "".u+8(SP), SI
DUFFCOPY $868
MOVQ 40(SP), BP
ADDQ $48, SP
RET
We zero a temporary variable on the stack, then copy it to the destination.
We should process large structs through SSA as well. This will require a fair amount of work in the SSA backend to introduce struct builders, selectors of arbitrary width, stack allocation of large types, maybe heap allocation if they are really huge, etc.
Arrays of size > 1 are in a similar state, but they are somewhat harder because non-constant indexes add an additional complication.
Just to ask an obvious question, is the problem that we want to handle all n, or just that n<=4 is too small? If the latter, and a reasonable cap is say 16, it might be easier to just extend the current approach, maybe using a bit of codegen magic. Probably we should Do It Right, but worth asking...
It definitely compiles to better code now, but I think the underlying issue is still there. I think it just needs a better test case.
package p
type T struct {
a, b, c, d int
}
type U struct {
a, b, c, d, e int
}
func f() int {
t := T{1, 2, 3, 4}
return t.c
}
func g() int {
u := U{1, 2, 3, 4, 5}
return u.c
}
It's not abandoned, it just isn't finished. It had issues. Performance wasn't good, and there were pathological cases, like large fields of even larger structs weren't handled well.
Reacted by Oleg Kovalov, quasilyte, Clément Nussbaumer, Vladimir Zhigulin, ignoramous, Matt Mueller, Beoran, inkeliz and black23eep
Activity
josharian commentedon Mar 15, 2018
Just to ask an obvious question, is the problem that we want to handle all n, or just that n<=4 is too small? If the latter, and a reasonable cap is say 16, it might be easier to just extend the current approach, maybe using a bit of codegen magic. Probably we should Do It Right, but worth asking...
randall77 commentedon Mar 15, 2018
My intent is to handle all n.
TocarIP commentedon Mar 21, 2018
Looks like this should also help #20859
gopherbot commentedon Apr 29, 2018
Change https://golang.org/cl/106495 mentions this issue:
cmd/compile: add some generic composite type optimizationscmd/compile: add some generic composite type optimizations
gopherbot commentedon Nov 12, 2019
Change https://golang.org/cl/206937 mentions this issue:
cmd/compile: optimize big structsChange uint128 from [2]uint64 to a struct of hi/lo to appease compiler
Change uint128 from [2]uint64 to a struct of hi/lo to appease compiler
zigo101 commentedon May 12, 2021
It looks, for Go toolchain v1.16, structs with 8 int fields and [8]int values have already been viewed as small-size values.
randall77 commentedon May 12, 2021
It definitely compiles to better code now, but I think the underlying issue is still there. I think it just needs a better test case.
fis compiles toMOVL $3, AX; RET.gcompiles toquasilyte commentedon Nov 9, 2021
I'm interested to know what's the status on this?
The CL206937 was abandoned but it's unclear why.
Are there any extra insights that came from that experiment?
randall77 commentedon Nov 9, 2021
It's not abandoned, it just isn't finished. It had issues. Performance wasn't good, and there were pathological cases, like large fields of even larger structs weren't handled well.
gopherbot commentedon Sep 5, 2024
Change https://go.dev/cl/611076 mentions this issue:
cmd/compile/internal/ssa: bump MaxStruct to 16gopherbot commentedon Sep 5, 2024
Change https://go.dev/cl/611075 mentions this issue:
cmd/compile: generalize struct load/storecmd/compile: generalize struct load/store
gopherbot commentedon Aug 5, 2026
Change https://go.dev/cl/810603 mentions this issue:
cmd/compile/internal/ssa: split MaxStruct and raise the SSA-ability capsgopherbot commentedon Aug 11, 2026
Change https://go.dev/cl/813343 mentions this issue:
cmd/compile: SSA-decompose small arraysgopherbot commentedon Aug 11, 2026
Change https://go.dev/cl/813340 mentions this issue:
cmd/compile: copy whole pointerful aggregates with a single Move