cmd/compile/internal/walk: expand the number of cases where the makeslicecopy function is generated.

73 views
Skip to first unread message

Oleg Aleksandrov

unread,
Jul 22, 2026, 12:06:00 PM (24 hours ago) Jul 22
to golang-dev
Hello,
I've been experimenting with generating the makeslicecopy function at the IR stage of the Go compiler. Generation for this function already exists (link to CL), but it 
is currently limited to cases where both dst and src are simple ir.Name nodes. My experiment extends this to handle more complex left-hand side expressions (such as pointer dereferencing, struct field access, and array indexing) without function calls.

To ensure correctness in these new cases, I am using ir.SameSafeExpr() to verify that src doesn't alias dst. Is this check sufficient, or are there aliasing scenarios it might miss? My change passes all tests of the Go compiler, but I would still appreciate confirmation that my approach is sound.

Finally, could you suggest which benchmarks I should use to evaluate the real-world performance of this change, beyond synthetic microbenchmarks?

Keith Randall

unread,
Jul 22, 2026, 7:16:15 PM (17 hours ago) Jul 22
to Oleg Aleksandrov, golang-dev
The generic answer is that you can assume SameSafeExpr does what its spec says, and nothing more.
The intent of that function is for code like

a, b := someExpression1, someExpression2

if SameSafeExpr(someExpression1, someExpression2) == true, then you can instead do
a := someExpression1
b := a

I don't think that says anything about aliasing. For instance, SameSafeExpr(a, a) == true. For something like:

a := []byte{3,4,5}
a = make([]byte, 5)
copy(a, a)

then you can't use the original value of `a` as the argument to makeslicecopy.

(The aliasing part in SameSafeExpr's spec is about the fact that a, b := make([]byte, 5), make([]byte, 5) must still make 2 byte slices.)

As far as benchmarks, a microbenchmark is fine to use for this case. But I'd also like a few references to where it actually triggers in real code. Not a benchmark per se, but some realistic code that would be helped by the optimization.



--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-dev/8a5b4754-f826-46e2-8948-446bc0636b7bn%40googlegroups.com.
Message has been deleted

Oleg Aleksandrov

unread,
11:04 AM (1 hour ago) 11:04 AM
to golang-dev
[DUBLICATE]

Thanks for the explanation.

After a brief search, I found the following code examples in large projects written in Go.

Case 1: Kubernetes

1) Many packages contain a zz_generated_deepcopy.go file. In this file you can find the following code examples:

*out = make([]Capability, len(*in))
copy(*out, *in)

or

*out = make([]byte, len(*in))
copy(*out, *in)

Links to the lines in code:
2) You can find this pattern:

out.Except = make([]string, len(in.Except))
copy(out.Except, in.Except)

Link: https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/extensions/v1beta1/conversion.go#L149-L150

3) Next pattern:

newMExps[i].Values = make([]string, len(me.Values))
copy(newMExps[i].Values, me.Values)

Link: https://github.com/kubernetes/kubernetes/blob/master/pkg/util/labels/labels.go#L94-L95

Case 2: moby

Code segments that can potentially be optimized:

p.PluginObj.Settings.Mounts = make([]plugin.Mount, len(p.PluginObj.Config.Mounts))
copy(p.PluginObj.Settings.Mounts, p.PluginObj.Config.Mounts)

p.PluginObj.Settings.Devices = make([]plugin.Device, len(p.PluginObj.Config.Linux.Devices))
copy(p.PluginObj.Settings.Devices, p.PluginObj.Config.Linux.Devices)

p.PluginObj.Settings.Args = make([]string, len(p.PluginObj.Config.Args.Value))
copy(p.PluginObj.Settings.Args, p.PluginObj.Config.Args.Value)

Links:

Case 3: go-ethereum

1) Code segments in accounts/abi/abigen/bind.go file:

normalized.Inputs = make([]abi.Argument, len(original.Inputs))
copy(normalized.Inputs, original.Inputs)

and

normalized.Outputs = make([]abi.Argument, len(original.Outputs))
copy(normalized.Outputs, original.Outputs)

Links:

2) Code segments in core/types/block.go file:

b.transactions = make(Transactions, len(txs))
copy(b.transactions, txs)

and

cpy.Extra = make([]byte, len(h.Extra))
copy(cpy.Extra, h.Extra)

Links:
четверг, 23 июля 2026 г. в 02:16:15 UTC+3, Keith Randall:
Reply all
Reply to author
Forward
0 new messages