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
25
26
27
28
29
30
31
32
33
34
35
36 func licm(f *Func) {
37
38 nest := loopnestfor(f)
39 if len(nest.loops) == 0 || nest.hasIrreducible {
40 return
41 }
42
43 uses := uses(f)
44 defer uses.free(f)
45
46 loopDependent := f.Cache.allocBoolSlice(f.NumValues())
47 defer f.Cache.freeBoolSlice(loopDependent)
48 queue := f.Cache.allocValueSlice(f.NumValues())
49 defer f.Cache.freeValueSlice(queue)
50 queue = queue[:0]
51
52
53 for _, b := range f.Blocks {
54 if loop := nest.b2l[b.ID]; loop == nil || !loop.isInner {
55
56
57 continue
58 }
59 for _, v := range b.Values {
60 if opcodeTable[v.Op].earlyOk {
61
62 if v.Type.IsMemory() || opcodeTable[v.Op].nilCheck || opcodeTable[v.Op].hasSideEffects || v.MemoryArg() != nil {
63 v.Fatalf("op %s has bad earlyOk mark", v.Op)
64 }
65 if !v.Type.IsPtr() {
66
67
68
69 continue
70 }
71 }
72 if v.Op == OpSelect0 || v.Op == OpSelect1 {
73
74 continue
75 }
76 loopDependent[v.ID] = true
77 queue = append(queue, v)
78 }
79 }
80
81
82
83
84 for len(queue) > 0 {
85 v := queue[len(queue)-1]
86 queue = queue[:len(queue)-1]
87
88 for _, u := range uses.get(v) {
89 if loop := nest.b2l[u.Block.ID]; loop == nil || !loop.isInner {
90 continue
91 }
92 if loopDependent[u.ID] {
93 continue
94 }
95 loopDependent[u.ID] = true
96 queue = append(queue, u)
97 }
98 }
99
100
101 for _, b := range f.Blocks {
102 loop := nest.b2l[b.ID]
103 if loop == nil || !loop.isInner {
104
105
106
107 continue
108 }
109 if len(loop.header.Preds) != 2 {
110 continue
111 }
112 anyMoved := false
113 for i, v := range b.Values {
114 if loopDependent[v.ID] {
115 continue
116 }
117
118 h := loop.header
119 var inIdx int
120 if int(h.Preds[0].b.ID) >= len(nest.b2l) || nest.b2l[h.Preds[0].b.ID] != loop {
121 inIdx = 0
122 } else {
123 inIdx = 1
124 }
125 dest := h.Preds[inIdx].b
126 if dest.Kind != BlockPlain {
127 outIdx := h.Preds[inIdx].i
128
129
130 mid := f.NewBlock(BlockPlain)
131 mid.Pos = dest.Pos
132
133 mid.Preds = append(mid.Preds, Edge{dest, outIdx})
134 mid.Succs = append(mid.Succs, Edge{h, inIdx})
135 h.Preds[inIdx] = Edge{mid, 0}
136 dest.Succs[outIdx] = Edge{mid, 0}
137
138 dest = mid
139 }
140
141 b.Values[i] = nil
142 v.Block = dest
143 dest.Values = append(dest.Values, v)
144 anyMoved = true
145 }
146 if anyMoved {
147
148 i := 0
149 for _, v := range b.Values {
150 if v == nil {
151 continue
152 }
153 b.Values[i] = v
154 i++
155 }
156 b.Values = b.Values[:i]
157 }
158 }
159 }
160
View as plain text