mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.inline] cmd/internal/src: introduce compact source position representation
XPos is a compact (8 instead of 16 bytes on a 64bit machine) source position representation. There is a 1:1 correspondence between each XPos and each regular Pos, translated via a global table. In some sense this brings back the LineHist, though positions can track line and column information; there is a O(1) translation between the representations (no binary search), and the translation is factored out. The size increase with the prior change is brought down again and the compiler speed is in line with the master repo (measured on the same "quiet" machine as for prior change): name old time/op new time/op delta Template 256ms ± 1% 262ms ± 2% ~ (p=0.063 n=5+4) Unicode 132ms ± 1% 135ms ± 2% ~ (p=0.063 n=5+4) GoTypes 891ms ± 1% 871ms ± 1% -2.28% (p=0.016 n=5+4) Compiler 3.84s ± 2% 3.89s ± 2% ~ (p=0.413 n=5+4) MakeBash 47.1s ± 1% 46.2s ± 2% ~ (p=0.095 n=5+5) name old user-ns/op new user-ns/op delta Template 309M ± 1% 314M ± 2% ~ (p=0.111 n=5+4) Unicode 165M ± 1% 172M ± 9% ~ (p=0.151 n=5+5) GoTypes 1.14G ± 2% 1.12G ± 1% ~ (p=0.063 n=5+4) Compiler 5.00G ± 1% 4.96G ± 1% ~ (p=0.286 n=5+4) Change-Id: Icc570cc60ab014d8d9af6976f1f961ab8828cc47 Reviewed-on: https://go-review.googlesource.com/34506 Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
4808fc4443
commit
472c792e0a
42 changed files with 313 additions and 163 deletions
|
|
@ -181,9 +181,9 @@ func pickReg(r regMask) register {
|
|||
}
|
||||
|
||||
type use struct {
|
||||
dist int32 // distance from start of the block to a use of a value
|
||||
pos src.Pos // source position of the use
|
||||
next *use // linked list of uses of a value in nondecreasing dist order
|
||||
dist int32 // distance from start of the block to a use of a value
|
||||
pos src.XPos // source position of the use
|
||||
next *use // linked list of uses of a value in nondecreasing dist order
|
||||
}
|
||||
|
||||
type valState struct {
|
||||
|
|
@ -288,8 +288,8 @@ type endReg struct {
|
|||
|
||||
type startReg struct {
|
||||
r register
|
||||
vid ID // pre-regalloc value needed in this register
|
||||
pos src.Pos // source position of use of this register
|
||||
vid ID // pre-regalloc value needed in this register
|
||||
pos src.XPos // source position of use of this register
|
||||
}
|
||||
|
||||
// freeReg frees up register r. Any current user of r is kicked out.
|
||||
|
|
@ -411,7 +411,7 @@ func (s *regAllocState) allocReg(mask regMask, v *Value) register {
|
|||
// allocated register is marked nospill so the assignment cannot be
|
||||
// undone until the caller allows it by clearing nospill. Returns a
|
||||
// *Value which is either v or a copy of v allocated to the chosen register.
|
||||
func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.Pos) *Value {
|
||||
func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
|
||||
vi := &s.values[v.ID]
|
||||
|
||||
// Check if v is already in a requested register.
|
||||
|
|
@ -555,7 +555,7 @@ func (s *regAllocState) init(f *Func) {
|
|||
case "s390x":
|
||||
// nothing to do, R10 & R11 already reserved
|
||||
default:
|
||||
s.f.Config.fe.Fatalf(src.NoPos, "arch %s not implemented", s.f.Config.arch)
|
||||
s.f.Config.fe.Fatalf(src.NoXPos, "arch %s not implemented", s.f.Config.arch)
|
||||
}
|
||||
}
|
||||
if s.f.Config.nacl {
|
||||
|
|
@ -618,7 +618,7 @@ func (s *regAllocState) init(f *Func) {
|
|||
|
||||
// Adds a use record for id at distance dist from the start of the block.
|
||||
// All calls to addUse must happen with nonincreasing dist.
|
||||
func (s *regAllocState) addUse(id ID, dist int32, pos src.Pos) {
|
||||
func (s *regAllocState) addUse(id ID, dist int32, pos src.XPos) {
|
||||
r := s.freeUseRecords
|
||||
if r != nil {
|
||||
s.freeUseRecords = r.next
|
||||
|
|
@ -1879,17 +1879,17 @@ type edgeState struct {
|
|||
}
|
||||
|
||||
type contentRecord struct {
|
||||
vid ID // pre-regalloc value
|
||||
c *Value // cached value
|
||||
final bool // this is a satisfied destination
|
||||
pos src.Pos // source position of use of the value
|
||||
vid ID // pre-regalloc value
|
||||
c *Value // cached value
|
||||
final bool // this is a satisfied destination
|
||||
pos src.XPos // source position of use of the value
|
||||
}
|
||||
|
||||
type dstRecord struct {
|
||||
loc Location // register or stack slot
|
||||
vid ID // pre-regalloc value it should contain
|
||||
splice **Value // place to store reference to the generating instruction
|
||||
pos src.Pos // source position of use of this location
|
||||
pos src.XPos // source position of use of this location
|
||||
}
|
||||
|
||||
// setup initializes the edge state for shuffling.
|
||||
|
|
@ -1912,13 +1912,13 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
|
|||
|
||||
// Live registers can be sources.
|
||||
for _, x := range srcReg {
|
||||
e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.NoPos) // don't care the position of the source
|
||||
e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.NoXPos) // don't care the position of the source
|
||||
}
|
||||
// So can all of the spill locations.
|
||||
for _, spillID := range stacklive {
|
||||
v := e.s.orig[spillID]
|
||||
spill := e.s.values[v.ID].spill
|
||||
e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.NoPos) // don't care the position of the source
|
||||
e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.NoXPos) // don't care the position of the source
|
||||
}
|
||||
|
||||
// Figure out all the destinations we need.
|
||||
|
|
@ -2018,7 +2018,7 @@ func (e *edgeState) process() {
|
|||
|
||||
// processDest generates code to put value vid into location loc. Returns true
|
||||
// if progress was made.
|
||||
func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.Pos) bool {
|
||||
func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
|
||||
occupant := e.contents[loc]
|
||||
if occupant.vid == vid {
|
||||
// Value is already in the correct place.
|
||||
|
|
@ -2140,7 +2140,7 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.Po
|
|||
}
|
||||
|
||||
// set changes the contents of location loc to hold the given value and its cached representative.
|
||||
func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.Pos) {
|
||||
func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.XPos) {
|
||||
e.s.f.setHome(c, loc)
|
||||
e.erase(loc)
|
||||
e.contents[loc] = contentRecord{vid, c, final, pos}
|
||||
|
|
@ -2291,9 +2291,9 @@ func (v *Value) rematerializeable() bool {
|
|||
}
|
||||
|
||||
type liveInfo struct {
|
||||
ID ID // ID of value
|
||||
dist int32 // # of instructions before next use
|
||||
pos src.Pos // source position of next use
|
||||
ID ID // ID of value
|
||||
dist int32 // # of instructions before next use
|
||||
pos src.XPos // source position of next use
|
||||
}
|
||||
|
||||
// dblock contains information about desired & avoid registers at the end of a block.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue