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