@@ -198,7 +198,13 @@ blockloop:
198
198
// its own chain, then starting from hottest edge and repeatedly merge two proper
199
199
// chains iff the edge dest is the first block of dest chain and edge src is the
200
200
// 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.
202
208
203
209
// chain is a linear sequence of blocks, where the first block is the entry block
204
210
// 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) {
261
267
g .b2chain [block .ID ] = to
262
268
}
263
269
to .blocks = append (to .blocks , from .blocks ... )
264
- to .priority ++ // increment
270
+ to .priority ++
265
271
g .chains [from .id - 1 /*ID always >0*/ ] = nil
266
272
}
267
273
@@ -277,6 +283,12 @@ func (g *chainGraph) print() {
277
283
}
278
284
fmt .Printf ("id:%d priority:%d blocks:%v\n " , ch .id , ch .priority , ch .blocks )
279
285
}
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 )
280
292
}
281
293
282
294
func greedyBlockOrder (fn * Func ) []* Block {
@@ -328,8 +340,11 @@ func greedyBlockOrder(fn *Func) []*Block {
328
340
for _ , edge := range graph .edges {
329
341
c1 := graph .getChain (edge .src )
330
342
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 () {
333
348
if fn .pass .debug > 2 {
334
349
fmt .Printf ("process %v merge %v to %v\n " ,
335
350
edge , c2 .blocks , c1 .blocks )
@@ -383,6 +398,10 @@ func greedyBlockOrder(fn *Func) []*Block {
383
398
if c1 .priority != c2 .priority {
384
399
return c1 .priority > c2 .priority
385
400
}
401
+ // Keep adjacent chains close together
402
+ if c1 .id > c2 .id {
403
+ return false
404
+ }
386
405
// Non-terminated chain is considered
387
406
if s1 , s2 := len (c1 .last ().Succs ), len (c2 .last ().Succs ); s1 != s2 {
388
407
return s1 > s2
0 commit comments