From: Cherry Zhang Date: Tue, 30 Mar 2021 20:28:48 +0000 (-0400) Subject: cmd/compile: avoid generating duplicated in-register Arg X-Git-Tag: go1.17beta1~917 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=64ca7e2cb3;p=gostls13.git 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 Reviewed-by: Than McIntosh Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 60eed37f1c..3444097ae3 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -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 } diff --git a/test/abi/store_reg_args.go b/test/abi/store_reg_args.go new file mode 100644 index 0000000000..df5e4e167c --- /dev/null +++ b/test/abi/store_reg_args.go @@ -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") + } +}