cmd/compile: avoid generating duplicated in-register Arg

In expand_calls, when rewriting OpArg to OpArgIntReg/OpArgFloatReg,
avoid generating duplicates. Otherwise it will confuse the
register allocator: it would think the second occurance clobbers
the first's register, causing it to generate copies, which may
clobber other args.

Change-Id: I4f1dc0519afb77500eae1c0e6ac8745e51f7aa4e
Reviewed-on: https://go-review.googlesource.com/c/go/+/306029
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Cherry Zhang 2021-03-30 16:28:48 -04:00
parent 4b1a24f3cd
commit 64ca7e2cb3
2 changed files with 45 additions and 0 deletions

View File

@ -1378,6 +1378,11 @@ func expandCalls(f *Func) {
// rewriteArgToMemOrRegs converts OpArg v in-place into the register version of v,
// if that is appropriate.
func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value {
if x.debug {
x.indent(3)
defer x.indent(-3)
x.Printf("rewriteArgToMemOrRegs(%s)\n", v.LongString())
}
pa := x.prAssignForArg(v)
switch len(pa.Registers) {
case 0:
@ -1387,15 +1392,26 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value {
pa.Offset(), frameOff, v.LongString()))
}
case 1:
t := v.Type
key := selKey{v, 0, t.Width, t}
w := x.commonArgs[key]
if w != nil {
v.copyOf(w)
break
}
r := pa.Registers[0]
var i int64
v.Op, i = ArgOpAndRegisterFor(r, x.f.ABISelf)
v.Aux = &AuxNameOffset{v.Aux.(*ir.Name), 0}
v.AuxInt = i
x.commonArgs[key] = v
default:
panic(badVal("Saw unexpanded OpArg", v))
}
if x.debug {
x.Printf("-->%s\n", v.LongString())
}
return v
}

View File

@ -0,0 +1,29 @@
// run
// Copyright 2021 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.
// When the function Store an Arg and also use it in another place,
// be sure not to generate duplicated OpArgXXXReg values, which confuses
// the register allocator.
package main
//go:noinline
//go:registerparams
func F(x, y float32) {
if x < 0 {
panic("FAIL")
}
g = [4]float32{x, y, x, y}
}
var g [4]float32
func main() {
F(1, 2)
if g[0] != 1 || g[1] != 2 || g[2] != 1 || g[3] != 2 {
panic("FAIL")
}
}