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