From 5a56d8848b4ffb79c5ccc11ec6fa01823a91aaf8 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 18 Aug 2025 10:17:27 -0700 Subject: [PATCH] cmd/compile: ensure we use allowed registers for input-clobbering instructions For instructions which clobber their input register, we make a second copy of the input value so it is still available in a register for future instructions. That second copy might not respect the register input restrictions for the instruction. So the second copy we make here can't actually be used by the instruction - it should use the first copy, the second copy is the one that will persist beyond the clobber. Fixes #75063 Change-Id: I99acdc63f0c4e54567a174ff7ada601ae4e796b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/697015 Auto-Submit: Keith Randall Reviewed-by: Keith Randall Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/ssa/regalloc.go | 3 +- test/fixedbugs/issue75063.go | 75 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue75063.go diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index f3c1d3bd96..43669fd143 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1725,10 +1725,9 @@ func (s *regAllocState) regalloc(f *Func) { // spilling the value with the most distant next use. continue } - // Copy input to a new clobberable register. + // Copy input to a different register that won't be clobbered. c := s.allocValToReg(v.Args[i], m, true, v.Pos) s.copies[c] = false - args[i] = c } // Pick a temporary register if needed. diff --git a/test/fixedbugs/issue75063.go b/test/fixedbugs/issue75063.go new file mode 100644 index 0000000000..5caa7cb9ab --- /dev/null +++ b/test/fixedbugs/issue75063.go @@ -0,0 +1,75 @@ +// compile + +// Copyright 2025 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 reorder + +type Element struct { + A string + B string + C string + D string + E string + Text []string + List []string + Child Elements + F string + G bool + H bool + I string +} + +type Elements []Element + +func DoesNotCompile(ve Elements) Elements { + aa := Elements{} + bb := Elements{} + cc := Elements{} + dd := Elements{} + ee := Elements{} + ff := Elements{} + gg := Elements{} + hh := Elements{} + ii := Elements{} + + if len(ve) != 1 { + return ve + } + for _, e := range ve[0].Child { + if len(e.Text) == 1 && (e.Text[0] == "xx") { + ee = append(ee, e) + } else if len(e.Text) == 1 && e.Text[0] == "yy" { + for _, c := range e.Child { + if len(c.Text) == 1 && c.Text[0] == "zz" { + ii = append(ii, c) + } else { + hh = append(hh, c) + } + } + ii = append(ii, hh...) + e.Child = ii + gg = append(gg, e) + } else if len(e.Text) == 1 && e.Text[0] == "tt" { + for _, entry := range e.Child { + for _, c := range entry.Child { + if len(c.Text) == 1 && c.Text[0] == "ee" { + cc = append(cc, c) + } else { + dd = append(dd, c) + } + } + cc = append(cc, dd...) + entry.Child = cc + bb = append(bb, entry) + cc, dd = Elements{}, Elements{} + } + e.Child = bb + aa = append(aa, e) + } else { + ff = append(ff, e) + } + } + return ve +} -- 2.51.0