github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/ssa/layout.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 // layout orders basic blocks in f with the goal of minimizing control flow instructions. 8 // After this phase returns, the order of f.Blocks matters and is the order 9 // in which those blocks will appear in the assembly output. 10 func layout(f *Func) { 11 order := make([]*Block, 0, f.NumBlocks()) 12 scheduled := make([]bool, f.NumBlocks()) 13 idToBlock := make([]*Block, f.NumBlocks()) 14 indegree := make([]int, f.NumBlocks()) 15 posdegree := f.newSparseSet(f.NumBlocks()) // blocks with positive remaining degree 16 defer f.retSparseSet(posdegree) 17 zerodegree := f.newSparseSet(f.NumBlocks()) // blocks with zero remaining degree 18 defer f.retSparseSet(zerodegree) 19 20 // Initialize indegree of each block 21 for _, b := range f.Blocks { 22 idToBlock[b.ID] = b 23 indegree[b.ID] = len(b.Preds) 24 if len(b.Preds) == 0 { 25 zerodegree.add(b.ID) 26 } else { 27 posdegree.add(b.ID) 28 } 29 } 30 31 bid := f.Entry.ID 32 blockloop: 33 for { 34 // add block to schedule 35 b := idToBlock[bid] 36 order = append(order, b) 37 scheduled[bid] = true 38 if len(order) == len(f.Blocks) { 39 break 40 } 41 42 for _, e := range b.Succs { 43 c := e.b 44 indegree[c.ID]-- 45 if indegree[c.ID] == 0 { 46 posdegree.remove(c.ID) 47 zerodegree.add(c.ID) 48 } 49 } 50 51 // Pick the next block to schedule 52 // Pick among the successor blocks that have not been scheduled yet. 53 54 // Use likely direction if we have it. 55 var likely *Block 56 switch b.Likely { 57 case BranchLikely: 58 likely = b.Succs[0].b 59 case BranchUnlikely: 60 likely = b.Succs[1].b 61 } 62 if likely != nil && !scheduled[likely.ID] { 63 bid = likely.ID 64 continue 65 } 66 67 // Use degree for now. 68 bid = 0 69 mindegree := f.NumBlocks() 70 for _, e := range order[len(order)-1].Succs { 71 c := e.b 72 if scheduled[c.ID] { 73 continue 74 } 75 if indegree[c.ID] < mindegree { 76 mindegree = indegree[c.ID] 77 bid = c.ID 78 } 79 } 80 if bid != 0 { 81 continue 82 } 83 // TODO: improve this part 84 // No successor of the previously scheduled block works. 85 // Pick a zero-degree block if we can. 86 for zerodegree.size() > 0 { 87 cid := zerodegree.pop() 88 if !scheduled[cid] { 89 bid = cid 90 continue blockloop 91 } 92 } 93 // Still nothing, pick any block. 94 for { 95 cid := posdegree.pop() 96 if !scheduled[cid] { 97 bid = cid 98 continue blockloop 99 } 100 } 101 } 102 f.Blocks = order 103 }