What version of Go are you using (go version
)?
$ go version go version go1.13 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What did you do?
I compiled the following function:
package test
func pingPong(c chan int) {
for {
x := <- c
c <- x
}
}
What did you expect to see?
I expected that the generated code would not contain unnecessary instructions.
What did you see instead?
Instead, there are a couple of move instructions that don't accomplish anything (lines 25-26 in https://godbolt.org/z/RnTRWz).
Comment From: ivzhh
The syntax <- chan
will be translated to runtime
call: func chanrecv1(c *hchan, elem unsafe.Pointer)
. The address of the receiver will be passed as the second argument.
x := <- c
will create ORECV
node; later in order.go
, temporary variable .autotmp_2
is created and the AST will be translated as:
var .autotmp_2 int
chanrecv1(c, &.autotmp_2)
x := *(&.autotmp_2)
order.go
issues VarKill
and Vardef
for this temporary variable .autotmp_2
.
The SSA result in Opt
pass:
v18 (+5) = StaticCall <mem> {runtime.chanrecv1} [16] v17
v19 (5) = LocalAddr <*int> {.autotmp_2} v2 v18
v20 (5) = Load <int> v19 v18 (x[int])
v21 (4) = VarKill <mem> {.autotmp_2} v18
v22 (6) = VarDef <mem> {.autotmp_2} v21
v23 (6) = LocalAddr <*int> {.autotmp_2} v2 v22
v24 (6) = Store <mem> {int} v23 v20 v22
The cmd/compile/internal/ssa/gen/generic.rules
contains rules to remove extra store/load:
Eliminate stores of values that have just been loaded from the same location.
However, the (Store (LocalAddr (...
pattern is not included in generic.rules
.
Comment From: ivzhh
I have a fix now. Will submit to CL soon.
Comment From: gopherbot
Change https://golang.org/cl/212303 mentions this issue: cmd/compile: remove unnecessary MOV in channel receiving
Comment From: mariecurried
No longer reproduces. Fixed in Go 1.22