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 <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Keith Randall 2025-08-18 10:17:27 -07:00 committed by Gopher Robot
parent c3927a47f0
commit 5a56d8848b
2 changed files with 76 additions and 2 deletions

View file

@ -1725,10 +1725,9 @@ func (s *regAllocState) regalloc(f *Func) {
// spilling the value with the most distant next use. // spilling the value with the most distant next use.
continue 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) c := s.allocValToReg(v.Args[i], m, true, v.Pos)
s.copies[c] = false s.copies[c] = false
args[i] = c
} }
// Pick a temporary register if needed. // Pick a temporary register if needed.

View file

@ -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
}