mirror of
https://github.com/golang/go
synced 2024-11-23 00:40:08 -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,
|
// rewriteArgToMemOrRegs converts OpArg v in-place into the register version of v,
|
||||||
// if that is appropriate.
|
// if that is appropriate.
|
||||||
func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value {
|
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)
|
pa := x.prAssignForArg(v)
|
||||||
switch len(pa.Registers) {
|
switch len(pa.Registers) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -1387,15 +1392,26 @@ func (x *expandState) rewriteArgToMemOrRegs(v *Value) *Value {
|
|||||||
pa.Offset(), frameOff, v.LongString()))
|
pa.Offset(), frameOff, v.LongString()))
|
||||||
}
|
}
|
||||||
case 1:
|
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]
|
r := pa.Registers[0]
|
||||||
var i int64
|
var i int64
|
||||||
v.Op, i = ArgOpAndRegisterFor(r, x.f.ABISelf)
|
v.Op, i = ArgOpAndRegisterFor(r, x.f.ABISelf)
|
||||||
v.Aux = &AuxNameOffset{v.Aux.(*ir.Name), 0}
|
v.Aux = &AuxNameOffset{v.Aux.(*ir.Name), 0}
|
||||||
v.AuxInt = i
|
v.AuxInt = i
|
||||||
|
x.commonArgs[key] = v
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic(badVal("Saw unexpanded OpArg", v))
|
panic(badVal("Saw unexpanded OpArg", v))
|
||||||
}
|
}
|
||||||
|
if x.debug {
|
||||||
|
x.Printf("-->%s\n", v.LongString())
|
||||||
|
}
|
||||||
return v
|
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