diff options
author | Cherry Zhang <cherryyz@google.com> | 2021-03-17 19:15:38 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2021-03-19 23:21:21 +0000 |
commit | 6ae3b70ef255cd7317764a12b7230f293683f2c5 (patch) | |
tree | ba2d6362e17980c0123f9e1b37c3c3a54e4d4214 /src/cmd/compile/internal/ssa/regalloc.go | |
parent | 9f2a71b6e7b418182dd0467e7d054ccf8130c026 (diff) | |
download | go-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.go | 31 |
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 |