...
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 || p == b {
60 continue
61 }
62 after[p.ID] = []*Block{b}
63 for {
64 nextIdx := idToIdx[b.ID] + 1
65 if nextIdx >= len(f.Blocks) {
66 break
67 }
68 nextb := f.Blocks[nextIdx]
69 if nextb == p {
70 break
71 }
72 if loopnest.b2l[nextb.ID] == loop {
73 after[p.ID] = append(after[p.ID], nextb)
74 }
75 b = nextb
76 }
77
78 f.Blocks[idToIdx[loop.header.ID]] = p
79 f.Blocks[idToIdx[p.ID]] = loop.header
80 idToIdx[loop.header.ID], idToIdx[p.ID] = idToIdx[p.ID], idToIdx[loop.header.ID]
81
82
83 for _, b := range after[p.ID] {
84 move[b.ID] = struct{}{}
85 }
86 }
87
88
89
90
91
92 j := 0
93
94
95
96 oldOrder := f.Cache.allocBlockSlice(len(f.Blocks))
97 defer f.Cache.freeBlockSlice(oldOrder)
98 copy(oldOrder, f.Blocks)
99 for _, b := range oldOrder {
100 if _, ok := move[b.ID]; ok {
101 continue
102 }
103 f.Blocks[j] = b
104 j++
105 for _, a := range after[b.ID] {
106 f.Blocks[j] = a
107 j++
108 }
109 }
110 if j != len(oldOrder) {
111 f.Fatalf("bad reordering in looprotate")
112 }
113 }
114
View as plain text