aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/regalloc.go
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2021-03-17 19:15:38 -0400
committerCherry Zhang <cherryyz@google.com>2021-03-19 23:21:21 +0000
commit6ae3b70ef255cd7317764a12b7230f293683f2c5 (patch)
treeba2d6362e17980c0123f9e1b37c3c3a54e4d4214 /src/cmd/compile/internal/ssa/regalloc.go
parent9f2a71b6e7b418182dd0467e7d054ccf8130c026 (diff)
downloadgo-6ae3b70ef255cd7317764a12b7230f293683f2c5.tar.gz
go-6ae3b70ef255cd7317764a12b7230f293683f2c5.zip
cmd/compile: add clobberdeadreg mode
When -clobberdeadreg flag is set, the compiler inserts code that clobbers integer registers at call sites. This may be helpful for debugging register ABI. Only implemented on AMD64 for now. Change-Id: Ia203d3f891c30fd95d0103489056fe01d63a2899 Reviewed-on: https://go-review.googlesource.com/c/go/+/302809 Trust: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc.go')
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 42df8387e4..1baff184b0 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -114,6 +114,7 @@
package ssa
import (
+ "cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/objabi"
@@ -301,6 +302,9 @@ type regAllocState struct {
// blockOrder[b.ID] corresponds to the index of block b in visitOrder.
blockOrder []int32
+
+ // whether to insert instructions that clobber dead registers at call sites
+ doClobber bool
}
type endReg struct {
@@ -339,6 +343,17 @@ func (s *regAllocState) freeRegs(m regMask) {
}
}
+// clobberRegs inserts instructions that clobber registers listed in m.
+func (s *regAllocState) clobberRegs(m regMask) {
+ m &= s.allocatable & s.f.Config.gpRegMask // only integer register can contain pointers, only clobber them
+ for m != 0 {
+ r := pickReg(m)
+ m &^= 1 << r
+ x := s.curBlock.NewValue0(src.NoXPos, OpClobberReg, types.TypeVoid)
+ s.f.setHome(x, &s.registers[r])
+ }
+}
+
// setOrig records that c's original value is the same as
// v's original value.
func (s *regAllocState) setOrig(c *Value, v *Value) {
@@ -700,6 +715,14 @@ func (s *regAllocState) init(f *Func) {
}
}
}
+
+ // The clobberdeadreg experiment inserts code to clobber dead registers
+ // at call sites.
+ // Ignore huge functions to avoid doing too much work.
+ if base.Flag.ClobberDeadReg && len(s.f.Blocks) <= 10000 {
+ // TODO: honor GOCLOBBERDEADHASH, or maybe GOSSAHASH.
+ s.doClobber = true
+ }
}
// Adds a use record for id at distance dist from the start of the block.
@@ -1314,6 +1337,9 @@ func (s *regAllocState) regalloc(f *Func) {
}
if len(regspec.inputs) == 0 && len(regspec.outputs) == 0 {
// No register allocation required (or none specified yet)
+ if s.doClobber && v.Op.IsCall() {
+ s.clobberRegs(regspec.clobbers)
+ }
s.freeRegs(regspec.clobbers)
b.Values = append(b.Values, v)
s.advanceUses(v)
@@ -1475,6 +1501,11 @@ func (s *regAllocState) regalloc(f *Func) {
}
// Dump any registers which will be clobbered
+ if s.doClobber && v.Op.IsCall() {
+ // clobber registers that are marked as clobber in regmask, but
+ // don't clobber inputs.
+ s.clobberRegs(regspec.clobbers &^ s.tmpused &^ s.nospill)
+ }
s.freeRegs(regspec.clobbers)
s.tmpused |= regspec.clobbers