mirror of
https://github.com/golang/go
synced 2024-11-22 20:50:05 -07:00
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:
parent
4b1a24f3cd
commit
64ca7e2cb3
@ -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
|
||||
}
|
||||
|
||||
|
29
test/abi/store_reg_args.go
Normal file
29
test/abi/store_reg_args.go
Normal 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")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user