]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: avoid generating duplicated in-register Arg
authorCherry Zhang <cherryyz@google.com>
Tue, 30 Mar 2021 20:28:48 +0000 (16:28 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 30 Mar 2021 22:10:19 +0000 (22:10 +0000)
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>
src/cmd/compile/internal/ssa/expand_calls.go
test/abi/store_reg_args.go [new file with mode: 0644]

index 60eed37f1c64c15722258999216866e5733e373b..3444097ae3e6800cadfa1f057ed8efd500e06661 100644 (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
 }
 
diff --git a/test/abi/store_reg_args.go b/test/abi/store_reg_args.go
new file mode 100644 (file)
index 0000000..df5e4e1
--- /dev/null
@@ -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")
+       }
+}