mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
9f2a71b6e7
commit
6ae3b70ef2
17 changed files with 103 additions and 8 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue