1
2
3
4
5 package ssa
6
7
8
9
10
11
12 func tighten(f *Func) {
13 canMove := make([]bool, f.NumValues())
14 for _, b := range f.Blocks {
15 for _, v := range b.Values {
16 if v.Op.isLoweredGetClosurePtr() {
17
18 continue
19 }
20 switch v.Op {
21 case OpPhi, OpArg, OpArgIntReg, OpArgFloatReg, OpSelect0, OpSelect1, OpSelectN:
22
23
24
25
26 continue
27 }
28 if v.MemoryArg() != nil {
29
30
31 continue
32 }
33
34 narg := 0
35 for _, a := range v.Args {
36 if !a.rematerializeable() {
37 narg++
38 }
39 }
40 if narg >= 2 && !v.Type.IsFlags() {
41
42
43
44
45 continue
46 }
47 canMove[v.ID] = true
48 }
49 }
50
51
52 lca := makeLCArange(f)
53
54
55 target := make([]*Block, f.NumValues())
56
57
58
59 idom := f.Idom()
60 loops := f.loopnest()
61 loops.calculateDepths()
62
63 changed := true
64 for changed {
65 changed = false
66
67
68 for i := range target {
69 target[i] = nil
70 }
71
72
73
74 for _, b := range f.Blocks {
75 for _, v := range b.Values {
76 for i, a := range v.Args {
77 if !canMove[a.ID] {
78 continue
79 }
80 use := b
81 if v.Op == OpPhi {
82 use = b.Preds[i].b
83 }
84 if target[a.ID] == nil {
85 target[a.ID] = use
86 } else {
87 target[a.ID] = lca.find(target[a.ID], use)
88 }
89 }
90 }
91 for _, c := range b.ControlValues() {
92 if !canMove[c.ID] {
93 continue
94 }
95 if target[c.ID] == nil {
96 target[c.ID] = b
97 } else {
98 target[c.ID] = lca.find(target[c.ID], b)
99 }
100 }
101 }
102
103
104
105 for _, b := range f.Blocks {
106 origloop := loops.b2l[b.ID]
107 for _, v := range b.Values {
108 t := target[v.ID]
109 if t == nil {
110 continue
111 }
112 targetloop := loops.b2l[t.ID]
113 for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
114 t = idom[targetloop.header.ID]
115 target[v.ID] = t
116 targetloop = loops.b2l[t.ID]
117 }
118 }
119 }
120
121
122 for _, b := range f.Blocks {
123 for i := 0; i < len(b.Values); i++ {
124 v := b.Values[i]
125 t := target[v.ID]
126 if t == nil || t == b {
127
128 continue
129 }
130
131 t.Values = append(t.Values, v)
132 v.Block = t
133 last := len(b.Values) - 1
134 b.Values[i] = b.Values[last]
135 b.Values[last] = nil
136 b.Values = b.Values[:last]
137 changed = true
138 i--
139 }
140 }
141 }
142 }
143
144
145
146
147 func phiTighten(f *Func) {
148 for _, b := range f.Blocks {
149 for _, v := range b.Values {
150 if v.Op != OpPhi {
151 continue
152 }
153 for i, a := range v.Args {
154 if !a.rematerializeable() {
155 continue
156 }
157 if a.Block == b.Preds[i].b {
158 continue
159 }
160
161 v.SetArg(i, a.copyInto(b.Preds[i].b))
162 }
163 }
164 }
165 }
166
View as plain text