Skip to content

Commit 89a0af8

Browse files
randall77gopherbot
authored andcommitted
cmd/compile: allow ops to specify clobbering input registers
Same as clobbering fixed registers, but which register is clobbered depends on which register was assigned to the input. Add code similar to resultInArg0 processing that makes a register copy before allowing the op to clobber the last available copy of a value. (Will be used by subsequent CLs in this stack.) Change-Id: I6bad88b2cb9ac3303d960ff0fb1611727292cfc4 Reviewed-on: https://go-review.googlesource.com/c/go/+/680335 Auto-Submit: Keith Randall <[email protected]> Reviewed-by: Keith Randall <[email protected]> Reviewed-by: Jorropo <[email protected]> Reviewed-by: Mark Freeman <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 5e94d72 commit 89a0af8

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

src/cmd/compile/internal/ssa/_gen/main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ type regInfo struct {
8787
// clobbers encodes the set of registers that are overwritten by
8888
// the instruction (other than the output registers).
8989
clobbers regMask
90+
// Instruction clobbers the register containing input 0.
91+
clobbersArg0 bool
92+
// Instruction clobbers the register containing input 1.
93+
clobbersArg1 bool
9094
// outputs[i] encodes the set of registers allowed for the i'th output.
9195
outputs []regMask
9296
}
@@ -293,7 +297,7 @@ func genOp() {
293297
fmt.Fprintf(w, "argLen: %d,\n", v.argLength)
294298

295299
if v.rematerializeable {
296-
if v.reg.clobbers != 0 {
300+
if v.reg.clobbers != 0 || v.reg.clobbersArg0 || v.reg.clobbersArg1 {
297301
log.Fatalf("%s is rematerializeable and clobbers registers", v.name)
298302
}
299303
if v.clobberFlags {
@@ -402,6 +406,12 @@ func genOp() {
402406
if v.reg.clobbers > 0 {
403407
fmt.Fprintf(w, "clobbers: %d,%s\n", v.reg.clobbers, a.regMaskComment(v.reg.clobbers))
404408
}
409+
if v.reg.clobbersArg0 {
410+
fmt.Fprintf(w, "clobbersArg0: true,\n")
411+
}
412+
if v.reg.clobbersArg1 {
413+
fmt.Fprintf(w, "clobbersArg1: true,\n")
414+
}
405415

406416
// reg outputs
407417
s = s[:0]

src/cmd/compile/internal/ssa/op.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ type regInfo struct {
7070
// clobbers encodes the set of registers that are overwritten by
7171
// the instruction (other than the output registers).
7272
clobbers regMask
73+
// Instruction clobbers the register containing input 0.
74+
clobbersArg0 bool
75+
// Instruction clobbers the register containing input 1.
76+
clobbersArg1 bool
7377
// outputs is the same as inputs, but for the outputs of the instruction.
7478
outputs []outputInfo
7579
}

src/cmd/compile/internal/ssa/regalloc.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1686,8 +1686,38 @@ func (s *regAllocState) regalloc(f *Func) {
16861686
}
16871687
}
16881688
}
1689-
16901689
ok:
1690+
for i := 0; i < 2; i++ {
1691+
if !(i == 0 && regspec.clobbersArg0 || i == 1 && regspec.clobbersArg1) {
1692+
continue
1693+
}
1694+
if !s.liveAfterCurrentInstruction(v.Args[i]) {
1695+
// arg is dead. We can clobber its register.
1696+
continue
1697+
}
1698+
if s.values[v.Args[i].ID].rematerializeable {
1699+
// We can rematerialize the input, don't worry about clobbering it.
1700+
continue
1701+
}
1702+
if countRegs(s.values[v.Args[i].ID].regs) >= 2 {
1703+
// We have at least 2 copies of arg. We can afford to clobber one.
1704+
continue
1705+
}
1706+
// Possible new registers to copy into.
1707+
m := s.compatRegs(v.Args[i].Type) &^ s.used
1708+
if m == 0 {
1709+
// No free registers. In this case we'll just clobber the
1710+
// input and future uses of that input must use a restore.
1711+
// TODO(khr): We should really do this like allocReg does it,
1712+
// spilling the value with the most distant next use.
1713+
continue
1714+
}
1715+
// Copy input to a new clobberable register.
1716+
c := s.allocValToReg(v.Args[i], m, true, v.Pos)
1717+
s.copies[c] = false
1718+
args[i] = c
1719+
}
1720+
16911721
// Pick a temporary register if needed.
16921722
// It should be distinct from all the input registers, so we
16931723
// allocate it after all the input registers, but before
@@ -1709,6 +1739,13 @@ func (s *regAllocState) regalloc(f *Func) {
17091739
s.tmpused |= regMask(1) << tmpReg
17101740
}
17111741

1742+
if regspec.clobbersArg0 {
1743+
s.freeReg(register(s.f.getHome(args[0].ID).(*Register).num))
1744+
}
1745+
if regspec.clobbersArg1 {
1746+
s.freeReg(register(s.f.getHome(args[1].ID).(*Register).num))
1747+
}
1748+
17121749
// Now that all args are in regs, we're ready to issue the value itself.
17131750
// Before we pick a register for the output value, allow input registers
17141751
// to be deallocated. We do this here so that the output can use the

0 commit comments

Comments
 (0)