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 := make([]int, f.NumBlocks())
34 for i, b := range f.Blocks {
35 idToIdx[b.ID] = i
36 }
37
38
39 move := map[ID]struct{}{}
40
41
42
43 after := map[ID][]*Block{}
44
45
46 for _, loop := range loopnest.loops {
47 b := loop.header
48 var p *Block
49 for _, e := range b.Preds {
50 if e.b.Kind != BlockPlain {
51 continue
52 }
53 if loopnest.b2l[e.b.ID] != loop {
54 continue
55 }
56 p = e.b
57 }
58 if p == nil || p == b {
59 continue
60 }
61 after[p.ID] = []*Block{b}
62 for {
63 nextIdx := idToIdx[b.ID] + 1
64 if nextIdx >= len(f.Blocks) {
65 break
66 }
67 nextb := f.Blocks[nextIdx]
68 if nextb == p {
69 break
70 }
71 if loopnest.b2l[nextb.ID] == loop {
72 after[p.ID] = append(after[p.ID], nextb)
73 }
74 b = nextb
75 }
76
77 f.Blocks[idToIdx[loop.header.ID]] = p
78 f.Blocks[idToIdx[p.ID]] = loop.header
79 idToIdx[loop.header.ID], idToIdx[p.ID] = idToIdx[p.ID], idToIdx[loop.header.ID]
80
81
82 for _, b := range after[p.ID] {
83 move[b.ID] = struct{}{}
84 }
85 }
86
87
88
89
90
91 j := 0
92
93
94
95 newOrder := make([]*Block, 0, f.NumBlocks())
96 for _, b := range f.Blocks {
97 if _, ok := move[b.ID]; ok {
98 continue
99 }
100 newOrder = append(newOrder, b)
101 j++
102 for _, a := range after[b.ID] {
103 newOrder = append(newOrder, a)
104 j++
105 }
106 }
107 if j != len(f.Blocks) {
108 f.Fatalf("bad reordering in looprotate")
109 }
110 f.Blocks = newOrder
111 }
112
View as plain text