runtime: teach peephole optimizer that duffcopy clobbers X0

Duffcopy now uses X0, as of 5cf281a.  Teach the peephole
optimizer that duffcopy clobbers X0 so that it does not
rename registers use X0 across the duffcopy instruction.

Fixes #13171

Change-Id: I389cbf1982cb6eb2f51e6152ac96736a8589f085
Reviewed-on: https://go-review.googlesource.com/16715
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Ilya Tocar <ilya.tocar@intel.com>
This commit is contained in:
Keith Randall 2015-11-06 00:06:52 -08:00
parent 59bac0be90
commit ffb20631fc
4 changed files with 40 additions and 1 deletions

View file

@ -823,6 +823,10 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
return 2
}
if (p.Info.Reguse|p.Info.Regset)&FtoB(int(v.Reg)) != 0 {
return 2
}
if p.Info.Flags&gc.LeftAddr != 0 {
if copyas(&p.From, v) {
return 2

View file

@ -140,7 +140,7 @@ var progtable = [x86.ALAST]obj.ProgInfo{
x86.AMOVSL: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
x86.AMOVSQ: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
x86.AMOVSW: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
obj.ADUFFCOPY: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | CX},
obj.ADUFFCOPY: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | X0},
x86.AMOVSD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
x86.AMOVSS: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},

View file

@ -107,6 +107,7 @@ const (
DI = 1 << (x86.REG_DI - x86.REG_AX)
SI = 1 << (x86.REG_SI - x86.REG_AX)
R15 = 1 << (x86.REG_R15 - x86.REG_AX)
X0 = 1 << 16
)
func RtoB(r int) uint64 {

View file

@ -0,0 +1,34 @@
// run
// Copyright 2015 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.
package main
// Make sure the compiler knows that DUFFCOPY clobbers X0
import "fmt"
//go:noinline
func f(x float64) float64 {
// y is allocated to X0
y := x + 5
// marshals z before y. Marshalling z
// calls DUFFCOPY.
return g(z, y)
}
//go:noinline
func g(b [64]byte, y float64) float64 {
return y
}
var z [64]byte
func main() {
got := f(5)
if got != 10 {
panic(fmt.Sprintf("want 10, got %f", got))
}
}