1
2
3
4
5 package ssa
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 func loopRotate(f *Func) {
25 loopnest := f.loopnest()
26 if loopnest.hasIrreducible {
27 return
28 }
29 if len(loopnest.loops) == 0 {
30 return
31 }
32
33 idToIdx := f.Cache.allocIntSlice(f.NumBlocks())
34 defer f.Cache.freeIntSlice(idToIdx)
35 for i, b := range f.Blocks {
36 idToIdx[b.ID] = i
37 }
38
39
40 move := map[ID]struct{}{}
41
42
43
44 after := map[ID][]*Block{}
45
46
47 for _, loop := range loopnest.loops {
48 b := loop.header
49 var p *Block
50 for _, e := range b.Preds {
51 if e.b.Kind != BlockPlain {
52 continue
53 }
54 if loopnest.b2l[e.b.ID] != loop {
55 continue
56 }
57 p = e.b
58 }
59 if p == nil {
60 continue
61 }
62 p.Hotness |= HotInitial
63 if f.IsPgoHot {
64 p.Hotness |= HotPgo
65 }
66
67 if p == b {
68 continue
69 }
70 p.Hotness |= HotNotFlowIn
71
72
73 after[p.ID] = []*Block{b}
74 for {
75 nextIdx := idToIdx[b.ID] + 1
76 if nextIdx >= len(f.Blocks) {
77 break
78 }
79 nextb := f.Blocks[nextIdx]
80 if nextb == p {
81 break
82 }
83 if loopnest.b2l[nextb.ID] == loop {
84 after[p.ID] = append(after[p.ID], nextb)
85 }
86 b = nextb
87 }
88
89 f.Blocks[idToIdx[loop.header.ID]] = p
90 f.Blocks[idToIdx[p.ID]] = loop.header
91 idToIdx[loop.header.ID], idToIdx[p.ID] = idToIdx[p.ID], idToIdx[loop.header.ID]
92
93
94 for _, b := range after[p.ID] {
95 move[b.ID] = struct{}{}
96 }
97 }
98
99
100
101
102
103 j := 0
104
105
106
107 oldOrder := f.Cache.allocBlockSlice(len(f.Blocks))
108 defer f.Cache.freeBlockSlice(oldOrder)
109 copy(oldOrder, f.Blocks)
110 for _, b := range oldOrder {
111 if _, ok := move[b.ID]; ok {
112 continue
113 }
114 f.Blocks[j] = b
115 j++
116 for _, a := range after[b.ID] {
117 f.Blocks[j] = a
118 j++
119 }
120 }
121 if j != len(oldOrder) {
122 f.Fatalf("bad reordering in looprotate")
123 }
124 }
125
View as plain text