Commit 46ba5902 authored by Cherry Zhang's avatar Cherry Zhang

cmd/compile: label LoadReg with line number of the use

A tentative fix of #16380. It adds "line" everywhere...

This also reduces binary size slightly (cmd/go on ARM as an example):

			before		after
total binary size	8068097		8018945 (-0.6%)
.gopclntab		1195341		1179929 (-1.3%)
.debug_line		 689692		 652017 (-5.5%)

Change-Id: Ibda657c6999783c5bac180cbbba487006dbf0ed7
Reviewed-on: https://go-review.googlesource.com/25082Reviewed-by: 's avatarDavid Chase <drchase@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 882dd1c3
...@@ -111,7 +111,7 @@ func dse(f *Func) { ...@@ -111,7 +111,7 @@ func dse(f *Func) {
if sz > 0x7fffffff { // work around sparseMap's int32 value type if sz > 0x7fffffff { // work around sparseMap's int32 value type
sz = 0x7fffffff sz = 0x7fffffff
} }
shadowed.set(v.Args[0].ID, int32(sz)) shadowed.set(v.Args[0].ID, int32(sz), 0)
} }
} }
// walk to previous store // walk to previous store
......
...@@ -180,6 +180,7 @@ func pickReg(r regMask) register { ...@@ -180,6 +180,7 @@ func pickReg(r regMask) register {
type use struct { type use struct {
dist int32 // distance from start of the block to a use of a value dist int32 // distance from start of the block to a use of a value
line int32 // line number of the use
next *use // linked list of uses of a value in nondecreasing dist order next *use // linked list of uses of a value in nondecreasing dist order
} }
...@@ -277,8 +278,9 @@ type endReg struct { ...@@ -277,8 +278,9 @@ type endReg struct {
} }
type startReg struct { type startReg struct {
r register r register
vid ID // pre-regalloc value needed in this register vid ID // pre-regalloc value needed in this register
line int32 // line number of use of this register
} }
// freeReg frees up register r. Any current user of r is kicked out. // freeReg frees up register r. Any current user of r is kicked out.
...@@ -567,7 +569,7 @@ func (s *regAllocState) init(f *Func) { ...@@ -567,7 +569,7 @@ func (s *regAllocState) init(f *Func) {
// Adds a use record for id at distance dist from the start of the block. // Adds a use record for id at distance dist from the start of the block.
// All calls to addUse must happen with nonincreasing dist. // All calls to addUse must happen with nonincreasing dist.
func (s *regAllocState) addUse(id ID, dist int32) { func (s *regAllocState) addUse(id ID, dist int32, line int32) {
r := s.freeUseRecords r := s.freeUseRecords
if r != nil { if r != nil {
s.freeUseRecords = r.next s.freeUseRecords = r.next
...@@ -575,6 +577,7 @@ func (s *regAllocState) addUse(id ID, dist int32) { ...@@ -575,6 +577,7 @@ func (s *regAllocState) addUse(id ID, dist int32) {
r = &use{} r = &use{}
} }
r.dist = dist r.dist = dist
r.line = line
r.next = s.values[id].uses r.next = s.values[id].uses
s.values[id].uses = r s.values[id].uses = r
if r.next != nil && dist > r.next.dist { if r.next != nil && dist > r.next.dist {
...@@ -701,11 +704,11 @@ func (s *regAllocState) regalloc(f *Func) { ...@@ -701,11 +704,11 @@ func (s *regAllocState) regalloc(f *Func) {
// Walk backwards through the block doing liveness analysis. // Walk backwards through the block doing liveness analysis.
liveSet.clear() liveSet.clear()
for _, e := range s.live[b.ID] { for _, e := range s.live[b.ID] {
s.addUse(e.ID, int32(len(b.Values))+e.dist) // pseudo-uses from beyond end of block s.addUse(e.ID, int32(len(b.Values))+e.dist, e.line) // pseudo-uses from beyond end of block
liveSet.add(e.ID) liveSet.add(e.ID)
} }
if v := b.Control; v != nil && s.values[v.ID].needReg { if v := b.Control; v != nil && s.values[v.ID].needReg {
s.addUse(v.ID, int32(len(b.Values))) // psuedo-use by control value s.addUse(v.ID, int32(len(b.Values)), b.Line) // psuedo-use by control value
liveSet.add(v.ID) liveSet.add(v.ID)
} }
for i := len(b.Values) - 1; i >= 0; i-- { for i := len(b.Values) - 1; i >= 0; i-- {
...@@ -721,7 +724,7 @@ func (s *regAllocState) regalloc(f *Func) { ...@@ -721,7 +724,7 @@ func (s *regAllocState) regalloc(f *Func) {
if !s.values[a.ID].needReg { if !s.values[a.ID].needReg {
continue continue
} }
s.addUse(a.ID, int32(i)) s.addUse(a.ID, int32(i), v.Line)
liveSet.add(a.ID) liveSet.add(a.ID)
} }
} }
...@@ -893,7 +896,7 @@ func (s *regAllocState) regalloc(f *Func) { ...@@ -893,7 +896,7 @@ func (s *regAllocState) regalloc(f *Func) {
// specially during merge edge processing. // specially during merge edge processing.
continue continue
} }
regList = append(regList, startReg{r, v.ID}) regList = append(regList, startReg{r, v.ID, s.values[v.ID].uses.line})
} }
s.startRegs[b.ID] = regList s.startRegs[b.ID] = regList
...@@ -1747,12 +1750,14 @@ type contentRecord struct { ...@@ -1747,12 +1750,14 @@ type contentRecord struct {
vid ID // pre-regalloc value vid ID // pre-regalloc value
c *Value // cached value c *Value // cached value
final bool // this is a satisfied destination final bool // this is a satisfied destination
line int32 // line number of use of the value
} }
type dstRecord struct { type dstRecord struct {
loc Location // register or stack slot loc Location // register or stack slot
vid ID // pre-regalloc value it should contain vid ID // pre-regalloc value it should contain
splice **Value // place to store reference to the generating instruction splice **Value // place to store reference to the generating instruction
line int32 // line number of use of this location
} }
// setup initializes the edge state for shuffling. // setup initializes the edge state for shuffling.
...@@ -1775,19 +1780,19 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive ...@@ -1775,19 +1780,19 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
// Live registers can be sources. // Live registers can be sources.
for _, x := range srcReg { for _, x := range srcReg {
e.set(&e.s.registers[x.r], x.v.ID, x.c, false) e.set(&e.s.registers[x.r], x.v.ID, x.c, false, 0) // don't care the line number of the source
} }
// So can all of the spill locations. // So can all of the spill locations.
for _, spillID := range stacklive { for _, spillID := range stacklive {
v := e.s.orig[spillID] v := e.s.orig[spillID]
spill := e.s.values[v.ID].spill spill := e.s.values[v.ID].spill
e.set(e.s.f.getHome(spillID), v.ID, spill, false) e.set(e.s.f.getHome(spillID), v.ID, spill, false, 0) // don't care the line number of the source
} }
// Figure out all the destinations we need. // Figure out all the destinations we need.
dsts := e.destinations[:0] dsts := e.destinations[:0]
for _, x := range dstReg { for _, x := range dstReg {
dsts = append(dsts, dstRecord{&e.s.registers[x.r], x.vid, nil}) dsts = append(dsts, dstRecord{&e.s.registers[x.r], x.vid, nil, x.line})
} }
// Phis need their args to end up in a specific location. // Phis need their args to end up in a specific location.
for _, v := range e.b.Values { for _, v := range e.b.Values {
...@@ -1798,7 +1803,7 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive ...@@ -1798,7 +1803,7 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
if loc == nil { if loc == nil {
continue continue
} }
dsts = append(dsts, dstRecord{loc, v.Args[idx].ID, &v.Args[idx]}) dsts = append(dsts, dstRecord{loc, v.Args[idx].ID, &v.Args[idx], v.Line})
} }
e.destinations = dsts e.destinations = dsts
...@@ -1823,7 +1828,7 @@ func (e *edgeState) process() { ...@@ -1823,7 +1828,7 @@ func (e *edgeState) process() {
for len(dsts) > 0 { for len(dsts) > 0 {
i := 0 i := 0
for _, d := range dsts { for _, d := range dsts {
if !e.processDest(d.loc, d.vid, d.splice) { if !e.processDest(d.loc, d.vid, d.splice, d.line) {
// Failed - save for next iteration. // Failed - save for next iteration.
dsts[i] = d dsts[i] = d
i++ i++
...@@ -1861,7 +1866,8 @@ func (e *edgeState) process() { ...@@ -1861,7 +1866,8 @@ func (e *edgeState) process() {
// Copy any cycle location to a temp register. This duplicates // Copy any cycle location to a temp register. This duplicates
// one of the cycle entries, allowing the just duplicated value // one of the cycle entries, allowing the just duplicated value
// to be overwritten and the cycle to proceed. // to be overwritten and the cycle to proceed.
loc := dsts[0].loc d := dsts[0]
loc := d.loc
vid := e.contents[loc].vid vid := e.contents[loc].vid
c := e.contents[loc].c c := e.contents[loc].c
r := e.findRegFor(c.Type) r := e.findRegFor(c.Type)
...@@ -1869,22 +1875,22 @@ func (e *edgeState) process() { ...@@ -1869,22 +1875,22 @@ func (e *edgeState) process() {
fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc.Name(), c) fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc.Name(), c)
} }
if _, isReg := loc.(*Register); isReg { if _, isReg := loc.(*Register); isReg {
c = e.p.NewValue1(c.Line, OpCopy, c.Type, c) c = e.p.NewValue1(d.line, OpCopy, c.Type, c)
} else { } else {
e.s.lateSpillUse(vid) e.s.lateSpillUse(vid)
c = e.p.NewValue1(c.Line, OpLoadReg, c.Type, c) c = e.p.NewValue1(d.line, OpLoadReg, c.Type, c)
} }
e.set(r, vid, c, false) e.set(r, vid, c, false, d.line)
} }
} }
// processDest generates code to put value vid into location loc. Returns true // processDest generates code to put value vid into location loc. Returns true
// if progress was made. // if progress was made.
func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { func (e *edgeState) processDest(loc Location, vid ID, splice **Value, line int32) bool {
occupant := e.contents[loc] occupant := e.contents[loc]
if occupant.vid == vid { if occupant.vid == vid {
// Value is already in the correct place. // Value is already in the correct place.
e.contents[loc] = contentRecord{vid, occupant.c, true} e.contents[loc] = contentRecord{vid, occupant.c, true, line}
if splice != nil { if splice != nil {
(*splice).Uses-- (*splice).Uses--
*splice = occupant.c *splice = occupant.c
...@@ -1946,25 +1952,25 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { ...@@ -1946,25 +1952,25 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
e.erase(loc) // see pre-clobber comment below e.erase(loc) // see pre-clobber comment below
r := e.findRegFor(v.Type) r := e.findRegFor(v.Type)
x = v.copyInto(e.p) x = v.copyInto(e.p)
e.set(r, vid, x, false) e.set(r, vid, x, false, line)
// Make sure we spill with the size of the slot, not the // Make sure we spill with the size of the slot, not the
// size of x (which might be wider due to our dropping // size of x (which might be wider due to our dropping
// of narrowing conversions). // of narrowing conversions).
x = e.p.NewValue1(x.Line, OpStoreReg, loc.(LocalSlot).Type, x) x = e.p.NewValue1(line, OpStoreReg, loc.(LocalSlot).Type, x)
} }
} else { } else {
// Emit move from src to dst. // Emit move from src to dst.
_, srcReg := src.(*Register) _, srcReg := src.(*Register)
if srcReg { if srcReg {
if dstReg { if dstReg {
x = e.p.NewValue1(c.Line, OpCopy, c.Type, c) x = e.p.NewValue1(line, OpCopy, c.Type, c)
} else { } else {
x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, c) x = e.p.NewValue1(line, OpStoreReg, loc.(LocalSlot).Type, c)
} }
} else { } else {
if dstReg { if dstReg {
e.s.lateSpillUse(vid) e.s.lateSpillUse(vid)
x = e.p.NewValue1(c.Line, OpLoadReg, c.Type, c) x = e.p.NewValue1(line, OpLoadReg, c.Type, c)
} else { } else {
// mem->mem. Use temp register. // mem->mem. Use temp register.
...@@ -1982,13 +1988,13 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { ...@@ -1982,13 +1988,13 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
r := e.findRegFor(c.Type) r := e.findRegFor(c.Type)
e.s.lateSpillUse(vid) e.s.lateSpillUse(vid)
t := e.p.NewValue1(c.Line, OpLoadReg, c.Type, c) t := e.p.NewValue1(line, OpLoadReg, c.Type, c)
e.set(r, vid, t, false) e.set(r, vid, t, false, line)
x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, t) x = e.p.NewValue1(line, OpStoreReg, loc.(LocalSlot).Type, t)
} }
} }
} }
e.set(loc, vid, x, true) e.set(loc, vid, x, true, line)
if splice != nil { if splice != nil {
(*splice).Uses-- (*splice).Uses--
*splice = x *splice = x
...@@ -1998,10 +2004,10 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool { ...@@ -1998,10 +2004,10 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
} }
// set changes the contents of location loc to hold the given value and its cached representative. // 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) { func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, line int32) {
e.s.f.setHome(c, loc) e.s.f.setHome(c, loc)
e.erase(loc) e.erase(loc)
e.contents[loc] = contentRecord{vid, c, final} e.contents[loc] = contentRecord{vid, c, final, line}
a := e.cache[vid] a := e.cache[vid]
if len(a) == 0 { if len(a) == 0 {
e.cachedVals = append(e.cachedVals, vid) e.cachedVals = append(e.cachedVals, vid)
...@@ -2040,7 +2046,7 @@ func (e *edgeState) erase(loc Location) { ...@@ -2040,7 +2046,7 @@ func (e *edgeState) erase(loc Location) {
// Add a destination to move this value back into place. // Add a destination to move this value back into place.
// Make sure it gets added to the tail of the destination queue // Make sure it gets added to the tail of the destination queue
// so we make progress on other moves first. // so we make progress on other moves first.
e.extra = append(e.extra, dstRecord{loc, cr.vid, nil}) e.extra = append(e.extra, dstRecord{loc, cr.vid, nil, cr.line})
} }
// Remove c from the list of cached values. // Remove c from the list of cached values.
...@@ -2110,7 +2116,7 @@ func (e *edgeState) findRegFor(typ Type) Location { ...@@ -2110,7 +2116,7 @@ func (e *edgeState) findRegFor(typ Type) Location {
for _, c := range a { for _, c := range a {
if r, ok := e.s.f.getHome(c.ID).(*Register); ok && m>>uint(r.Num)&1 != 0 { if r, ok := e.s.f.getHome(c.ID).(*Register); ok && m>>uint(r.Num)&1 != 0 {
x := e.p.NewValue1(c.Line, OpStoreReg, c.Type, c) x := e.p.NewValue1(c.Line, OpStoreReg, c.Type, c)
e.set(t, vid, x, false) e.set(t, vid, x, false, c.Line)
if e.s.f.pass.debug > regDebug { if e.s.f.pass.debug > regDebug {
fmt.Printf(" SPILL %s->%s %s\n", r.Name(), t.Name(), x.LongString()) fmt.Printf(" SPILL %s->%s %s\n", r.Name(), t.Name(), x.LongString())
} }
...@@ -2151,6 +2157,7 @@ func (v *Value) rematerializeable() bool { ...@@ -2151,6 +2157,7 @@ func (v *Value) rematerializeable() bool {
type liveInfo struct { type liveInfo struct {
ID ID // ID of value ID ID // ID of value
dist int32 // # of instructions before next use dist int32 // # of instructions before next use
line int32 // line number of next use
} }
// dblock contains information about desired & avoid registers at the end of a block. // dblock contains information about desired & avoid registers at the end of a block.
...@@ -2199,12 +2206,12 @@ func (s *regAllocState) computeLive() { ...@@ -2199,12 +2206,12 @@ func (s *regAllocState) computeLive() {
// to beginning-of-block distance. // to beginning-of-block distance.
live.clear() live.clear()
for _, e := range s.live[b.ID] { for _, e := range s.live[b.ID] {
live.set(e.ID, e.dist+int32(len(b.Values))) live.set(e.ID, e.dist+int32(len(b.Values)), e.line)
} }
// Mark control value as live // Mark control value as live
if b.Control != nil && s.values[b.Control.ID].needReg { if b.Control != nil && s.values[b.Control.ID].needReg {
live.set(b.Control.ID, int32(len(b.Values))) live.set(b.Control.ID, int32(len(b.Values)), b.Line)
} }
// Propagate backwards to the start of the block // Propagate backwards to the start of the block
...@@ -2226,7 +2233,7 @@ func (s *regAllocState) computeLive() { ...@@ -2226,7 +2233,7 @@ func (s *regAllocState) computeLive() {
} }
for _, a := range v.Args { for _, a := range v.Args {
if s.values[a.ID].needReg { if s.values[a.ID].needReg {
live.set(a.ID, int32(i)) live.set(a.ID, int32(i), v.Line)
} }
} }
} }
...@@ -2285,7 +2292,7 @@ func (s *regAllocState) computeLive() { ...@@ -2285,7 +2292,7 @@ func (s *regAllocState) computeLive() {
// Start t off with the previously known live values at the end of p. // Start t off with the previously known live values at the end of p.
t.clear() t.clear()
for _, e := range s.live[p.ID] { for _, e := range s.live[p.ID] {
t.set(e.ID, e.dist) t.set(e.ID, e.dist, e.line)
} }
update := false update := false
...@@ -2294,7 +2301,7 @@ func (s *regAllocState) computeLive() { ...@@ -2294,7 +2301,7 @@ func (s *regAllocState) computeLive() {
d := e.val + delta d := e.val + delta
if !t.contains(e.key) || d < t.get(e.key) { if !t.contains(e.key) || d < t.get(e.key) {
update = true update = true
t.set(e.key, d) t.set(e.key, d, e.aux)
} }
} }
// Also add the correct arg from the saved phi values. // Also add the correct arg from the saved phi values.
...@@ -2304,7 +2311,7 @@ func (s *regAllocState) computeLive() { ...@@ -2304,7 +2311,7 @@ func (s *regAllocState) computeLive() {
id := v.Args[i].ID id := v.Args[i].ID
if s.values[id].needReg && (!t.contains(id) || delta < t.get(id)) { if s.values[id].needReg && (!t.contains(id) || delta < t.get(id)) {
update = true update = true
t.set(id, delta) t.set(id, delta, v.Line)
} }
} }
...@@ -2317,7 +2324,7 @@ func (s *regAllocState) computeLive() { ...@@ -2317,7 +2324,7 @@ func (s *regAllocState) computeLive() {
l = make([]liveInfo, 0, t.size()) l = make([]liveInfo, 0, t.size())
} }
for _, e := range t.contents() { for _, e := range t.contents() {
l = append(l, liveInfo{e.key, e.val}) l = append(l, liveInfo{e.key, e.val, e.aux})
} }
s.live[p.ID] = l s.live[p.ID] = l
changed = true changed = true
......
...@@ -10,6 +10,7 @@ package ssa ...@@ -10,6 +10,7 @@ package ssa
type sparseEntry struct { type sparseEntry struct {
key ID key ID
val int32 val int32
aux int32
} }
type sparseMap struct { type sparseMap struct {
...@@ -42,13 +43,14 @@ func (s *sparseMap) get(k ID) int32 { ...@@ -42,13 +43,14 @@ func (s *sparseMap) get(k ID) int32 {
return -1 return -1
} }
func (s *sparseMap) set(k ID, v int32) { func (s *sparseMap) set(k ID, v, a int32) {
i := s.sparse[k] i := s.sparse[k]
if i < int32(len(s.dense)) && s.dense[i].key == k { if i < int32(len(s.dense)) && s.dense[i].key == k {
s.dense[i].val = v s.dense[i].val = v
s.dense[i].aux = a
return return
} }
s.dense = append(s.dense, sparseEntry{k, v}) s.dense = append(s.dense, sparseEntry{k, v, a})
s.sparse[k] = int32(len(s.dense)) - 1 s.sparse[k] = int32(len(s.dense)) - 1
} }
...@@ -62,7 +64,7 @@ func (s *sparseMap) setBit(k ID, v uint) { ...@@ -62,7 +64,7 @@ func (s *sparseMap) setBit(k ID, v uint) {
s.dense[i].val |= 1 << v s.dense[i].val |= 1 << v
return return
} }
s.dense = append(s.dense, sparseEntry{k, 1 << v}) s.dense = append(s.dense, sparseEntry{k, 1 << v, 0})
s.sparse[k] = int32(len(s.dense)) - 1 s.sparse[k] = int32(len(s.dense)) - 1
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment