Skip to content

Commit 8c24bff

Browse files
committed
cmd/compile: layout stack frame during SSA
Identify live stack variables during SSA and compute the stack frame layout earlier so that we can emit instructions with the correct offsets upfront. Passes toolstash/buildall. Change-Id: I191100dba274f1e364a15bdcfdc1d1466cdd1db5 Reviewed-on: https://go-review.googlesource.com/30216 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent f239196 commit 8c24bff

File tree

17 files changed

+157
-316
lines changed

17 files changed

+157
-316
lines changed

src/cmd/compile/internal/amd64/ssa.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -669,17 +669,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
669669
return
670670
}
671671
p := gc.Prog(loadByType(v.Type))
672-
n, off := gc.AutoVar(v.Args[0])
673-
p.From.Type = obj.TYPE_MEM
674-
p.From.Node = n
675-
p.From.Sym = gc.Linksym(n.Sym)
676-
p.From.Offset = off
677-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
678-
p.From.Name = obj.NAME_PARAM
679-
p.From.Offset += n.Xoffset
680-
} else {
681-
p.From.Name = obj.NAME_AUTO
682-
}
672+
gc.AddrAuto(&p.From, v.Args[0])
683673
p.To.Type = obj.TYPE_REG
684674
p.To.Reg = v.Reg()
685675

@@ -691,17 +681,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
691681
p := gc.Prog(storeByType(v.Type))
692682
p.From.Type = obj.TYPE_REG
693683
p.From.Reg = v.Args[0].Reg()
694-
n, off := gc.AutoVar(v)
695-
p.To.Type = obj.TYPE_MEM
696-
p.To.Node = n
697-
p.To.Sym = gc.Linksym(n.Sym)
698-
p.To.Offset = off
699-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
700-
p.To.Name = obj.NAME_PARAM
701-
p.To.Offset += n.Xoffset
702-
} else {
703-
p.To.Name = obj.NAME_AUTO
704-
}
684+
gc.AddrAuto(&p.To, v)
705685
case ssa.OpPhi:
706686
gc.CheckLoweredPhi(v)
707687
case ssa.OpInitMem:

src/cmd/compile/internal/arm/ssa.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
162162
return
163163
}
164164
p := gc.Prog(loadByType(v.Type))
165-
n, off := gc.AutoVar(v.Args[0])
166-
p.From.Type = obj.TYPE_MEM
167-
p.From.Node = n
168-
p.From.Sym = gc.Linksym(n.Sym)
169-
p.From.Offset = off
170-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
171-
p.From.Name = obj.NAME_PARAM
172-
p.From.Offset += n.Xoffset
173-
} else {
174-
p.From.Name = obj.NAME_AUTO
175-
}
165+
gc.AddrAuto(&p.From, v.Args[0])
176166
p.To.Type = obj.TYPE_REG
177167
p.To.Reg = v.Reg()
178168
case ssa.OpPhi:
@@ -185,17 +175,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
185175
p := gc.Prog(storeByType(v.Type))
186176
p.From.Type = obj.TYPE_REG
187177
p.From.Reg = v.Args[0].Reg()
188-
n, off := gc.AutoVar(v)
189-
p.To.Type = obj.TYPE_MEM
190-
p.To.Node = n
191-
p.To.Sym = gc.Linksym(n.Sym)
192-
p.To.Offset = off
193-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
194-
p.To.Name = obj.NAME_PARAM
195-
p.To.Offset += n.Xoffset
196-
} else {
197-
p.To.Name = obj.NAME_AUTO
198-
}
178+
gc.AddrAuto(&p.To, v)
199179
case ssa.OpARMUDIVrtcall:
200180
p := gc.Prog(obj.ACALL)
201181
p.To.Type = obj.TYPE_MEM

src/cmd/compile/internal/arm64/ssa.go

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -136,17 +136,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
136136
return
137137
}
138138
p := gc.Prog(loadByType(v.Type))
139-
n, off := gc.AutoVar(v.Args[0])
140-
p.From.Type = obj.TYPE_MEM
141-
p.From.Node = n
142-
p.From.Sym = gc.Linksym(n.Sym)
143-
p.From.Offset = off
144-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
145-
p.From.Name = obj.NAME_PARAM
146-
p.From.Offset += n.Xoffset
147-
} else {
148-
p.From.Name = obj.NAME_AUTO
149-
}
139+
gc.AddrAuto(&p.From, v.Args[0])
150140
p.To.Type = obj.TYPE_REG
151141
p.To.Reg = v.Reg()
152142
case ssa.OpPhi:
@@ -159,17 +149,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
159149
p := gc.Prog(storeByType(v.Type))
160150
p.From.Type = obj.TYPE_REG
161151
p.From.Reg = v.Args[0].Reg()
162-
n, off := gc.AutoVar(v)
163-
p.To.Type = obj.TYPE_MEM
164-
p.To.Node = n
165-
p.To.Sym = gc.Linksym(n.Sym)
166-
p.To.Offset = off
167-
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
168-
p.To.Name = obj.NAME_PARAM
169-
p.To.Offset += n.Xoffset
170-
} else {
171-
p.To.Name = obj.NAME_AUTO
172-
}
152+
gc.AddrAuto(&p.To, v)
173153
case ssa.OpARM64ADD,
174154
ssa.OpARM64SUB,
175155
ssa.OpARM64AND,

src/cmd/compile/internal/gc/gsubr.go

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -75,40 +75,6 @@ func Appendpp(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16, foffset in
7575
return q
7676
}
7777

78-
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
79-
func fixautoused(p *obj.Prog) {
80-
for lp := &p; ; {
81-
p = *lp
82-
if p == nil {
83-
break
84-
}
85-
if p.As == obj.ATYPE && p.From.Node != nil && p.From.Name == obj.NAME_AUTO && !((p.From.Node).(*Node)).Used {
86-
*lp = p.Link
87-
continue
88-
}
89-
90-
if (p.As == obj.AVARDEF || p.As == obj.AVARKILL || p.As == obj.AVARLIVE) && p.To.Node != nil && !((p.To.Node).(*Node)).Used {
91-
// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
92-
// VARDEFs are interspersed with other code, and a jump might be using the
93-
// VARDEF as a target. Replace with a no-op instead. A later pass will remove
94-
// the no-ops.
95-
obj.Nopout(p)
96-
97-
continue
98-
}
99-
100-
if p.From.Name == obj.NAME_AUTO && p.From.Node != nil {
101-
p.From.Offset += p.From.Node.(*Node).Xoffset
102-
}
103-
104-
if p.To.Name == obj.NAME_AUTO && p.To.Node != nil {
105-
p.To.Offset += p.To.Node.(*Node).Xoffset
106-
}
107-
108-
lp = &p.Link
109-
}
110-
}
111-
11278
func ggloblnod(nam *Node) {
11379
s := Linksym(nam.Sym)
11480
s.Gotype = Linksym(ngotype(nam))
@@ -153,23 +119,6 @@ func isfat(t *Type) bool {
153119
return false
154120
}
155121

156-
// Sweep the prog list to mark any used nodes.
157-
func markautoused(p *obj.Prog) {
158-
for ; p != nil; p = p.Link {
159-
if p.As == obj.ATYPE || p.As == obj.AVARDEF || p.As == obj.AVARKILL {
160-
continue
161-
}
162-
163-
if p.From.Node != nil {
164-
((p.From.Node).(*Node)).Used = true
165-
}
166-
167-
if p.To.Node != nil {
168-
((p.To.Node).(*Node)).Used = true
169-
}
170-
}
171-
}
172-
173122
// Naddr rewrites a to refer to n.
174123
// It assumes that a is zeroed on entry.
175124
func Naddr(a *obj.Addr, n *Node) {

src/cmd/compile/internal/gc/pgen.go

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package gc
66

77
import (
8+
"cmd/compile/internal/ssa"
89
"cmd/internal/obj"
910
"cmd/internal/sys"
1011
"fmt"
@@ -93,6 +94,11 @@ func gvardefx(n *Node, as obj.As) {
9394

9495
switch n.Class {
9596
case PAUTO, PPARAM, PPARAMOUT:
97+
if !n.Used {
98+
Prog(obj.ANOP)
99+
return
100+
}
101+
96102
if as == obj.AVARLIVE {
97103
Gins(as, n, nil)
98104
} else {
@@ -214,53 +220,73 @@ func (s byStackVar) Len() int { return len(s) }
214220
func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) }
215221
func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
216222

217-
// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
218-
func allocauto(ptxt *obj.Prog) {
223+
var scratchFpMem *Node
224+
225+
func (s *ssaExport) AllocFrame(f *ssa.Func) {
219226
Stksize = 0
220227
stkptrsize = 0
221228

222-
if len(Curfn.Func.Dcl) == 0 {
223-
return
224-
}
225-
226229
// Mark the PAUTO's unused.
227230
for _, ln := range Curfn.Func.Dcl {
228231
if ln.Class == PAUTO {
229232
ln.Used = false
230233
}
231234
}
232235

233-
markautoused(ptxt)
236+
for _, l := range f.RegAlloc {
237+
if ls, ok := l.(ssa.LocalSlot); ok {
238+
ls.N.(*Node).Used = true
239+
}
234240

235-
sort.Sort(byStackVar(Curfn.Func.Dcl))
241+
}
236242

237-
// Unused autos are at the end, chop 'em off.
238-
n := Curfn.Func.Dcl[0]
239-
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
240-
// No locals used at all
241-
Curfn.Func.Dcl = nil
243+
scratchUsed := false
244+
for _, b := range f.Blocks {
245+
for _, v := range b.Values {
246+
switch a := v.Aux.(type) {
247+
case *ssa.ArgSymbol:
248+
a.Node.(*Node).Used = true
249+
case *ssa.AutoSymbol:
250+
a.Node.(*Node).Used = true
251+
}
242252

243-
fixautoused(ptxt)
244-
return
253+
// TODO(mdempsky): Encode in opcodeTable
254+
// whether an Op requires scratch memory.
255+
switch v.Op {
256+
case ssa.Op386UCOMISS, ssa.Op386UCOMISD,
257+
ssa.Op386ADDSS, ssa.Op386SUBSS, ssa.Op386MULSS, ssa.Op386DIVSS,
258+
ssa.Op386CVTSD2SS, ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD, ssa.Op386CVTTSD2SL, ssa.Op386CVTTSS2SL,
259+
ssa.OpPPC64Xf2i64, ssa.OpPPC64Xi2f64:
260+
scratchUsed = true
261+
}
262+
}
245263
}
246264

247-
for i := 1; i < len(Curfn.Func.Dcl); i++ {
248-
n = Curfn.Func.Dcl[i]
249-
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
250-
Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
251-
break
252-
}
265+
// To satisfy toolstash -cmp, preserve the unsorted
266+
// declaration order so we can emit the ATYPE instructions in
267+
// the same order.
268+
// TODO(mdempsky): Remove in followup CL.
269+
Curfn.Func.UnsortedDcls = append([]*Node(nil), Curfn.Func.Dcl...)
270+
271+
if f.Config.NeedsFpScratch {
272+
scratchFpMem = temp(Types[TUINT64])
273+
scratchFpMem.Used = scratchUsed
253274
}
254275

255-
// Reassign stack offsets of the locals that are still there.
256-
var w int64
257-
for _, n := range Curfn.Func.Dcl {
258-
if n.Class != PAUTO || n.Op != ONAME {
276+
sort.Sort(byStackVar(Curfn.Func.Dcl))
277+
278+
// Reassign stack offsets of the locals that are used.
279+
for i, n := range Curfn.Func.Dcl {
280+
if n.Op != ONAME || n.Class != PAUTO {
259281
continue
260282
}
283+
if !n.Used {
284+
Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
285+
break
286+
}
261287

262288
dowidth(n.Type)
263-
w = n.Type.Width
289+
w := n.Type.Width
264290
if w >= Thearch.MAXWIDTH || w < 0 {
265291
Fatalf("bad width")
266292
}
@@ -282,8 +308,6 @@ func allocauto(ptxt *obj.Prog) {
282308

283309
Stksize = Rnd(Stksize, int64(Widthreg))
284310
stkptrsize = Rnd(stkptrsize, int64(Widthreg))
285-
286-
fixautoused(ptxt)
287311
}
288312

289313
func compile(fn *Node) {
@@ -408,12 +432,22 @@ func compile(fn *Node) {
408432
}
409433
}
410434

411-
for _, n := range fn.Func.Dcl {
435+
for _, n := range fn.Func.UnsortedDcls {
412436
if n.Op != ONAME { // might be OTYPE or OLITERAL
413437
continue
414438
}
415439
switch n.Class {
416-
case PAUTO, PPARAM, PPARAMOUT:
440+
case PAUTO:
441+
if !n.Used {
442+
// Hacks to appease toolstash -cmp.
443+
// TODO(mdempsky): Remove in followup CL.
444+
pcloc++
445+
Pc.Pc++
446+
Linksym(ngotype(n))
447+
continue
448+
}
449+
fallthrough
450+
case PPARAM, PPARAMOUT:
417451
p := Gins(obj.ATYPE, n, nil)
418452
p.From.Gotype = Linksym(ngotype(n))
419453
}

src/cmd/compile/internal/gc/sizeof_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
2222
_32bit uintptr // size on 32bit platforms
2323
_64bit uintptr // size on 64bit platforms
2424
}{
25-
{Func{}, 96, 168},
25+
{Func{}, 108, 192}, // TODO(mdempsky): Change back to 96, 168 in followup CL.
2626
{Name{}, 52, 80},
2727
{Node{}, 92, 144},
2828
{Sym{}, 60, 112},

0 commit comments

Comments
 (0)