diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index bfc0004ff8..34a2ee8d13 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1295,7 +1295,9 @@ func zeroUpper32Bits(x *Value, depth int) bool { OpARM64MADDW, OpARM64MSUBW, OpARM64RORW, OpARM64RORWconst: return true case OpArg: // note: but not ArgIntReg - return x.Type.Size() == 4 + // amd64 always loads args from the stack unsigned. + // most other architectures load them sign/zero extended based on the type. + return x.Type.Size() == 4 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1319,7 +1321,7 @@ func zeroUpper48Bits(x *Value, depth int) bool { case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2: return true case OpArg: // note: but not ArgIntReg - return x.Type.Size() == 2 + return x.Type.Size() == 2 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1343,7 +1345,7 @@ func zeroUpper56Bits(x *Value, depth int) bool { case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1: return true case OpArg: // note: but not ArgIntReg - return x.Type.Size() == 1 + return x.Type.Size() == 1 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. diff --git a/test/fixedbugs/issue66066b.go b/test/fixedbugs/issue66066b.go new file mode 100644 index 0000000000..7540a85293 --- /dev/null +++ b/test/fixedbugs/issue66066b.go @@ -0,0 +1,58 @@ +// run + +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +//go:noinline +func f32(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x int32) uint64 { + return uint64(uint32(x)) +} + +//go:noinline +func f16(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x int16) uint64 { + return uint64(uint16(x)) +} + +//go:noinline +func f8(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x int8) uint64 { + return uint64(uint8(x)) +} + +//go:noinline +func g32(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x uint32) int64 { + return int64(int32(x)) +} + +//go:noinline +func g16(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x uint16) int64 { + return int64(int16(x)) +} + +//go:noinline +func g8(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, x uint8) int64 { + return int64(int8(x)) +} + +func main() { + if got := f32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1); got != 0xffffffff { + println("bad f32", got) + } + if got := f16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1); got != 0xffff { + println("bad f16", got) + } + if got := f8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1); got != 0xff { + println("bad f8", got) + } + if got := g32(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff); got != -1 { + println("bad g32", got) + } + if got := g16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffff); got != -1 { + println("bad g16", got) + } + if got := g8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff); got != -1 { + println("bad g8", got) + } +}