go version go1.28-devel_d1c1356637 Sun Jul 26 21:47:10 2026 -0700 linux/amd64
I guess it repros on all versions.
repro.go:
package main
var sink uint32
//go:noinline
func g(x uint32) { sink = x }
//go:noinline
func f(a, b uint32) int64 {
p := a * b // MULW <uint32> — register holds sign-extended 32-bit result
g(p) // p live across the call → spilled as uint32 (4 bytes), restored with MOVWU
return int64(int32(p)) // (MOVWreg (MULW)) elided at lower → uses restored (zero-extended) reg
}
func main() {
r := f(0x8000, 0x10000) // product = 0x80000000
if r != -2147483648 {
println("BUG: got", r, "want -2147483648")
return
}
println("ok")
}
> GOARCH=riscv64 go run repro.go
BUG: got 2147483648 want -2147483648
> GOARCH=arm64 go run repro.go
ok
> GOARCH=amd64 go run repro.go
ok
I guess it repros on all versions.
repro.go: