Skip to content

Commit c4b8d33

Browse files
committed
cmd/compile: ignore dead blocks during SSA construction
For golang#15537 Compiling github.com/gogo/protobuf/test/combos/both Before: 69.83 real 82.72 user 2.01 sys 4206456832 maximum resident set size After: 62.94 real 74.74 user 1.92 sys 3832225792 maximum resident set size name old time/op new time/op delta Template 279ms ± 4% 277ms ± 4% ~ (p=0.529 n=20+20) Unicode 142ms ±10% 143ms ± 6% ~ (p=0.461 n=20+20) GoTypes 850ms ± 1% 846ms ± 2% ~ (p=0.175 n=19+20) Compiler 4.43s ± 2% 4.38s ± 1% -1.12% (p=0.000 n=19+20) name old user-ns/op new user-ns/op delta Template 376user-ms ± 4% 378user-ms ± 3% ~ (p=0.755 n=19+20) Unicode 203user-ms ± 3% 205user-ms ± 8% ~ (p=0.314 n=15+20) GoTypes 1.15user-s ± 2% 1.15user-s ± 3% ~ (p=0.799 n=20+20) Compiler 6.14user-s ± 3% 6.12user-s ± 2% ~ (p=0.547 n=20+20) name old alloc/op new alloc/op delta Template 47.6MB ± 0% 46.9MB ± 0% -1.41% (p=0.000 n=19+20) Unicode 37.1MB ± 0% 37.1MB ± 0% ~ (p=0.134 n=20+20) GoTypes 138MB ± 0% 136MB ± 0% -1.65% (p=0.000 n=20+20) Compiler 632MB ± 0% 614MB ± 0% -2.82% (p=0.000 n=20+20) name old allocs/op new allocs/op delta Template 445k ± 0% 444k ± 0% -0.17% (p=0.000 n=20+20) Unicode 356k ± 0% 356k ± 0% ~ (p=0.204 n=20+20) GoTypes 1.25M ± 0% 1.25M ± 0% -0.41% (p=0.000 n=20+19) Compiler 5.03M ± 0% 4.99M ± 0% -0.87% (p=0.000 n=19+20) Change-Id: Iee7b56ede4c319e4194160502f0796f478a9b73f
1 parent 149ac34 commit c4b8d33

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,11 @@ type state struct {
267267
// symbols for PEXTERN, PAUTO and PPARAMOUT variables so they can be reused.
268268
varsyms map[*Node]interface{}
269269

270-
// starting values. Memory, stack pointer, and globals pointer
270+
// starting values. Memory, stack pointer, globals pointer, reusable dead value
271271
startmem *ssa.Value
272272
sp *ssa.Value
273273
sb *ssa.Value
274+
dead *ssa.Value
274275

275276
// line number stack. The current line number is top of stack
276277
line []int32
@@ -279,8 +280,8 @@ type state struct {
279280
// Used to deduplicate panic calls.
280281
panics map[funcLine]*ssa.Block
281282

282-
// list of FwdRef values.
283-
fwdRefs []*ssa.Value
283+
fwdRefs []*ssa.Value // list of FwdRef values
284+
reachable []bool // reachable[b.ID] is whether b.ID is reachable; used during fwdRef resolution
284285

285286
// list of PPARAMOUT (return) variables. Does not include PPARAM|PHEAP vars.
286287
returns []*Node
@@ -3741,6 +3742,13 @@ func (s *state) mem() *ssa.Value {
37413742
return s.variable(&memVar, ssa.TypeMem)
37423743
}
37433744

3745+
func (s *state) deadval() *ssa.Value {
3746+
if s.dead == nil {
3747+
s.dead = s.entryNewValue0(ssa.OpUnknown, nil) // type doesn't matter
3748+
}
3749+
return s.dead
3750+
}
3751+
37443752
func (s *state) linkForwardReferences() {
37453753
// Build SSA graph. Each variable on its first use in a basic block
37463754
// leaves a FwdRef in that block representing the incoming value
@@ -3753,11 +3761,19 @@ func (s *state) linkForwardReferences() {
37533761
// completely built. That way we can avoid the notion of "sealed"
37543762
// blocks.
37553763
// - Phi optimization is a separate pass (in ../ssa/phielim.go).
3764+
s.reachable = ssa.ReachableBlocks(s.f)
37563765
for len(s.fwdRefs) > 0 {
37573766
v := s.fwdRefs[len(s.fwdRefs)-1]
37583767
s.fwdRefs = s.fwdRefs[:len(s.fwdRefs)-1]
3759-
s.resolveFwdRef(v)
3768+
if s.reachable[v.Block.ID] {
3769+
s.resolveFwdRef(v)
3770+
} else {
3771+
v.Op = ssa.OpUnknown
3772+
v.Aux = nil
3773+
v.AuxInt = 0
3774+
}
37603775
}
3776+
s.reachable = nil
37613777
}
37623778

37633779
// resolveFwdRef modifies v to be the variable's value at the start of its block.
@@ -3814,6 +3830,9 @@ func (s *state) resolveFwdRef(v *ssa.Value) {
38143830
if a == w {
38153831
continue // already have this witness
38163832
}
3833+
if a.Op == ssa.OpUnknown {
3834+
continue // dead value, ignore
3835+
}
38173836
if w != nil {
38183837
// two witnesses, need a phi value
38193838
v.Op = ssa.OpPhi
@@ -3837,6 +3856,10 @@ func (s *state) lookupVarOutgoing(b *ssa.Block, t ssa.Type, name *Node, line int
38373856
return v
38383857
}
38393858
// The variable is not defined by b and we haven't looked it up yet.
3859+
// If b is dead, don't bother, just return a (re-usable) placeholder.
3860+
if !s.reachable[b.ID] {
3861+
return s.deadval()
3862+
}
38403863
// If b has exactly one predecessor, loop to look it up there.
38413864
// Otherwise, give up and insert a new FwdRef and resolve it later.
38423865
if len(b.Preds) != 1 {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ package ssa
66

77
// findlive returns the reachable blocks and live values in f.
88
func findlive(f *Func) (reachable []bool, live []bool) {
9-
reachable = reachableBlocks(f)
9+
reachable = ReachableBlocks(f)
1010
live = liveValues(f, reachable)
1111
return
1212
}
1313

14-
// reachableBlocks returns the reachable blocks in f.
15-
func reachableBlocks(f *Func) []bool {
14+
// ReachableBlocks returns the reachable blocks in f.
15+
func ReachableBlocks(f *Func) []bool {
1616
reachable := make([]bool, f.NumBlocks())
1717
reachable[f.Entry.ID] = true
1818
p := []*Block{f.Entry} // stack-like worklist
@@ -94,7 +94,7 @@ func deadcode(f *Func) {
9494
}
9595

9696
// Find reachable blocks.
97-
reachable := reachableBlocks(f)
97+
reachable := ReachableBlocks(f)
9898

9999
// Get rid of edges from dead to live code.
100100
for _, b := range f.Blocks {

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,9 @@ func (v *Value) LongHTML() string {
352352
// maybe we could replace some of that with formatting.
353353
s := fmt.Sprintf("<span class=\"%s ssa-long-value\">", v.String())
354354
s += fmt.Sprintf("%s = %s", v.HTML(), v.Op.String())
355-
s += " &lt;" + html.EscapeString(v.Type.String()) + "&gt;"
355+
if v.Type != nil {
356+
s += " &lt;" + html.EscapeString(v.Type.String()) + "&gt;"
357+
}
356358
s += html.EscapeString(v.auxString())
357359
for _, a := range v.Args {
358360
s += fmt.Sprintf(" %s", a.HTML())

0 commit comments

Comments
 (0)