]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: label LoadReg with line number of the use
authorCherry Zhang <cherryyz@google.com>
Wed, 20 Jul 2016 14:09:40 +0000 (10:09 -0400)
committerCherry Zhang <cherryyz@google.com>
Fri, 16 Sep 2016 15:38:28 +0000 (15:38 +0000)
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/25082
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/deadstore.go
src/cmd/compile/internal/ssa/regalloc.go
src/cmd/compile/internal/ssa/sparsemap.go

index 3386a227ed6b01f1cb460392cb4fd467a45bf54e..89ab17a4271e0d595141274a892172ee1da9544f 100644 (file)
@@ -111,7 +111,7 @@ func dse(f *Func) {
                                if sz > 0x7fffffff { // work around sparseMap's int32 value type
                                        sz = 0x7fffffff
                                }
-                               shadowed.set(v.Args[0].ID, int32(sz))
+                               shadowed.set(v.Args[0].ID, int32(sz), 0)
                        }
                }
                // walk to previous store
index f6a118bf2291be6bb9c25a8b78b861be7f35ebd3..ba4ffedc50c16ff33e58773f7e33867ad12b28fe 100644 (file)
@@ -180,6 +180,7 @@ func pickReg(r regMask) register {
 
 type use struct {
        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
 }
 
@@ -277,8 +278,9 @@ type endReg struct {
 }
 
 type startReg struct {
-       r   register
-       vid ID // pre-regalloc value needed in this register
+       r    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.
@@ -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.
 // 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
        if r != nil {
                s.freeUseRecords = r.next
@@ -575,6 +577,7 @@ func (s *regAllocState) addUse(id ID, dist int32) {
                r = &use{}
        }
        r.dist = dist
+       r.line = line
        r.next = s.values[id].uses
        s.values[id].uses = r
        if r.next != nil && dist > r.next.dist {
@@ -701,11 +704,11 @@ func (s *regAllocState) regalloc(f *Func) {
                // Walk backwards through the block doing liveness analysis.
                liveSet.clear()
                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)
                }
                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)
                }
                for i := len(b.Values) - 1; i >= 0; i-- {
@@ -721,7 +724,7 @@ func (s *regAllocState) regalloc(f *Func) {
                                if !s.values[a.ID].needReg {
                                        continue
                                }
-                               s.addUse(a.ID, int32(i))
+                               s.addUse(a.ID, int32(i), v.Line)
                                liveSet.add(a.ID)
                        }
                }
@@ -893,7 +896,7 @@ func (s *regAllocState) regalloc(f *Func) {
                                        // specially during merge edge processing.
                                        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
 
@@ -1747,12 +1750,14 @@ type contentRecord struct {
        vid   ID     // pre-regalloc value
        c     *Value // cached value
        final bool   // this is a satisfied destination
+       line  int32  // line number 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
+       line   int32    // line number of use of this location
 }
 
 // setup initializes the edge state for shuffling.
@@ -1775,19 +1780,19 @@ 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)
+               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.
        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)
+               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.
        dsts := e.destinations[:0]
        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.
        for _, v := range e.b.Values {
@@ -1798,7 +1803,7 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
                if loc == nil {
                        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
 
@@ -1823,7 +1828,7 @@ func (e *edgeState) process() {
        for len(dsts) > 0 {
                i := 0
                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.
                                dsts[i] = d
                                i++
@@ -1861,7 +1866,8 @@ func (e *edgeState) process() {
                // Copy any cycle location to a temp register. This duplicates
                // one of the cycle entries, allowing the just duplicated value
                // to be overwritten and the cycle to proceed.
-               loc := dsts[0].loc
+               d := dsts[0]
+               loc := d.loc
                vid := e.contents[loc].vid
                c := e.contents[loc].c
                r := e.findRegFor(c.Type)
@@ -1869,22 +1875,22 @@ func (e *edgeState) process() {
                        fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc.Name(), c)
                }
                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 {
                        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
 // 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]
        if occupant.vid == vid {
                // 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 {
                        (*splice).Uses--
                        *splice = occupant.c
@@ -1946,25 +1952,25 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
                        e.erase(loc) // see pre-clobber comment below
                        r := e.findRegFor(v.Type)
                        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
                        // size of x (which might be wider due to our dropping
                        // 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 {
                // Emit move from src to dst.
                _, srcReg := src.(*Register)
                if srcReg {
                        if dstReg {
-                               x = e.p.NewValue1(c.Line, OpCopy, c.Type, c)
+                               x = e.p.NewValue1(line, OpCopy, c.Type, c)
                        } else {
-                               x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, c)
+                               x = e.p.NewValue1(line, OpStoreReg, loc.(LocalSlot).Type, c)
                        }
                } else {
                        if dstReg {
                                e.s.lateSpillUse(vid)
-                               x = e.p.NewValue1(c.Line, OpLoadReg, c.Type, c)
+                               x = e.p.NewValue1(line, OpLoadReg, c.Type, c)
                        } else {
                                // mem->mem. Use temp register.
 
@@ -1982,13 +1988,13 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
 
                                r := e.findRegFor(c.Type)
                                e.s.lateSpillUse(vid)
-                               t := e.p.NewValue1(c.Line, OpLoadReg, c.Type, c)
-                               e.set(r, vid, t, false)
-                               x = e.p.NewValue1(c.Line, OpStoreReg, loc.(LocalSlot).Type, t)
+                               t := e.p.NewValue1(line, OpLoadReg, c.Type, c)
+                               e.set(r, vid, t, false, line)
+                               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 {
                (*splice).Uses--
                *splice = x
@@ -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.
-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.erase(loc)
-       e.contents[loc] = contentRecord{vid, c, final}
+       e.contents[loc] = contentRecord{vid, c, final, line}
        a := e.cache[vid]
        if len(a) == 0 {
                e.cachedVals = append(e.cachedVals, vid)
@@ -2040,7 +2046,7 @@ func (e *edgeState) erase(loc Location) {
                // Add a destination to move this value back into place.
                // Make sure it gets added to the tail of the destination queue
                // 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.
@@ -2110,7 +2116,7 @@ func (e *edgeState) findRegFor(typ Type) Location {
                for _, c := range a {
                        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)
-                               e.set(t, vid, x, false)
+                               e.set(t, vid, x, false, c.Line)
                                if e.s.f.pass.debug > regDebug {
                                        fmt.Printf("  SPILL %s->%s %s\n", r.Name(), t.Name(), x.LongString())
                                }
@@ -2151,6 +2157,7 @@ func (v *Value) rematerializeable() bool {
 type liveInfo struct {
        ID   ID    // ID of value
        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.
@@ -2199,12 +2206,12 @@ func (s *regAllocState) computeLive() {
                        // to beginning-of-block distance.
                        live.clear()
                        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
                        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
@@ -2226,7 +2233,7 @@ func (s *regAllocState) computeLive() {
                                }
                                for _, a := range v.Args {
                                        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() {
                                // Start t off with the previously known live values at the end of p.
                                t.clear()
                                for _, e := range s.live[p.ID] {
-                                       t.set(e.ID, e.dist)
+                                       t.set(e.ID, e.dist, e.line)
                                }
                                update := false
 
@@ -2294,7 +2301,7 @@ func (s *regAllocState) computeLive() {
                                        d := e.val + delta
                                        if !t.contains(e.key) || d < t.get(e.key) {
                                                update = true
-                                               t.set(e.key, d)
+                                               t.set(e.key, d, e.aux)
                                        }
                                }
                                // Also add the correct arg from the saved phi values.
@@ -2304,7 +2311,7 @@ func (s *regAllocState) computeLive() {
                                        id := v.Args[i].ID
                                        if s.values[id].needReg && (!t.contains(id) || delta < t.get(id)) {
                                                update = true
-                                               t.set(id, delta)
+                                               t.set(id, delta, v.Line)
                                        }
                                }
 
@@ -2317,7 +2324,7 @@ func (s *regAllocState) computeLive() {
                                        l = make([]liveInfo, 0, t.size())
                                }
                                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
                                changed = true
index afb9f6049186cc7368d24054bdd3aafb32d92457..70c4f6190cb53cd993303a6111bcc99b924053b1 100644 (file)
@@ -10,6 +10,7 @@ package ssa
 type sparseEntry struct {
        key ID
        val int32
+       aux int32
 }
 
 type sparseMap struct {
@@ -42,13 +43,14 @@ func (s *sparseMap) get(k ID) int32 {
        return -1
 }
 
-func (s *sparseMap) set(k ID, v int32) {
+func (s *sparseMap) set(k ID, v, a int32) {
        i := s.sparse[k]
        if i < int32(len(s.dense)) && s.dense[i].key == k {
                s.dense[i].val = v
+               s.dense[i].aux = a
                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
 }
 
@@ -62,7 +64,7 @@ func (s *sparseMap) setBit(k ID, v uint) {
                s.dense[i].val |= 1 << v
                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
 }