Commit 369f4f5d authored by Keith Randall's avatar Keith Randall

cmd/compile: regalloc of two address instructions

x86 has a lot of instructions that require the output to be in the same
register as one of the inputs.  When allocating the output register,
allocate the same register as the input if it is available.

Improves the performance of golang.org/x/crypto/sha3 by
10% (from 6% slower than 1.6 to 4% faster).

Fixes #14745

Change-Id: I4d81785240c9368e4dc75107b45c959d200df8e6
Reviewed-on: https://go-review.googlesource.com/20488Reviewed-by: default avatarJosh Bleecher Snyder <josharian@gmail.com>
parent 157f0698
......@@ -34,6 +34,7 @@ type opData struct {
rematerializeable bool
argLength int32 // number of arguments, if -1, then this operation has a variable number of arguments
commutative bool // this operation is commutative (e.g. addition)
resultInArg0 bool // prefer v and v.Args[0] to be allocated to the same register
}
type blockData struct {
......@@ -141,6 +142,9 @@ func genOp() {
if v.commutative {
fmt.Fprintln(w, "commutative: true,")
}
if v.resultInArg0 {
fmt.Fprintln(w, "resultInArg0: true,")
}
if a.name == "generic" {
fmt.Fprintln(w, "generic:true,")
fmt.Fprintln(w, "},") // close op
......
......@@ -26,6 +26,7 @@ type opInfo struct {
generic bool // this is a generic (arch-independent) opcode
rematerializeable bool // this op is rematerializeable
commutative bool // this operation is commutative (e.g. addition)
resultInArg0 bool // prefer v and v.Args[0] to be allocated to the same register
}
type inputInfo struct {
......
This diff is collapsed.
......@@ -923,14 +923,26 @@ func (s *regAllocState) regalloc(f *Func) {
s.freeRegs(regspec.clobbers)
// Pick register for output.
var mask regMask
if s.values[v.ID].needReg {
mask = regspec.outputs[0] &^ s.reserved()
mask := regspec.outputs[0] &^ s.reserved()
if mask>>33&1 != 0 {
s.f.Fatalf("bad mask %s\n", v.LongString())
}
}
if mask != 0 {
if opcodeTable[v.Op].resultInArg0 {
r := register(s.f.getHome(args[0].ID).(*Register).Num)
if (mask&^s.used)>>r&1 != 0 {
mask = regMask(1) << r
}
if opcodeTable[v.Op].commutative {
r := register(s.f.getHome(args[1].ID).(*Register).Num)
if (mask&^s.used)>>r&1 != 0 {
mask = regMask(1) << r
}
}
// TODO: enforce resultInArg0 always, instead of treating it
// as a hint. Then we don't need the special cases adding
// moves all throughout ssa.go:genValue.
}
r := s.allocReg(v, mask)
s.assignReg(r, v, v)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment