Skip to content

Commit 9fd9a54

Browse files
committed
keep adjacent chains close together
1 parent 2611f3d commit 9fd9a54

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,13 @@ blockloop:
198198
// its own chain, then starting from hottest edge and repeatedly merge two proper
199199
// chains iff the edge dest is the first block of dest chain and edge src is the
200200
// last block of src chain. Once all edges are processed, the chains are sorted
201-
// by hottness and merge count and generate final block order.
201+
// by hottness and merge count and generate final block order. The algorithm is
202+
// summarized as follows:
203+
// - Initially every block is in its own chain.
204+
// - Sort edges by weight and move slow path to end.
205+
// - Merge proper chains until no more chains can be merged.
206+
// - Sort chains by hottness and priority.
207+
// - Generate final block order.
202208

203209
// chain is a linear sequence of blocks, where the first block is the entry block
204210
// and the last block is the exit block. The chain is used to represent a sequence
@@ -261,7 +267,7 @@ func (g *chainGraph) mergeChain(from, to *chain) {
261267
g.b2chain[block.ID] = to
262268
}
263269
to.blocks = append(to.blocks, from.blocks...)
264-
to.priority++ // increment
270+
to.priority++
265271
g.chains[from.id-1 /*ID always >0*/] = nil
266272
}
267273

@@ -277,6 +283,12 @@ func (g *chainGraph) print() {
277283
}
278284
fmt.Printf("id:%d priority:%d blocks:%v\n", ch.id, ch.priority, ch.blocks)
279285
}
286+
fmt.Printf("== BlockOrder:\n")
287+
blockOrder := make([]*Block, 0)
288+
for _, chain := range g.chains {
289+
blockOrder = append(blockOrder, chain.blocks...)
290+
}
291+
fmt.Printf("%v\n", blockOrder)
280292
}
281293

282294
func greedyBlockOrder(fn *Func) []*Block {
@@ -328,8 +340,11 @@ func greedyBlockOrder(fn *Func) []*Block {
328340
for _, edge := range graph.edges {
329341
c1 := graph.getChain(edge.src)
330342
c2 := graph.getChain(edge.dst)
331-
// [c1] edge [c2] ? Then merge c1 into c2 and remove entire c1 then
332-
if c1 != c2 && (edge.dst == c2.first() && edge.src == c1.last()) {
343+
if c1 == c2 {
344+
continue
345+
}
346+
// [..c1..] edge [..c2..] ? Then merge c1 into c2 and remove entire c1 then
347+
if edge.dst == c2.first() && edge.src == c1.last() {
333348
if fn.pass.debug > 2 {
334349
fmt.Printf("process %v merge %v to %v\n",
335350
edge, c2.blocks, c1.blocks)
@@ -383,6 +398,10 @@ func greedyBlockOrder(fn *Func) []*Block {
383398
if c1.priority != c2.priority {
384399
return c1.priority > c2.priority
385400
}
401+
// Keep adjacent chains close together
402+
if c1.id > c2.id {
403+
return false
404+
}
386405
// Non-terminated chain is considered
387406
if s1, s2 := len(c1.last().Succs), len(c2.last().Succs); s1 != s2 {
388407
return s1 > s2

0 commit comments

Comments
 (0)