...
Source file src/pkg/cmd/compile/internal/ssa/flagalloc.go
1
2
3
4
5 package ssa
6
7
8
9
10 func flagalloc(f *Func) {
11
12
13
14 end := make([]*Value, f.NumBlocks())
15 po := f.postorder()
16 for n := 0; n < 2; n++ {
17 for _, b := range po {
18
19
20
21 flag := end[b.ID]
22 if b.Control != nil && b.Control.Type.IsFlags() {
23 flag = b.Control
24 }
25 for j := len(b.Values) - 1; j >= 0; j-- {
26 v := b.Values[j]
27 if v == flag {
28 flag = nil
29 }
30 if v.clobbersFlags() {
31 flag = nil
32 }
33 for _, a := range v.Args {
34 if a.Type.IsFlags() {
35 flag = a
36 }
37 }
38 }
39 if flag != nil {
40 for _, e := range b.Preds {
41 p := e.b
42 end[p.ID] = flag
43 }
44 }
45 }
46 }
47
48
49
50
51 for _, b := range f.Blocks {
52 v := b.Control
53 if v != nil && v.Type.IsFlags() && end[b.ID] != v {
54 end[b.ID] = nil
55 }
56 if b.Kind == BlockDefer {
57
58 end[b.ID] = nil
59 }
60 }
61
62
63 spill := map[ID]bool{}
64 for _, b := range f.Blocks {
65 var flag *Value
66 if len(b.Preds) > 0 {
67 flag = end[b.Preds[0].b.ID]
68 }
69 for _, v := range b.Values {
70 for _, a := range v.Args {
71 if !a.Type.IsFlags() {
72 continue
73 }
74 if a == flag {
75 continue
76 }
77
78 spill[a.ID] = true
79 flag = a
80 }
81 if v.clobbersFlags() {
82 flag = nil
83 }
84 if v.Type.IsFlags() {
85 flag = v
86 }
87 }
88 if v := b.Control; v != nil && v != flag && v.Type.IsFlags() {
89 spill[v.ID] = true
90 }
91 if v := end[b.ID]; v != nil && v != flag {
92 spill[v.ID] = true
93 }
94 }
95
96
97
98 var oldSched []*Value
99 for _, b := range f.Blocks {
100 oldSched = append(oldSched[:0], b.Values...)
101 b.Values = b.Values[:0]
102
103 var flag *Value
104 if len(b.Preds) > 0 {
105 flag = end[b.Preds[0].b.ID]
106
107 for _, e := range b.Preds[1:] {
108 p := e.b
109 if end[p.ID] != flag {
110 f.Fatalf("live flag in %s's predecessors not consistent", b)
111 }
112 }
113 }
114 for _, v := range oldSched {
115 if v.Op == OpPhi && v.Type.IsFlags() {
116 f.Fatalf("phi of flags not supported: %s", v.LongString())
117 }
118
119
120
121 if spill[v.ID] && v.MemoryArg() != nil {
122 if !f.Config.splitLoad(v) {
123 f.Fatalf("can't split flag generator: %s", v.LongString())
124 }
125 }
126
127
128
129 for i, a := range v.Args {
130 if !a.Type.IsFlags() {
131 continue
132 }
133 if a == flag {
134 continue
135 }
136
137 c := copyFlags(a, b)
138
139 v.SetArg(i, c)
140
141 flag = a
142 }
143
144 b.Values = append(b.Values, v)
145 if v.clobbersFlags() {
146 flag = nil
147 }
148 if v.Type.IsFlags() {
149 flag = v
150 }
151 }
152 if v := b.Control; v != nil && v != flag && v.Type.IsFlags() {
153
154 c := copyFlags(v, b)
155 b.SetControl(c)
156 flag = v
157 }
158 if v := end[b.ID]; v != nil && v != flag {
159
160
161 copyFlags(v, b)
162
163
164
165
166
167 }
168 }
169
170
171 for _, b := range f.Blocks {
172 b.FlagsLiveAtEnd = end[b.ID] != nil
173 }
174 }
175
176 func (v *Value) clobbersFlags() bool {
177 if opcodeTable[v.Op].clobberFlags {
178 return true
179 }
180 if v.Type.IsTuple() && (v.Type.FieldType(0).IsFlags() || v.Type.FieldType(1).IsFlags()) {
181
182
183
184 return true
185 }
186 return false
187 }
188
189
190
191 func copyFlags(v *Value, b *Block) *Value {
192 flagsArgs := make(map[int]*Value)
193 for i, a := range v.Args {
194 if a.Type.IsFlags() || a.Type.IsTuple() {
195 flagsArgs[i] = copyFlags(a, b)
196 }
197 }
198 c := v.copyInto(b)
199 for i, a := range flagsArgs {
200 c.SetArg(i, a)
201 }
202 return c
203 }
204
View as plain text