From 72dc9ab1919e9fac9f3e63a109232cd79a050255 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 6 Oct 2019 23:03:28 -0700 Subject: [PATCH] cmd/compile: reuse dead register before reusing register holding constant For commuting ops, check whether the second argument is dead before checking if the first argument is rematerializeable. Reusing the register holding a dead value is always best. Fixes #33580 Change-Id: I7372cfc03d514e6774d2d9cc727a3e6bf6ce2657 Reviewed-on: https://go-review.googlesource.com/c/go/+/199559 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/regalloc.go | 24 +++++++++++------------ test/codegen/issue33580.go | 25 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 test/codegen/issue33580.go diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 6ffa1e3848..3f326722ae 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -1328,27 +1328,25 @@ func (s *regAllocState) regalloc(f *Func) { // arg0 is dead. We can clobber its register. goto ok } + if opcodeTable[v.Op].commutative && !s.liveAfterCurrentInstruction(v.Args[1]) { + args[0], args[1] = args[1], args[0] + goto ok + } if s.values[v.Args[0].ID].rematerializeable { // We can rematerialize the input, don't worry about clobbering it. goto ok } + if opcodeTable[v.Op].commutative && s.values[v.Args[1].ID].rematerializeable { + args[0], args[1] = args[1], args[0] + goto ok + } if countRegs(s.values[v.Args[0].ID].regs) >= 2 { // we have at least 2 copies of arg0. We can afford to clobber one. goto ok } - if opcodeTable[v.Op].commutative { - if !s.liveAfterCurrentInstruction(v.Args[1]) { - args[0], args[1] = args[1], args[0] - goto ok - } - if s.values[v.Args[1].ID].rematerializeable { - args[0], args[1] = args[1], args[0] - goto ok - } - if countRegs(s.values[v.Args[1].ID].regs) >= 2 { - args[0], args[1] = args[1], args[0] - goto ok - } + if opcodeTable[v.Op].commutative && countRegs(s.values[v.Args[1].ID].regs) >= 2 { + args[0], args[1] = args[1], args[0] + goto ok } // We can't overwrite arg0 (or arg1, if commutative). So we diff --git a/test/codegen/issue33580.go b/test/codegen/issue33580.go new file mode 100644 index 0000000000..1ded944c33 --- /dev/null +++ b/test/codegen/issue33580.go @@ -0,0 +1,25 @@ +// asmcheck + +// Copyright 2019 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. + +// Make sure we reuse large constant loads, if we can. +// See issue 33580. + +package codegen + +const ( + A = 7777777777777777 + B = 8888888888888888 +) + +func f(x, y uint64) uint64 { + p := x & A + q := y & A + r := x & B + // amd64:-"MOVQ.*8888888888888888" + s := y & B + + return p * q * r * s +}